From b84b6b23fa58beb5674b37279742eb65461ca076 Mon Sep 17 00:00:00 2001 From: YamaArashi Date: Thu, 11 Feb 2016 01:12:34 -0800 Subject: delete irrelevant configs --- gcc/config/1750a/1750a.c | 734 -- gcc/config/1750a/1750a.h | 1348 ---- gcc/config/1750a/1750a.md | 1436 ---- gcc/config/1750a/ms1750.inc | 158 - gcc/config/1750a/xm-1750a.h | 23 - gcc/config/README | 5 - gcc/config/a29k/a29k.c | 1538 ---- gcc/config/a29k/a29k.h | 1673 ----- gcc/config/a29k/a29k.md | 2874 -------- gcc/config/a29k/t-a29k | 5 - gcc/config/a29k/t-a29kbare | 19 - gcc/config/a29k/t-vx29k | 17 - gcc/config/a29k/udi.h | 94 - gcc/config/a29k/unix.h | 92 - gcc/config/a29k/vx29k.h | 46 - gcc/config/a29k/x-unix | 2 - gcc/config/a29k/xm-a29k.h | 41 - gcc/config/a29k/xm-unix.h | 43 - gcc/config/alpha/alpha.c | 5101 ------------- gcc/config/alpha/alpha.h | 2518 ------- gcc/config/alpha/alpha.md | 5313 -------------- gcc/config/alpha/config-nt.sed | 33 - gcc/config/alpha/crtbegin.asm | 192 - gcc/config/alpha/crtend.asm | 108 - gcc/config/alpha/elf.h | 527 -- gcc/config/alpha/lib1funcs.asm | 327 - gcc/config/alpha/linux-ecoff.h | 37 - gcc/config/alpha/linux-elf.h | 48 - gcc/config/alpha/linux.h | 46 - gcc/config/alpha/netbsd-elf.h | 32 - gcc/config/alpha/netbsd.h | 39 - gcc/config/alpha/osf.h | 127 - gcc/config/alpha/osf12.h | 33 - gcc/config/alpha/osf2or3.h | 30 - gcc/config/alpha/t-crtbe | 9 - gcc/config/alpha/t-linux | 5 - gcc/config/alpha/t-vms | 6 - gcc/config/alpha/va_list.h | 16 - gcc/config/alpha/vms-tramp.asm | 22 - gcc/config/alpha/vms.h | 510 -- gcc/config/alpha/vxworks.h | 51 - gcc/config/alpha/win-nt.h | 129 - gcc/config/alpha/x-alpha | 2 - gcc/config/alpha/xm-alpha.h | 76 - gcc/config/alpha/xm-linux.h | 2 - gcc/config/alpha/xm-vms.h | 93 - gcc/config/alpha/xm-winnt.h | 34 - gcc/config/aoutos.h | 88 - gcc/config/arc/arc.c | 2203 ------ gcc/config/arc/arc.h | 1642 ----- gcc/config/arc/arc.md | 1630 ----- gcc/config/arc/initfini.c | 157 - gcc/config/arc/lib1funcs.asm | 273 - gcc/config/arc/t-arc | 72 - gcc/config/arc/xm-arc.h | 47 - gcc/config/c4x/c4x.c | 4341 ----------- gcc/config/c4x/c4x.h | 2671 ------- gcc/config/c4x/c4x.md | 6877 ------------------ gcc/config/c4x/libgcc.S | 1501 ---- gcc/config/c4x/t-c4x | 22 - gcc/config/c4x/xm-c4x.h | 21 - gcc/config/clipper/clipper.c | 508 -- gcc/config/clipper/clipper.h | 1125 --- gcc/config/clipper/clipper.md | 1421 ---- gcc/config/clipper/clix.h | 162 - gcc/config/clipper/x-clix | 1 - gcc/config/clipper/xm-clix.h | 30 - gcc/config/convex/convex.c | 675 -- gcc/config/convex/convex.h | 1503 ---- gcc/config/convex/convex.md | 1885 ----- gcc/config/convex/fixinc.convex | 416 -- gcc/config/convex/x-convex | 5 - gcc/config/convex/xm-convex.h | 48 - gcc/config/d10v/abi | 131 - gcc/config/d10v/d10v.c | 3880 ---------- gcc/config/d10v/d10v.h | 5065 ------------- gcc/config/d10v/d10v.md | 3758 ---------- gcc/config/d10v/libgcc1.asm | 556 -- gcc/config/d10v/scrt0.asm | 45 - gcc/config/d10v/sim.asm | 81 - gcc/config/d10v/t-d10v | 30 - gcc/config/d10v/xm-d10v.h | 77 - gcc/config/d30v/abi | 234 - gcc/config/d30v/d30v.c | 3514 --------- gcc/config/d30v/d30v.h | 6245 ---------------- gcc/config/d30v/d30v.md | 3910 ---------- gcc/config/d30v/libgcc1.asm | 193 - gcc/config/d30v/t-d30v | 36 - gcc/config/d30v/xm-d30v.h | 199 - gcc/config/dbx.h | 30 - gcc/config/dbxcoff.h | 87 - gcc/config/dsp16xx/dsp16xx.c | 2241 ------ gcc/config/dsp16xx/dsp16xx.h | 1972 ----- gcc/config/dsp16xx/dsp16xx.md | 2171 ------ gcc/config/dsp16xx/xm-dsp16xx.h | 46 - gcc/config/elfos.h | 754 -- gcc/config/elxsi/elxsi.c | 127 - gcc/config/elxsi/elxsi.h | 967 --- gcc/config/elxsi/elxsi.md | 1420 ---- gcc/config/elxsi/x-elxsi | 9 - gcc/config/elxsi/xm-elxsi.h | 38 - gcc/config/float-d10v.h | 131 - gcc/config/float-i128.h | 96 - gcc/config/float-i32.h | 96 - gcc/config/float-i386.h | 104 - gcc/config/float-m68k.h | 97 - gcc/config/float-sh.h | 130 - gcc/config/float-vax.h | 96 - gcc/config/fr30/crti.asm | 75 - gcc/config/fr30/crtn.asm | 57 - gcc/config/fr30/fr30.c | 804 --- gcc/config/fr30/fr30.h | 4496 ------------ gcc/config/fr30/fr30.md | 1404 ---- gcc/config/fr30/lib1funcs.asm | 126 - gcc/config/fr30/t-fr30 | 47 - gcc/config/fr30/xm-fr30.h | 49 - gcc/config/fx80/fx80.c | 300 - gcc/config/fx80/fx80.h | 1446 ---- gcc/config/fx80/fx80.md | 2516 ------- gcc/config/fx80/xm-fx80.h | 39 - gcc/config/gmicro/gmicro.c | 982 --- gcc/config/gmicro/gmicro.h | 1588 ---- gcc/config/gmicro/gmicro.md | 2738 ------- gcc/config/gnu.h | 23 - gcc/config/gofast.h | 96 - gcc/config/h8300/h8300.c | 3143 -------- gcc/config/h8300/h8300.h | 1413 ---- gcc/config/h8300/h8300.md | 2291 ------ gcc/config/h8300/lib1funcs.asm | 781 -- gcc/config/h8300/t-h8300 | 27 - gcc/config/h8300/xm-h8300.h | 46 - gcc/config/i370/i370.c | 584 -- gcc/config/i370/i370.h | 1440 ---- gcc/config/i370/i370.md | 4210 ----------- gcc/config/i370/t-i370 | 4 - gcc/config/i370/xm-i370.h | 53 - gcc/config/i386/386bsd.h | 76 - gcc/config/i386/aix386.h | 69 - gcc/config/i386/aix386ng.h | 140 - gcc/config/i386/att.h | 93 - gcc/config/i386/bsd.h | 128 - gcc/config/i386/bsd386.h | 33 - gcc/config/i386/config-nt.sed | 38 - gcc/config/i386/crtdll.h | 42 - gcc/config/i386/cygwin.asm | 32 - gcc/config/i386/cygwin.h | 504 -- gcc/config/i386/dgux.c | 192 - gcc/config/i386/dgux.h | 266 - gcc/config/i386/freebsd-elf.h | 200 - gcc/config/i386/freebsd.h | 268 - gcc/config/i386/gas.h | 161 - gcc/config/i386/gmon-sol2.c | 409 -- gcc/config/i386/gnu.h | 23 - gcc/config/i386/go32-rtems.h | 40 - gcc/config/i386/go32.h | 148 - gcc/config/i386/gstabs.h | 9 - gcc/config/i386/i386-aout.h | 34 - gcc/config/i386/i386-coff.h | 103 - gcc/config/i386/i386.c | 5591 -------------- gcc/config/i386/i386.h | 2760 ------- gcc/config/i386/i386.md | 7732 -------------------- gcc/config/i386/i386elf.h | 294 - gcc/config/i386/isc.h | 96 - gcc/config/i386/isccoff.h | 12 - gcc/config/i386/iscdbx.h | 43 - gcc/config/i386/linux-aout.h | 74 - gcc/config/i386/linux-oldld.h | 75 - gcc/config/i386/linux.h | 235 - gcc/config/i386/lynx-ng.h | 37 - gcc/config/i386/lynx.h | 39 - gcc/config/i386/mach.h | 20 - gcc/config/i386/mingw32.h | 95 - gcc/config/i386/moss.h | 35 - gcc/config/i386/netbsd.h | 85 - gcc/config/i386/netware.h | 40 - gcc/config/i386/next.h | 233 - gcc/config/i386/os2.h | 76 - gcc/config/i386/osf1-ci.asm | 65 - gcc/config/i386/osf1-cn.asm | 46 - gcc/config/i386/osf1elf.h | 260 - gcc/config/i386/osf1elfgdb.h | 7 - gcc/config/i386/osfelf.h | 79 - gcc/config/i386/osfrose.h | 918 --- gcc/config/i386/perform.h | 98 - gcc/config/i386/ptx4-i.h | 247 - gcc/config/i386/rtems.h | 34 - gcc/config/i386/rtemself.h | 169 - gcc/config/i386/sco.h | 117 - gcc/config/i386/sco4.h | 86 - gcc/config/i386/sco4dbx.h | 81 - gcc/config/i386/sco5.h | 974 --- gcc/config/i386/sco5gas.h | 24 - gcc/config/i386/scodbx.h | 92 - gcc/config/i386/seq-gas.h | 46 - gcc/config/i386/seq-sysv3.h | 42 - gcc/config/i386/seq2-sysv3.h | 8 - gcc/config/i386/sequent.h | 151 - gcc/config/i386/sol2-c1.asm | 156 - gcc/config/i386/sol2-ci.asm | 51 - gcc/config/i386/sol2-cn.asm | 46 - gcc/config/i386/sol2-gc1.asm | 160 - gcc/config/i386/sol2.h | 98 - gcc/config/i386/sol2dbg.h | 27 - gcc/config/i386/sun.h | 83 - gcc/config/i386/sun386.h | 142 - gcc/config/i386/svr3.ifile | 48 - gcc/config/i386/svr3dbx.h | 83 - gcc/config/i386/svr3gas.h | 293 - gcc/config/i386/svr3z.ifile | 48 - gcc/config/i386/sysv3.h | 124 - gcc/config/i386/sysv4.h | 253 - gcc/config/i386/t-crtpic | 16 - gcc/config/i386/t-crtstuff | 2 - gcc/config/i386/t-cygwin | 16 - gcc/config/i386/t-dgux | 4 - gcc/config/i386/t-freebsd | 5 - gcc/config/i386/t-go32 | 2 - gcc/config/i386/t-i386bare | 3 - gcc/config/i386/t-i386elf | 8 - gcc/config/i386/t-mingw32 | 4 - gcc/config/i386/t-netware | 6 - gcc/config/i386/t-next | 12 - gcc/config/i386/t-osf | 2 - gcc/config/i386/t-osf1elf | 18 - gcc/config/i386/t-sco5 | 16 - gcc/config/i386/t-sco5gas | 16 - gcc/config/i386/t-sol2 | 40 - gcc/config/i386/t-svr3dbx | 7 - gcc/config/i386/t-svr4 | 17 - gcc/config/i386/t-udk | 2 - gcc/config/i386/t-vsta | 2 - gcc/config/i386/t-winnt | 6 - gcc/config/i386/udk.h | 35 - gcc/config/i386/unix.h | 190 - gcc/config/i386/v3gas.h | 80 - gcc/config/i386/vsta.h | 78 - gcc/config/i386/vxi386.h | 23 - gcc/config/i386/win-nt.h | 150 - gcc/config/i386/win32.h | 280 - gcc/config/i386/winnt.c | 570 -- gcc/config/i386/x-aix | 12 - gcc/config/i386/x-cygwin | 4 - gcc/config/i386/x-dgux | 11 - gcc/config/i386/x-go32 | 47 - gcc/config/i386/x-isc | 3 - gcc/config/i386/x-isc3 | 4 - gcc/config/i386/x-ncr3000 | 34 - gcc/config/i386/x-next | 3 - gcc/config/i386/x-osf1elf | 8 - gcc/config/i386/x-osfrose | 27 - gcc/config/i386/x-sco | 7 - gcc/config/i386/x-sco4 | 10 - gcc/config/i386/x-sco5 | 10 - gcc/config/i386/x-sysv3 | 1 - gcc/config/i386/x-vsta | 1 - gcc/config/i386/xm-aix.h | 2 - gcc/config/i386/xm-bsd386.h | 3 - gcc/config/i386/xm-cygwin.h | 62 - gcc/config/i386/xm-dgux.h | 12 - gcc/config/i386/xm-dos.h | 14 - gcc/config/i386/xm-freebsd.h | 4 - gcc/config/i386/xm-gnu.h | 5 - gcc/config/i386/xm-go32.h | 36 - gcc/config/i386/xm-isc.h | 4 - gcc/config/i386/xm-linux.h | 24 - gcc/config/i386/xm-lynx.h | 33 - gcc/config/i386/xm-mingw32.h | 42 - gcc/config/i386/xm-netbsd.h | 4 - gcc/config/i386/xm-next.h | 5 - gcc/config/i386/xm-os2.h | 69 - gcc/config/i386/xm-osf.h | 2 - gcc/config/i386/xm-osf1elf.h | 6 - gcc/config/i386/xm-sco.h | 13 - gcc/config/i386/xm-sco5.h | 7 - gcc/config/i386/xm-sun.h | 23 - gcc/config/i386/xm-sysv3.h | 4 - gcc/config/i386/xm-sysv4.h | 5 - gcc/config/i386/xm-vsta.h | 2 - gcc/config/i386/xm-winnt.h | 24 - gcc/config/i860/bsd-gas.h | 2 - gcc/config/i860/bsd.h | 44 - gcc/config/i860/fx2800.h | 356 - gcc/config/i860/i860.c | 2097 ------ gcc/config/i860/i860.h | 1432 ---- gcc/config/i860/i860.md | 2310 ------ gcc/config/i860/mach.h | 14 - gcc/config/i860/paragon.h | 236 - gcc/config/i860/sysv3.h | 174 - gcc/config/i860/sysv4.h | 193 - gcc/config/i860/t-fx2800 | 3 - gcc/config/i860/x-fx2800 | 7 - gcc/config/i860/x-sysv3 | 1 - gcc/config/i860/x-sysv4 | 44 - gcc/config/i860/xm-fx2800.h | 7 - gcc/config/i860/xm-i860.h | 43 - gcc/config/i960/i960-coff.h | 101 - gcc/config/i960/i960.c | 3000 -------- gcc/config/i960/i960.h | 1628 ----- gcc/config/i960/i960.md | 2933 -------- gcc/config/i960/rtems.h | 33 - gcc/config/i960/t-960bare | 24 - gcc/config/i960/t-vxworks960 | 27 - gcc/config/i960/vx960-coff.h | 72 - gcc/config/i960/vx960.h | 30 - gcc/config/i960/xm-i960.h | 43 - gcc/config/libgloss.h | 35 - gcc/config/linux-aout.h | 48 - gcc/config/linux.h | 115 - gcc/config/lynx-ng.h | 118 - gcc/config/lynx.h | 179 - gcc/config/m32r/initfini.c | 169 - gcc/config/m32r/m32r.c | 3323 --------- gcc/config/m32r/m32r.h | 2408 ------- gcc/config/m32r/m32r.md | 2649 ------- gcc/config/m32r/t-m32r | 70 - gcc/config/m32r/xm-m32r.h | 47 - gcc/config/m68k/3b1.h | 513 -- gcc/config/m68k/3b1g.h | 64 - gcc/config/m68k/a-ux.h | 206 - gcc/config/m68k/altos3068.h | 135 - gcc/config/m68k/amix.h | 149 - gcc/config/m68k/apollo68.h | 208 - gcc/config/m68k/atari.h | 106 - gcc/config/m68k/aux-crt1.c | 134 - gcc/config/m68k/aux-crt2.asm | 42 - gcc/config/m68k/aux-crtn.asm | 26 - gcc/config/m68k/aux-exit.c | 99 - gcc/config/m68k/aux-low.gld | 38 - gcc/config/m68k/aux-mcount.c | 69 - gcc/config/m68k/auxas.h | 189 - gcc/config/m68k/auxgas.h | 56 - gcc/config/m68k/auxgld.h | 29 - gcc/config/m68k/auxld.h | 35 - gcc/config/m68k/ccur-GAS.h | 129 - gcc/config/m68k/coff.h | 176 - gcc/config/m68k/crds.h | 621 -- gcc/config/m68k/ctix.h | 48 - gcc/config/m68k/dpx2.h | 822 --- gcc/config/m68k/dpx2.ifile | 55 - gcc/config/m68k/dpx2cdbx.h | 31 - gcc/config/m68k/dpx2g.h | 71 - gcc/config/m68k/fpgnulib.c | 442 -- gcc/config/m68k/hp2bsd.h | 78 - gcc/config/m68k/hp310.h | 36 - gcc/config/m68k/hp310g.h | 12 - gcc/config/m68k/hp320.h | 642 -- gcc/config/m68k/hp320g.h | 12 - gcc/config/m68k/hp3bsd.h | 44 - gcc/config/m68k/hp3bsd44.h | 53 - gcc/config/m68k/hpux7.h | 7 - gcc/config/m68k/isi-nfp.h | 9 - gcc/config/m68k/isi.h | 91 - gcc/config/m68k/lb1sf68.asm | 3904 ---------- gcc/config/m68k/lb1sun3.asm | 1036 --- gcc/config/m68k/linux-aout.h | 77 - gcc/config/m68k/linux.h | 387 - gcc/config/m68k/lynx-ng.h | 43 - gcc/config/m68k/lynx.h | 74 - gcc/config/m68k/m68020-elf.h | 53 - gcc/config/m68k/m68360-coff.h | 27 - gcc/config/m68k/m68360-none.h | 129 - gcc/config/m68k/m68k-aout.h | 44 - gcc/config/m68k/m68k-coff.h | 28 - gcc/config/m68k/m68k-none.h | 197 - gcc/config/m68k/m68k-psos.h | 67 - gcc/config/m68k/m68k.c | 3393 --------- gcc/config/m68k/m68k.h | 2139 ------ gcc/config/m68k/m68k.md | 7913 -------------------- gcc/config/m68k/m68kelf.h | 297 - gcc/config/m68k/m68kemb.h | 55 - gcc/config/m68k/m68kv4.h | 346 - gcc/config/m68k/mot3300-crt0.S | 98 - gcc/config/m68k/mot3300.h | 816 --- gcc/config/m68k/mot3300Mcrt0.S | 142 - gcc/config/m68k/netbsd.h | 63 - gcc/config/m68k/news.h | 552 -- gcc/config/m68k/news3.h | 6 - gcc/config/m68k/news3gas.h | 6 - gcc/config/m68k/newsgas.h | 19 - gcc/config/m68k/next.h | 199 - gcc/config/m68k/next21.h | 104 - gcc/config/m68k/os68000.h | 81 - gcc/config/m68k/ose68k.h | 45 - gcc/config/m68k/pbb.h | 163 - gcc/config/m68k/plexus.h | 108 - gcc/config/m68k/rtems.h | 33 - gcc/config/m68k/sgs.h | 446 -- gcc/config/m68k/st2000.h | 610 -- gcc/config/m68k/sun2.h | 77 - gcc/config/m68k/sun2o4.h | 189 - gcc/config/m68k/sun3.h | 301 - gcc/config/m68k/sun3mach.h | 15 - gcc/config/m68k/sun3n.h | 9 - gcc/config/m68k/sun3n3.h | 5 - gcc/config/m68k/sun3o3.h | 5 - gcc/config/m68k/t-adobe | 9 - gcc/config/m68k/t-aux | 44 - gcc/config/m68k/t-linux | 2 - gcc/config/m68k/t-linux-aout | 2 - gcc/config/m68k/t-lynx | 6 - gcc/config/m68k/t-m68kbare | 24 - gcc/config/m68k/t-m68kelf | 29 - gcc/config/m68k/t-mot3300 | 10 - gcc/config/m68k/t-mot3300-gald | 13 - gcc/config/m68k/t-mot3300-gas | 13 - gcc/config/m68k/t-mot3300-gld | 12 - gcc/config/m68k/t-next | 6 - gcc/config/m68k/t-ose68 | 26 - gcc/config/m68k/t-vxworks68 | 27 - gcc/config/m68k/tower-as.h | 616 -- gcc/config/m68k/tower.h | 104 - gcc/config/m68k/vxm68k.h | 101 - gcc/config/m68k/x-alloca-c | 1 - gcc/config/m68k/x-amix | 27 - gcc/config/m68k/x-apollo68 | 15 - gcc/config/m68k/x-apollo68v | 5 - gcc/config/m68k/x-ccur | 3 - gcc/config/m68k/x-crds | 7 - gcc/config/m68k/x-dpx2 | 16 - gcc/config/m68k/x-hp2bsd | 4 - gcc/config/m68k/x-hp320 | 17 - gcc/config/m68k/x-hp320g | 17 - gcc/config/m68k/x-hp3bsd44 | 1 - gcc/config/m68k/x-mot3300 | 15 - gcc/config/m68k/x-mot3300-gas | 12 - gcc/config/m68k/x-next | 13 - gcc/config/m68k/x-sun3 | 1 - gcc/config/m68k/x-tower | 9 - gcc/config/m68k/xm-3b1.h | 4 - gcc/config/m68k/xm-altos3068.h | 3 - gcc/config/m68k/xm-amix.h | 45 - gcc/config/m68k/xm-atari.h | 5 - gcc/config/m68k/xm-aux.h | 9 - gcc/config/m68k/xm-crds.h | 7 - gcc/config/m68k/xm-hp320.h | 13 - gcc/config/m68k/xm-linux.h | 4 - gcc/config/m68k/xm-lynx.h | 35 - gcc/config/m68k/xm-m68k.h | 41 - gcc/config/m68k/xm-m68kv.h | 9 - gcc/config/m68k/xm-mot3300.h | 41 - gcc/config/m68k/xm-netbsd.h | 4 - gcc/config/m68k/xm-next.h | 3 - gcc/config/m68k/xm-plexus.h | 6 - gcc/config/m68k/xm-sun3.h | 5 - gcc/config/m68k/xm-tower.h | 4 - gcc/config/m88k/dgux.h | 305 - gcc/config/m88k/dgux.ld | 48 - gcc/config/m88k/dguxbcs.h | 62 - gcc/config/m88k/dolph.h | 43 - gcc/config/m88k/dolphin.ld | 40 - gcc/config/m88k/luna.h | 58 - gcc/config/m88k/m88k-aout.h | 32 - gcc/config/m88k/m88k-coff.h | 34 - gcc/config/m88k/m88k-move.sh | 306 - gcc/config/m88k/m88k.c | 3162 -------- gcc/config/m88k/m88k.h | 2646 ------- gcc/config/m88k/m88k.md | 4023 ----------- gcc/config/m88k/sysv3.h | 150 - gcc/config/m88k/sysv4.h | 85 - gcc/config/m88k/t-bug | 12 - gcc/config/m88k/t-dgux | 26 - gcc/config/m88k/t-dgux-gas | 17 - gcc/config/m88k/t-dguxbcs | 28 - gcc/config/m88k/t-luna | 12 - gcc/config/m88k/t-luna-gas | 13 - gcc/config/m88k/t-m88k | 12 - gcc/config/m88k/t-m88k-gas | 18 - gcc/config/m88k/t-sysv4 | 22 - gcc/config/m88k/tekXD88.h | 50 - gcc/config/m88k/tekXD88.ld | 39 - gcc/config/m88k/x-dgux | 6 - gcc/config/m88k/x-dguxbcs | 4 - gcc/config/m88k/x-dolph | 19 - gcc/config/m88k/x-sysv3 | 7 - gcc/config/m88k/x-sysv4 | 10 - gcc/config/m88k/x-tekXD88 | 12 - gcc/config/m88k/xm-m88k.h | 61 - gcc/config/m88k/xm-sysv3.h | 32 - gcc/config/mips/abi64.h | 251 - gcc/config/mips/big.h | 24 - gcc/config/mips/bsd-4.h | 46 - gcc/config/mips/bsd-5.h | 67 - gcc/config/mips/cross64.h | 34 - gcc/config/mips/dec-bsd.h | 53 - gcc/config/mips/dec-osf1.h | 55 - gcc/config/mips/ecoff.h | 35 - gcc/config/mips/ecoffl.h | 30 - gcc/config/mips/elf.h | 352 - gcc/config/mips/elf5400.h | 50 - gcc/config/mips/elf64.h | 354 - gcc/config/mips/elfb4100.h | 61 - gcc/config/mips/elfb4300.h | 41 - gcc/config/mips/elfb5000.h | 48 - gcc/config/mips/elfl.h | 29 - gcc/config/mips/elfl4100.h | 61 - gcc/config/mips/elfl4300.h | 41 - gcc/config/mips/elfl5000.h | 48 - gcc/config/mips/elfl64.h | 29 - gcc/config/mips/elflorion.h | 24 - gcc/config/mips/elforion.h | 22 - gcc/config/mips/gnu.h | 129 - gcc/config/mips/iris3.h | 72 - gcc/config/mips/iris4.h | 48 - gcc/config/mips/iris4loser.h | 5 - gcc/config/mips/iris5.h | 164 - gcc/config/mips/iris5gas.h | 34 - gcc/config/mips/iris6.h | 567 -- gcc/config/mips/linux.h | 99 - gcc/config/mips/little.h | 24 - gcc/config/mips/mips-5.h | 46 - gcc/config/mips/mips.c | 8711 ---------------------- gcc/config/mips/mips.h | 4760 ------------ gcc/config/mips/mips.md | 10710 --------------------------- gcc/config/mips/mips16.S | 740 -- gcc/config/mips/ncd.h | 42 - gcc/config/mips/netbsd.h | 227 - gcc/config/mips/news4.h | 39 - gcc/config/mips/news5.h | 62 - gcc/config/mips/nws3250v4.h | 36 - gcc/config/mips/osfrose.h | 149 - gcc/config/mips/r3900.h | 72 - gcc/config/mips/rtems64.h | 63 - gcc/config/mips/sni-gas.h | 38 - gcc/config/mips/sni-svr4.h | 100 - gcc/config/mips/svr3-4.h | 63 - gcc/config/mips/svr3-5.h | 89 - gcc/config/mips/svr4-4.h | 61 - gcc/config/mips/svr4-5.h | 92 - gcc/config/mips/svr4-t.h | 29 - gcc/config/mips/t-biendian | 18 - gcc/config/mips/t-bsd | 12 - gcc/config/mips/t-bsd-gas | 8 - gcc/config/mips/t-cross64 | 17 - gcc/config/mips/t-ecoff | 92 - gcc/config/mips/t-elf | 96 - gcc/config/mips/t-iris6 | 20 - gcc/config/mips/t-lsi | 100 - gcc/config/mips/t-mips | 8 - gcc/config/mips/t-mips-gas | 4 - gcc/config/mips/t-ncd | 2 - gcc/config/mips/t-osfrose | 8 - gcc/config/mips/t-r3900 | 95 - gcc/config/mips/t-svr3 | 12 - gcc/config/mips/t-svr3-gas | 8 - gcc/config/mips/t-svr4 | 12 - gcc/config/mips/t-svr4-gas | 8 - gcc/config/mips/t-ultrix | 10 - gcc/config/mips/t-vr4100 | 75 - gcc/config/mips/t-vr4300 | 75 - gcc/config/mips/t-vr5000 | 75 - gcc/config/mips/ultrix.h | 61 - gcc/config/mips/vxworks.h | 50 - gcc/config/mips/x-dec-osf1 | 17 - gcc/config/mips/x-iris | 31 - gcc/config/mips/x-iris3 | 30 - gcc/config/mips/x-iris6 | 11 - gcc/config/mips/x-mips | 20 - gcc/config/mips/x-netbsd | 17 - gcc/config/mips/x-nws3250v4 | 19 - gcc/config/mips/x-osfrose | 32 - gcc/config/mips/x-sni-svr4 | 18 - gcc/config/mips/x-sony | 18 - gcc/config/mips/x-sysv | 26 - gcc/config/mips/x-ultrix | 17 - gcc/config/mips/xm-iris3.h | 3 - gcc/config/mips/xm-iris4.h | 13 - gcc/config/mips/xm-iris5.h | 9 - gcc/config/mips/xm-iris6.h | 17 - gcc/config/mips/xm-mips.h | 76 - gcc/config/mips/xm-netbsd.h | 2 - gcc/config/mips/xm-news.h | 8 - gcc/config/mips/xm-nws3250v4.h | 9 - gcc/config/mips/xm-sysv.h | 30 - gcc/config/mips/xm-sysv4.h | 7 - gcc/config/mn10200/divmod.c | 50 - gcc/config/mn10200/lib1funcs.asm | 609 -- gcc/config/mn10200/mn10200.c | 1532 ---- gcc/config/mn10200/mn10200.h | 1078 --- gcc/config/mn10200/mn10200.md | 2052 ------ gcc/config/mn10200/mn10200_020422.h | 1074 --- gcc/config/mn10200/t-mn10200 | 55 - gcc/config/mn10200/udivmod.c | 14 - gcc/config/mn10200/udivmodsi4.c | 24 - gcc/config/mn10200/xm-mn10200.h | 47 - gcc/config/mn10300/mn10300.c | 1006 --- gcc/config/mn10300/mn10300.h | 1170 --- gcc/config/mn10300/mn10300.md | 2169 ------ gcc/config/mn10300/mn10300_020422.h | 1166 --- gcc/config/mn10300/t-mn10300 | 29 - gcc/config/mn10300/xm-mn10300.h | 47 - gcc/config/msdos/configur.bat | 47 - gcc/config/msdos/libgcc.mak | 14 - gcc/config/msdos/mklibgcc.c | 98 - gcc/config/msdos/top.sed | 57 - gcc/config/netbsd.h | 209 - gcc/config/netware.h | 153 - gcc/config/nextstep.c | 97 - gcc/config/nextstep.h | 601 -- gcc/config/nextstep21.h | 65 - gcc/config/ns32k/encore.h | 196 - gcc/config/ns32k/genix.h | 167 - gcc/config/ns32k/merlin.h | 231 - gcc/config/ns32k/netbsd.h | 113 - gcc/config/ns32k/ns32k.c | 1196 --- gcc/config/ns32k/ns32k.h | 1722 ----- gcc/config/ns32k/ns32k.md | 3058 -------- gcc/config/ns32k/pc532-mach.h | 30 - gcc/config/ns32k/pc532-min.h | 41 - gcc/config/ns32k/pc532.h | 73 - gcc/config/ns32k/sequent.h | 77 - gcc/config/ns32k/tek6000.h | 237 - gcc/config/ns32k/tek6100.h | 7 - gcc/config/ns32k/tek6200.h | 7 - gcc/config/ns32k/x-genix | 6 - gcc/config/ns32k/xm-genix.h | 5 - gcc/config/ns32k/xm-netbsd.h | 8 - gcc/config/ns32k/xm-ns32k.h | 42 - gcc/config/ns32k/xm-pc532-min.h | 7 - gcc/config/pa/ee.asm | 261 - gcc/config/pa/ee_fp.asm | 274 - gcc/config/pa/lib1funcs.asm | 1146 --- gcc/config/pa/lib2funcs.asm | 74 - gcc/config/pa/pa-gas.h | 22 - gcc/config/pa/pa-hiux.h | 26 - gcc/config/pa/pa-hpux.h | 49 - gcc/config/pa/pa-hpux10.h | 89 - gcc/config/pa/pa-hpux11.h | 98 - gcc/config/pa/pa-hpux7.h | 37 - gcc/config/pa/pa-hpux9.h | 31 - gcc/config/pa/pa-oldas.h | 22 - gcc/config/pa/pa-osf.h | 42 - gcc/config/pa/pa-pro-end.h | 42 - gcc/config/pa/pa-pro.h | 79 - gcc/config/pa/pa.c | 6491 ----------------- gcc/config/pa/pa.h | 2601 ------- gcc/config/pa/pa.md | 5729 --------------- gcc/config/pa/pa1.h | 28 - gcc/config/pa/rtems.h | 31 - gcc/config/pa/t-dce-thr | 5 - gcc/config/pa/t-pa | 18 - gcc/config/pa/t-pro | 38 - gcc/config/pa/x-pa | 3 - gcc/config/pa/x-pa-hpux | 4 - gcc/config/pa/xm-pa.h | 62 - gcc/config/pa/xm-pahpux.h | 61 - gcc/config/pa/xm-papro.h | 58 - gcc/config/pdp11/2bsd.h | 87 - gcc/config/pdp11/pdp11.c | 1415 ---- gcc/config/pdp11/pdp11.h | 1393 ---- gcc/config/pdp11/pdp11.md | 1824 ----- gcc/config/pdp11/t-pdp11 | 8 - gcc/config/pdp11/xm-pdp11.h | 27 - gcc/config/psos.h | 183 - gcc/config/ptx4.h | 859 --- gcc/config/pyr/pyr.c | 857 --- gcc/config/pyr/pyr.h | 1506 ---- gcc/config/pyr/pyr.md | 1360 ---- gcc/config/pyr/x-pyr | 2 - gcc/config/pyr/xm-pyr.h | 40 - gcc/config/romp/romp.c | 2038 ------ gcc/config/romp/romp.h | 1636 ----- gcc/config/romp/romp.md | 2776 ------- gcc/config/romp/x-mach | 5 - gcc/config/romp/x-romp | 11 - gcc/config/romp/xm-romp.h | 54 - gcc/config/rs6000/aix31.h | 41 - gcc/config/rs6000/aix3newas.h | 88 - gcc/config/rs6000/aix41.h | 169 - gcc/config/rs6000/aix43.h | 199 - gcc/config/rs6000/beos.h | 124 - gcc/config/rs6000/cygwin.h | 67 - gcc/config/rs6000/eabi-ci.asm | 131 - gcc/config/rs6000/eabi-cn.asm | 121 - gcc/config/rs6000/eabi-ctors.c | 92 - gcc/config/rs6000/eabi.asm | 575 -- gcc/config/rs6000/eabi.h | 40 - gcc/config/rs6000/eabiaix.h | 41 - gcc/config/rs6000/eabile.h | 49 - gcc/config/rs6000/eabilesim.h | 46 - gcc/config/rs6000/eabisim.h | 46 - gcc/config/rs6000/linux.h | 76 - gcc/config/rs6000/lynx.h | 104 - gcc/config/rs6000/mach.h | 42 - gcc/config/rs6000/milli.exp | 7 - gcc/config/rs6000/netware.h | 284 - gcc/config/rs6000/nt-ci.asm | 48 - gcc/config/rs6000/nt-cn.asm | 48 - gcc/config/rs6000/ntstack.asm | 42 - gcc/config/rs6000/powerpc.h | 61 - gcc/config/rs6000/rs6000.c | 7156 ------------------ gcc/config/rs6000/rs6000.h | 3403 --------- gcc/config/rs6000/rs6000.md | 13242 ---------------------------------- gcc/config/rs6000/rtems.h | 38 - gcc/config/rs6000/sol-c0.c | 122 - gcc/config/rs6000/sol-ci.asm | 104 - gcc/config/rs6000/sol-cn.asm | 82 - gcc/config/rs6000/sol2.h | 179 - gcc/config/rs6000/sysv4.h | 1770 ----- gcc/config/rs6000/sysv4le.h | 54 - gcc/config/rs6000/t-aix43 | 48 - gcc/config/rs6000/t-beos | 51 - gcc/config/rs6000/t-newas | 52 - gcc/config/rs6000/t-ppc | 12 - gcc/config/rs6000/t-ppccomm | 79 - gcc/config/rs6000/t-ppcgas | 22 - gcc/config/rs6000/t-ppcos | 12 - gcc/config/rs6000/t-rs6000 | 22 - gcc/config/rs6000/t-vxworks | 3 - gcc/config/rs6000/t-winnt | 35 - gcc/config/rs6000/t-xnewas | 58 - gcc/config/rs6000/t-xrs6000 | 28 - gcc/config/rs6000/tramp.asm | 120 - gcc/config/rs6000/vxppc.h | 107 - gcc/config/rs6000/vxppcle.h | 58 - gcc/config/rs6000/win-nt.h | 481 -- gcc/config/rs6000/x-aix31 | 9 - gcc/config/rs6000/x-aix41 | 12 - gcc/config/rs6000/x-aix43 | 15 - gcc/config/rs6000/x-beos | 9 - gcc/config/rs6000/x-cygwin | 4 - gcc/config/rs6000/x-lynx | 14 - gcc/config/rs6000/x-mach | 7 - gcc/config/rs6000/x-rs6000 | 9 - gcc/config/rs6000/x-sysv4 | 2 - gcc/config/rs6000/xm-beos.h | 89 - gcc/config/rs6000/xm-cygwin.h | 1 - gcc/config/rs6000/xm-lynx.h | 35 - gcc/config/rs6000/xm-mach.h | 2 - gcc/config/rs6000/xm-rs6000.h | 65 - gcc/config/rs6000/xm-sysv4.h | 72 - gcc/config/sh/elf.h | 123 - gcc/config/sh/lib1funcs.asm | 1206 ---- gcc/config/sh/rtems.h | 35 - gcc/config/sh/rtemself.h | 33 - gcc/config/sh/sh.c | 4786 ------------ gcc/config/sh/sh.h | 2232 ------ gcc/config/sh/sh.md | 4654 ------------ gcc/config/sh/t-sh | 29 - gcc/config/sh/xm-sh.h | 42 - gcc/config/sparc/aout.h | 26 - gcc/config/sparc/bsd.h | 7 - gcc/config/sparc/elf.h | 58 - gcc/config/sparc/gmon-sol2.c | 429 -- gcc/config/sparc/hal.h | 33 - gcc/config/sparc/lb1spc.asm | 784 -- gcc/config/sparc/lb1spl.asm | 246 - gcc/config/sparc/linux-aout.h | 130 - gcc/config/sparc/linux.h | 259 - gcc/config/sparc/linux64.h | 366 - gcc/config/sparc/lite.h | 45 - gcc/config/sparc/litecoff.h | 113 - gcc/config/sparc/liteelf.h | 53 - gcc/config/sparc/lynx-ng.h | 41 - gcc/config/sparc/lynx.h | 53 - gcc/config/sparc/netbsd.h | 46 - gcc/config/sparc/pbd.h | 184 - gcc/config/sparc/rtems.h | 35 - gcc/config/sparc/sol2-c1.asm | 110 - gcc/config/sparc/sol2-ci.asm | 68 - gcc/config/sparc/sol2-cn.asm | 54 - gcc/config/sparc/sol2-g1.asm | 88 - gcc/config/sparc/sol2-sld-64.h | 363 - gcc/config/sparc/sol2-sld.h | 11 - gcc/config/sparc/sol2.h | 236 - gcc/config/sparc/sp64-aout.h | 38 - gcc/config/sparc/sp64-elf.h | 158 - gcc/config/sparc/sp64-elf_020422.h | 155 - gcc/config/sparc/sp86x-aout.h | 60 - gcc/config/sparc/sp86x-elf.h | 73 - gcc/config/sparc/sparc.c | 7532 ------------------- gcc/config/sparc/sparc.h | 3504 --------- gcc/config/sparc/sparc.md | 8242 --------------------- gcc/config/sparc/splet.h | 69 - gcc/config/sparc/sun4gas.h | 27 - gcc/config/sparc/sun4o3.h | 29 - gcc/config/sparc/sunos4.h | 49 - gcc/config/sparc/sysv4.h | 233 - gcc/config/sparc/t-elf | 39 - gcc/config/sparc/t-halos | 2 - gcc/config/sparc/t-linux | 6 - gcc/config/sparc/t-linux64 | 21 - gcc/config/sparc/t-sol2 | 30 - gcc/config/sparc/t-sol2-64 | 8 - gcc/config/sparc/t-sp64 | 2 - gcc/config/sparc/t-sp86x | 21 - gcc/config/sparc/t-sparcbare | 26 - gcc/config/sparc/t-sparclite | 24 - gcc/config/sparc/t-splet | 22 - gcc/config/sparc/t-sunos40 | 7 - gcc/config/sparc/t-sunos41 | 16 - gcc/config/sparc/t-vxsparc | 17 - gcc/config/sparc/vxsim.h | 131 - gcc/config/sparc/vxsparc.h | 61 - gcc/config/sparc/x-sysv4 | 2 - gcc/config/sparc/xm-linux.h | 26 - gcc/config/sparc/xm-lynx.h | 39 - gcc/config/sparc/xm-netbsd.h | 4 - gcc/config/sparc/xm-pbd.h | 10 - gcc/config/sparc/xm-sol2.h | 4 - gcc/config/sparc/xm-sp64.h | 27 - gcc/config/sparc/xm-sparc.h | 49 - gcc/config/sparc/xm-sysv4-64.h | 27 - gcc/config/sparc/xm-sysv4.h | 48 - gcc/config/spur/spur.c | 326 - gcc/config/spur/spur.h | 1051 --- gcc/config/spur/spur.md | 1092 --- gcc/config/spur/xm-spur.h | 39 - gcc/config/svr3.h | 375 - gcc/config/svr4.h | 993 --- gcc/config/t-gnu | 13 - gcc/config/t-libc-ok | 3 - gcc/config/t-linux | 16 - gcc/config/t-linux-aout | 11 - gcc/config/t-linux-gnulibc1 | 2 - gcc/config/t-netbsd | 9 - gcc/config/t-rtems | 6 - gcc/config/t-svr4 | 8 - gcc/config/tahoe/harris.h | 87 - gcc/config/tahoe/tahoe.c | 564 -- gcc/config/tahoe/tahoe.h | 1017 --- gcc/config/tahoe/tahoe.md | 2113 ------ gcc/config/tahoe/xm-tahoe.h | 59 - gcc/config/tm-dwarf2.h | 4 - gcc/config/v850/lib1funcs.asm | 1670 ----- gcc/config/v850/t-v850 | 120 - gcc/config/v850/v850.c | 3673 ---------- gcc/config/v850/v850.h | 1792 ----- gcc/config/v850/v850.md | 1813 ----- gcc/config/v850/v850e.h | 62 - gcc/config/v850/v850ea.h | 54 - gcc/config/v850/xm-v850.h | 49 - gcc/config/vax/netbsd.h | 24 - gcc/config/vax/ultrix.h | 12 - gcc/config/vax/vax.c | 837 --- gcc/config/vax/vax.h | 1317 ---- gcc/config/vax/vax.md | 2136 ------ gcc/config/vax/vaxv.h | 70 - gcc/config/vax/vms.h | 369 - gcc/config/vax/x-vax | 3 - gcc/config/vax/xm-vax.h | 45 - gcc/config/vax/xm-vaxv.h | 3 - gcc/config/vax/xm-vms.h | 206 - gcc/config/we32k/we32k.c | 136 - gcc/config/we32k/we32k.h | 1048 --- gcc/config/we32k/we32k.md | 1185 --- gcc/config/we32k/x-we32k | 1 - gcc/config/we32k/xm-we32k.h | 49 - gcc/config/winnt/config-nt.bat | 58 - gcc/config/winnt/config-nt.sed | 127 - gcc/config/winnt/dirent.c | 360 - gcc/config/winnt/dirent.h | 96 - gcc/config/winnt/fixinc-nt.c | 260 - gcc/config/winnt/headers.mak | 51 - gcc/config/winnt/ld.c | 348 - gcc/config/winnt/libgcc.mak | 19 - gcc/config/winnt/mklibgcc.c | 97 - gcc/config/winnt/oldnames.c | 47 - gcc/config/winnt/spawnv.c | 71 - gcc/config/winnt/win-nt.h | 61 - gcc/config/winnt/x-winnt | 34 - gcc/config/winnt/xm-winnt.h | 63 - gcc/config/x-linux | 5 - gcc/config/x-linux-aout | 14 - gcc/config/x-lynx | 6 - gcc/config/x-svr4 | 9 - gcc/config/xm-alloca.h | 4 - gcc/config/xm-freebsd.h | 24 - gcc/config/xm-gnu.h | 32 - gcc/config/xm-linux.h | 33 - gcc/config/xm-netbsd.h | 26 - gcc/config/xm-siglist.h | 6 - gcc/config/xm-std32.h | 34 - gcc/config/xm-svr3.h | 25 - gcc/config/xm-svr4.h | 29 - gcc/config/z8k/lib2funcs.c | 110 - gcc/config/z8k/t-z8k | 26 - gcc/config/z8k/xm-z8k.h | 46 - gcc/config/z8k/z8k.c | 2910 -------- gcc/config/z8k/z8k.h | 1736 ----- gcc/config/z8k/z8k.md | 2350 ------ 880 files changed, 404976 deletions(-) delete mode 100755 gcc/config/1750a/1750a.c delete mode 100755 gcc/config/1750a/1750a.h delete mode 100755 gcc/config/1750a/1750a.md delete mode 100755 gcc/config/1750a/ms1750.inc delete mode 100755 gcc/config/1750a/xm-1750a.h delete mode 100755 gcc/config/README delete mode 100755 gcc/config/a29k/a29k.c delete mode 100755 gcc/config/a29k/a29k.h delete mode 100755 gcc/config/a29k/a29k.md delete mode 100755 gcc/config/a29k/t-a29k delete mode 100755 gcc/config/a29k/t-a29kbare delete mode 100755 gcc/config/a29k/t-vx29k delete mode 100755 gcc/config/a29k/udi.h delete mode 100755 gcc/config/a29k/unix.h delete mode 100755 gcc/config/a29k/vx29k.h delete mode 100755 gcc/config/a29k/x-unix delete mode 100755 gcc/config/a29k/xm-a29k.h delete mode 100755 gcc/config/a29k/xm-unix.h delete mode 100755 gcc/config/alpha/alpha.c delete mode 100755 gcc/config/alpha/alpha.h delete mode 100755 gcc/config/alpha/alpha.md delete mode 100755 gcc/config/alpha/config-nt.sed delete mode 100755 gcc/config/alpha/crtbegin.asm delete mode 100755 gcc/config/alpha/crtend.asm delete mode 100755 gcc/config/alpha/elf.h delete mode 100755 gcc/config/alpha/lib1funcs.asm delete mode 100755 gcc/config/alpha/linux-ecoff.h delete mode 100755 gcc/config/alpha/linux-elf.h delete mode 100755 gcc/config/alpha/linux.h delete mode 100755 gcc/config/alpha/netbsd-elf.h delete mode 100755 gcc/config/alpha/netbsd.h delete mode 100755 gcc/config/alpha/osf.h delete mode 100755 gcc/config/alpha/osf12.h delete mode 100755 gcc/config/alpha/osf2or3.h delete mode 100755 gcc/config/alpha/t-crtbe delete mode 100755 gcc/config/alpha/t-linux delete mode 100755 gcc/config/alpha/t-vms delete mode 100755 gcc/config/alpha/va_list.h delete mode 100755 gcc/config/alpha/vms-tramp.asm delete mode 100755 gcc/config/alpha/vms.h delete mode 100755 gcc/config/alpha/vxworks.h delete mode 100755 gcc/config/alpha/win-nt.h delete mode 100755 gcc/config/alpha/x-alpha delete mode 100755 gcc/config/alpha/xm-alpha.h delete mode 100755 gcc/config/alpha/xm-linux.h delete mode 100755 gcc/config/alpha/xm-vms.h delete mode 100755 gcc/config/alpha/xm-winnt.h delete mode 100755 gcc/config/aoutos.h delete mode 100755 gcc/config/arc/arc.c delete mode 100755 gcc/config/arc/arc.h delete mode 100755 gcc/config/arc/arc.md delete mode 100755 gcc/config/arc/initfini.c delete mode 100755 gcc/config/arc/lib1funcs.asm delete mode 100755 gcc/config/arc/t-arc delete mode 100755 gcc/config/arc/xm-arc.h delete mode 100755 gcc/config/c4x/c4x.c delete mode 100755 gcc/config/c4x/c4x.h delete mode 100755 gcc/config/c4x/c4x.md delete mode 100755 gcc/config/c4x/libgcc.S delete mode 100755 gcc/config/c4x/t-c4x delete mode 100755 gcc/config/c4x/xm-c4x.h delete mode 100755 gcc/config/clipper/clipper.c delete mode 100755 gcc/config/clipper/clipper.h delete mode 100755 gcc/config/clipper/clipper.md delete mode 100755 gcc/config/clipper/clix.h delete mode 100755 gcc/config/clipper/x-clix delete mode 100755 gcc/config/clipper/xm-clix.h delete mode 100755 gcc/config/convex/convex.c delete mode 100755 gcc/config/convex/convex.h delete mode 100755 gcc/config/convex/convex.md delete mode 100755 gcc/config/convex/fixinc.convex delete mode 100755 gcc/config/convex/x-convex delete mode 100755 gcc/config/convex/xm-convex.h delete mode 100755 gcc/config/d10v/abi delete mode 100755 gcc/config/d10v/d10v.c delete mode 100755 gcc/config/d10v/d10v.h delete mode 100755 gcc/config/d10v/d10v.md delete mode 100755 gcc/config/d10v/libgcc1.asm delete mode 100755 gcc/config/d10v/scrt0.asm delete mode 100755 gcc/config/d10v/sim.asm delete mode 100755 gcc/config/d10v/t-d10v delete mode 100755 gcc/config/d10v/xm-d10v.h delete mode 100755 gcc/config/d30v/abi delete mode 100755 gcc/config/d30v/d30v.c delete mode 100755 gcc/config/d30v/d30v.h delete mode 100755 gcc/config/d30v/d30v.md delete mode 100755 gcc/config/d30v/libgcc1.asm delete mode 100755 gcc/config/d30v/t-d30v delete mode 100755 gcc/config/d30v/xm-d30v.h delete mode 100755 gcc/config/dbx.h delete mode 100755 gcc/config/dbxcoff.h delete mode 100755 gcc/config/dsp16xx/dsp16xx.c delete mode 100755 gcc/config/dsp16xx/dsp16xx.h delete mode 100755 gcc/config/dsp16xx/dsp16xx.md delete mode 100755 gcc/config/dsp16xx/xm-dsp16xx.h delete mode 100755 gcc/config/elfos.h delete mode 100755 gcc/config/elxsi/elxsi.c delete mode 100755 gcc/config/elxsi/elxsi.h delete mode 100755 gcc/config/elxsi/elxsi.md delete mode 100755 gcc/config/elxsi/x-elxsi delete mode 100755 gcc/config/elxsi/xm-elxsi.h delete mode 100755 gcc/config/float-d10v.h delete mode 100755 gcc/config/float-i128.h delete mode 100755 gcc/config/float-i32.h delete mode 100755 gcc/config/float-i386.h delete mode 100755 gcc/config/float-m68k.h delete mode 100755 gcc/config/float-sh.h delete mode 100755 gcc/config/float-vax.h delete mode 100755 gcc/config/fr30/crti.asm delete mode 100755 gcc/config/fr30/crtn.asm delete mode 100755 gcc/config/fr30/fr30.c delete mode 100755 gcc/config/fr30/fr30.h delete mode 100755 gcc/config/fr30/fr30.md delete mode 100755 gcc/config/fr30/lib1funcs.asm delete mode 100755 gcc/config/fr30/t-fr30 delete mode 100755 gcc/config/fr30/xm-fr30.h delete mode 100755 gcc/config/fx80/fx80.c delete mode 100755 gcc/config/fx80/fx80.h delete mode 100755 gcc/config/fx80/fx80.md delete mode 100755 gcc/config/fx80/xm-fx80.h delete mode 100755 gcc/config/gmicro/gmicro.c delete mode 100755 gcc/config/gmicro/gmicro.h delete mode 100755 gcc/config/gmicro/gmicro.md delete mode 100755 gcc/config/gnu.h delete mode 100755 gcc/config/gofast.h delete mode 100755 gcc/config/h8300/h8300.c delete mode 100755 gcc/config/h8300/h8300.h delete mode 100755 gcc/config/h8300/h8300.md delete mode 100755 gcc/config/h8300/lib1funcs.asm delete mode 100755 gcc/config/h8300/t-h8300 delete mode 100755 gcc/config/h8300/xm-h8300.h delete mode 100755 gcc/config/i370/i370.c delete mode 100755 gcc/config/i370/i370.h delete mode 100755 gcc/config/i370/i370.md delete mode 100755 gcc/config/i370/t-i370 delete mode 100755 gcc/config/i370/xm-i370.h delete mode 100755 gcc/config/i386/386bsd.h delete mode 100755 gcc/config/i386/aix386.h delete mode 100755 gcc/config/i386/aix386ng.h delete mode 100755 gcc/config/i386/att.h delete mode 100755 gcc/config/i386/bsd.h delete mode 100755 gcc/config/i386/bsd386.h delete mode 100755 gcc/config/i386/config-nt.sed delete mode 100755 gcc/config/i386/crtdll.h delete mode 100755 gcc/config/i386/cygwin.asm delete mode 100755 gcc/config/i386/cygwin.h delete mode 100755 gcc/config/i386/dgux.c delete mode 100755 gcc/config/i386/dgux.h delete mode 100755 gcc/config/i386/freebsd-elf.h delete mode 100755 gcc/config/i386/freebsd.h delete mode 100755 gcc/config/i386/gas.h delete mode 100755 gcc/config/i386/gmon-sol2.c delete mode 100755 gcc/config/i386/gnu.h delete mode 100755 gcc/config/i386/go32-rtems.h delete mode 100755 gcc/config/i386/go32.h delete mode 100755 gcc/config/i386/gstabs.h delete mode 100755 gcc/config/i386/i386-aout.h delete mode 100755 gcc/config/i386/i386-coff.h delete mode 100755 gcc/config/i386/i386.c delete mode 100755 gcc/config/i386/i386.h delete mode 100755 gcc/config/i386/i386.md delete mode 100755 gcc/config/i386/i386elf.h delete mode 100755 gcc/config/i386/isc.h delete mode 100755 gcc/config/i386/isccoff.h delete mode 100755 gcc/config/i386/iscdbx.h delete mode 100755 gcc/config/i386/linux-aout.h delete mode 100755 gcc/config/i386/linux-oldld.h delete mode 100755 gcc/config/i386/linux.h delete mode 100755 gcc/config/i386/lynx-ng.h delete mode 100755 gcc/config/i386/lynx.h delete mode 100755 gcc/config/i386/mach.h delete mode 100755 gcc/config/i386/mingw32.h delete mode 100755 gcc/config/i386/moss.h delete mode 100755 gcc/config/i386/netbsd.h delete mode 100755 gcc/config/i386/netware.h delete mode 100755 gcc/config/i386/next.h delete mode 100755 gcc/config/i386/os2.h delete mode 100755 gcc/config/i386/osf1-ci.asm delete mode 100755 gcc/config/i386/osf1-cn.asm delete mode 100755 gcc/config/i386/osf1elf.h delete mode 100755 gcc/config/i386/osf1elfgdb.h delete mode 100755 gcc/config/i386/osfelf.h delete mode 100755 gcc/config/i386/osfrose.h delete mode 100755 gcc/config/i386/perform.h delete mode 100755 gcc/config/i386/ptx4-i.h delete mode 100755 gcc/config/i386/rtems.h delete mode 100755 gcc/config/i386/rtemself.h delete mode 100755 gcc/config/i386/sco.h delete mode 100755 gcc/config/i386/sco4.h delete mode 100755 gcc/config/i386/sco4dbx.h delete mode 100755 gcc/config/i386/sco5.h delete mode 100755 gcc/config/i386/sco5gas.h delete mode 100755 gcc/config/i386/scodbx.h delete mode 100755 gcc/config/i386/seq-gas.h delete mode 100755 gcc/config/i386/seq-sysv3.h delete mode 100755 gcc/config/i386/seq2-sysv3.h delete mode 100755 gcc/config/i386/sequent.h delete mode 100755 gcc/config/i386/sol2-c1.asm delete mode 100755 gcc/config/i386/sol2-ci.asm delete mode 100755 gcc/config/i386/sol2-cn.asm delete mode 100755 gcc/config/i386/sol2-gc1.asm delete mode 100755 gcc/config/i386/sol2.h delete mode 100755 gcc/config/i386/sol2dbg.h delete mode 100755 gcc/config/i386/sun.h delete mode 100755 gcc/config/i386/sun386.h delete mode 100755 gcc/config/i386/svr3.ifile delete mode 100755 gcc/config/i386/svr3dbx.h delete mode 100755 gcc/config/i386/svr3gas.h delete mode 100755 gcc/config/i386/svr3z.ifile delete mode 100755 gcc/config/i386/sysv3.h delete mode 100755 gcc/config/i386/sysv4.h delete mode 100755 gcc/config/i386/t-crtpic delete mode 100755 gcc/config/i386/t-crtstuff delete mode 100755 gcc/config/i386/t-cygwin delete mode 100755 gcc/config/i386/t-dgux delete mode 100755 gcc/config/i386/t-freebsd delete mode 100755 gcc/config/i386/t-go32 delete mode 100755 gcc/config/i386/t-i386bare delete mode 100755 gcc/config/i386/t-i386elf delete mode 100755 gcc/config/i386/t-mingw32 delete mode 100755 gcc/config/i386/t-netware delete mode 100755 gcc/config/i386/t-next delete mode 100755 gcc/config/i386/t-osf delete mode 100755 gcc/config/i386/t-osf1elf delete mode 100755 gcc/config/i386/t-sco5 delete mode 100755 gcc/config/i386/t-sco5gas delete mode 100755 gcc/config/i386/t-sol2 delete mode 100755 gcc/config/i386/t-svr3dbx delete mode 100755 gcc/config/i386/t-svr4 delete mode 100755 gcc/config/i386/t-udk delete mode 100755 gcc/config/i386/t-vsta delete mode 100755 gcc/config/i386/t-winnt delete mode 100755 gcc/config/i386/udk.h delete mode 100755 gcc/config/i386/unix.h delete mode 100755 gcc/config/i386/v3gas.h delete mode 100755 gcc/config/i386/vsta.h delete mode 100755 gcc/config/i386/vxi386.h delete mode 100755 gcc/config/i386/win-nt.h delete mode 100755 gcc/config/i386/win32.h delete mode 100755 gcc/config/i386/winnt.c delete mode 100755 gcc/config/i386/x-aix delete mode 100755 gcc/config/i386/x-cygwin delete mode 100755 gcc/config/i386/x-dgux delete mode 100755 gcc/config/i386/x-go32 delete mode 100755 gcc/config/i386/x-isc delete mode 100755 gcc/config/i386/x-isc3 delete mode 100755 gcc/config/i386/x-ncr3000 delete mode 100755 gcc/config/i386/x-next delete mode 100755 gcc/config/i386/x-osf1elf delete mode 100755 gcc/config/i386/x-osfrose delete mode 100755 gcc/config/i386/x-sco delete mode 100755 gcc/config/i386/x-sco4 delete mode 100755 gcc/config/i386/x-sco5 delete mode 100755 gcc/config/i386/x-sysv3 delete mode 100755 gcc/config/i386/x-vsta delete mode 100755 gcc/config/i386/xm-aix.h delete mode 100755 gcc/config/i386/xm-bsd386.h delete mode 100755 gcc/config/i386/xm-cygwin.h delete mode 100755 gcc/config/i386/xm-dgux.h delete mode 100755 gcc/config/i386/xm-dos.h delete mode 100755 gcc/config/i386/xm-freebsd.h delete mode 100755 gcc/config/i386/xm-gnu.h delete mode 100755 gcc/config/i386/xm-go32.h delete mode 100755 gcc/config/i386/xm-isc.h delete mode 100755 gcc/config/i386/xm-linux.h delete mode 100755 gcc/config/i386/xm-lynx.h delete mode 100755 gcc/config/i386/xm-mingw32.h delete mode 100755 gcc/config/i386/xm-netbsd.h delete mode 100755 gcc/config/i386/xm-next.h delete mode 100755 gcc/config/i386/xm-os2.h delete mode 100755 gcc/config/i386/xm-osf.h delete mode 100755 gcc/config/i386/xm-osf1elf.h delete mode 100755 gcc/config/i386/xm-sco.h delete mode 100755 gcc/config/i386/xm-sco5.h delete mode 100755 gcc/config/i386/xm-sun.h delete mode 100755 gcc/config/i386/xm-sysv3.h delete mode 100755 gcc/config/i386/xm-sysv4.h delete mode 100755 gcc/config/i386/xm-vsta.h delete mode 100755 gcc/config/i386/xm-winnt.h delete mode 100755 gcc/config/i860/bsd-gas.h delete mode 100755 gcc/config/i860/bsd.h delete mode 100755 gcc/config/i860/fx2800.h delete mode 100755 gcc/config/i860/i860.c delete mode 100755 gcc/config/i860/i860.h delete mode 100755 gcc/config/i860/i860.md delete mode 100755 gcc/config/i860/mach.h delete mode 100755 gcc/config/i860/paragon.h delete mode 100755 gcc/config/i860/sysv3.h delete mode 100755 gcc/config/i860/sysv4.h delete mode 100755 gcc/config/i860/t-fx2800 delete mode 100755 gcc/config/i860/x-fx2800 delete mode 100755 gcc/config/i860/x-sysv3 delete mode 100755 gcc/config/i860/x-sysv4 delete mode 100755 gcc/config/i860/xm-fx2800.h delete mode 100755 gcc/config/i860/xm-i860.h delete mode 100755 gcc/config/i960/i960-coff.h delete mode 100755 gcc/config/i960/i960.c delete mode 100755 gcc/config/i960/i960.h delete mode 100755 gcc/config/i960/i960.md delete mode 100755 gcc/config/i960/rtems.h delete mode 100755 gcc/config/i960/t-960bare delete mode 100755 gcc/config/i960/t-vxworks960 delete mode 100755 gcc/config/i960/vx960-coff.h delete mode 100755 gcc/config/i960/vx960.h delete mode 100755 gcc/config/i960/xm-i960.h delete mode 100755 gcc/config/libgloss.h delete mode 100755 gcc/config/linux-aout.h delete mode 100755 gcc/config/linux.h delete mode 100755 gcc/config/lynx-ng.h delete mode 100755 gcc/config/lynx.h delete mode 100755 gcc/config/m32r/initfini.c delete mode 100755 gcc/config/m32r/m32r.c delete mode 100755 gcc/config/m32r/m32r.h delete mode 100755 gcc/config/m32r/m32r.md delete mode 100755 gcc/config/m32r/t-m32r delete mode 100755 gcc/config/m32r/xm-m32r.h delete mode 100755 gcc/config/m68k/3b1.h delete mode 100755 gcc/config/m68k/3b1g.h delete mode 100755 gcc/config/m68k/a-ux.h delete mode 100755 gcc/config/m68k/altos3068.h delete mode 100755 gcc/config/m68k/amix.h delete mode 100755 gcc/config/m68k/apollo68.h delete mode 100755 gcc/config/m68k/atari.h delete mode 100755 gcc/config/m68k/aux-crt1.c delete mode 100755 gcc/config/m68k/aux-crt2.asm delete mode 100755 gcc/config/m68k/aux-crtn.asm delete mode 100755 gcc/config/m68k/aux-exit.c delete mode 100755 gcc/config/m68k/aux-low.gld delete mode 100755 gcc/config/m68k/aux-mcount.c delete mode 100755 gcc/config/m68k/auxas.h delete mode 100755 gcc/config/m68k/auxgas.h delete mode 100755 gcc/config/m68k/auxgld.h delete mode 100755 gcc/config/m68k/auxld.h delete mode 100755 gcc/config/m68k/ccur-GAS.h delete mode 100755 gcc/config/m68k/coff.h delete mode 100755 gcc/config/m68k/crds.h delete mode 100755 gcc/config/m68k/ctix.h delete mode 100755 gcc/config/m68k/dpx2.h delete mode 100755 gcc/config/m68k/dpx2.ifile delete mode 100755 gcc/config/m68k/dpx2cdbx.h delete mode 100755 gcc/config/m68k/dpx2g.h delete mode 100755 gcc/config/m68k/fpgnulib.c delete mode 100755 gcc/config/m68k/hp2bsd.h delete mode 100755 gcc/config/m68k/hp310.h delete mode 100755 gcc/config/m68k/hp310g.h delete mode 100755 gcc/config/m68k/hp320.h delete mode 100755 gcc/config/m68k/hp320g.h delete mode 100755 gcc/config/m68k/hp3bsd.h delete mode 100755 gcc/config/m68k/hp3bsd44.h delete mode 100755 gcc/config/m68k/hpux7.h delete mode 100755 gcc/config/m68k/isi-nfp.h delete mode 100755 gcc/config/m68k/isi.h delete mode 100755 gcc/config/m68k/lb1sf68.asm delete mode 100755 gcc/config/m68k/lb1sun3.asm delete mode 100755 gcc/config/m68k/linux-aout.h delete mode 100755 gcc/config/m68k/linux.h delete mode 100755 gcc/config/m68k/lynx-ng.h delete mode 100755 gcc/config/m68k/lynx.h delete mode 100755 gcc/config/m68k/m68020-elf.h delete mode 100755 gcc/config/m68k/m68360-coff.h delete mode 100755 gcc/config/m68k/m68360-none.h delete mode 100755 gcc/config/m68k/m68k-aout.h delete mode 100755 gcc/config/m68k/m68k-coff.h delete mode 100755 gcc/config/m68k/m68k-none.h delete mode 100755 gcc/config/m68k/m68k-psos.h delete mode 100755 gcc/config/m68k/m68k.c delete mode 100755 gcc/config/m68k/m68k.h delete mode 100755 gcc/config/m68k/m68k.md delete mode 100755 gcc/config/m68k/m68kelf.h delete mode 100755 gcc/config/m68k/m68kemb.h delete mode 100755 gcc/config/m68k/m68kv4.h delete mode 100755 gcc/config/m68k/mot3300-crt0.S delete mode 100755 gcc/config/m68k/mot3300.h delete mode 100755 gcc/config/m68k/mot3300Mcrt0.S delete mode 100755 gcc/config/m68k/netbsd.h delete mode 100755 gcc/config/m68k/news.h delete mode 100755 gcc/config/m68k/news3.h delete mode 100755 gcc/config/m68k/news3gas.h delete mode 100755 gcc/config/m68k/newsgas.h delete mode 100755 gcc/config/m68k/next.h delete mode 100755 gcc/config/m68k/next21.h delete mode 100755 gcc/config/m68k/os68000.h delete mode 100755 gcc/config/m68k/ose68k.h delete mode 100755 gcc/config/m68k/pbb.h delete mode 100755 gcc/config/m68k/plexus.h delete mode 100755 gcc/config/m68k/rtems.h delete mode 100755 gcc/config/m68k/sgs.h delete mode 100755 gcc/config/m68k/st2000.h delete mode 100755 gcc/config/m68k/sun2.h delete mode 100755 gcc/config/m68k/sun2o4.h delete mode 100755 gcc/config/m68k/sun3.h delete mode 100755 gcc/config/m68k/sun3mach.h delete mode 100755 gcc/config/m68k/sun3n.h delete mode 100755 gcc/config/m68k/sun3n3.h delete mode 100755 gcc/config/m68k/sun3o3.h delete mode 100755 gcc/config/m68k/t-adobe delete mode 100755 gcc/config/m68k/t-aux delete mode 100755 gcc/config/m68k/t-linux delete mode 100755 gcc/config/m68k/t-linux-aout delete mode 100755 gcc/config/m68k/t-lynx delete mode 100755 gcc/config/m68k/t-m68kbare delete mode 100755 gcc/config/m68k/t-m68kelf delete mode 100755 gcc/config/m68k/t-mot3300 delete mode 100755 gcc/config/m68k/t-mot3300-gald delete mode 100755 gcc/config/m68k/t-mot3300-gas delete mode 100755 gcc/config/m68k/t-mot3300-gld delete mode 100755 gcc/config/m68k/t-next delete mode 100755 gcc/config/m68k/t-ose68 delete mode 100755 gcc/config/m68k/t-vxworks68 delete mode 100755 gcc/config/m68k/tower-as.h delete mode 100755 gcc/config/m68k/tower.h delete mode 100755 gcc/config/m68k/vxm68k.h delete mode 100755 gcc/config/m68k/x-alloca-c delete mode 100755 gcc/config/m68k/x-amix delete mode 100755 gcc/config/m68k/x-apollo68 delete mode 100755 gcc/config/m68k/x-apollo68v delete mode 100755 gcc/config/m68k/x-ccur delete mode 100755 gcc/config/m68k/x-crds delete mode 100755 gcc/config/m68k/x-dpx2 delete mode 100755 gcc/config/m68k/x-hp2bsd delete mode 100755 gcc/config/m68k/x-hp320 delete mode 100755 gcc/config/m68k/x-hp320g delete mode 100755 gcc/config/m68k/x-hp3bsd44 delete mode 100755 gcc/config/m68k/x-mot3300 delete mode 100755 gcc/config/m68k/x-mot3300-gas delete mode 100755 gcc/config/m68k/x-next delete mode 100755 gcc/config/m68k/x-sun3 delete mode 100755 gcc/config/m68k/x-tower delete mode 100755 gcc/config/m68k/xm-3b1.h delete mode 100755 gcc/config/m68k/xm-altos3068.h delete mode 100755 gcc/config/m68k/xm-amix.h delete mode 100755 gcc/config/m68k/xm-atari.h delete mode 100755 gcc/config/m68k/xm-aux.h delete mode 100755 gcc/config/m68k/xm-crds.h delete mode 100755 gcc/config/m68k/xm-hp320.h delete mode 100755 gcc/config/m68k/xm-linux.h delete mode 100755 gcc/config/m68k/xm-lynx.h delete mode 100755 gcc/config/m68k/xm-m68k.h delete mode 100755 gcc/config/m68k/xm-m68kv.h delete mode 100755 gcc/config/m68k/xm-mot3300.h delete mode 100755 gcc/config/m68k/xm-netbsd.h delete mode 100755 gcc/config/m68k/xm-next.h delete mode 100755 gcc/config/m68k/xm-plexus.h delete mode 100755 gcc/config/m68k/xm-sun3.h delete mode 100755 gcc/config/m68k/xm-tower.h delete mode 100755 gcc/config/m88k/dgux.h delete mode 100755 gcc/config/m88k/dgux.ld delete mode 100755 gcc/config/m88k/dguxbcs.h delete mode 100755 gcc/config/m88k/dolph.h delete mode 100755 gcc/config/m88k/dolphin.ld delete mode 100755 gcc/config/m88k/luna.h delete mode 100755 gcc/config/m88k/m88k-aout.h delete mode 100755 gcc/config/m88k/m88k-coff.h delete mode 100755 gcc/config/m88k/m88k-move.sh delete mode 100755 gcc/config/m88k/m88k.c delete mode 100755 gcc/config/m88k/m88k.h delete mode 100755 gcc/config/m88k/m88k.md delete mode 100755 gcc/config/m88k/sysv3.h delete mode 100755 gcc/config/m88k/sysv4.h delete mode 100755 gcc/config/m88k/t-bug delete mode 100755 gcc/config/m88k/t-dgux delete mode 100755 gcc/config/m88k/t-dgux-gas delete mode 100755 gcc/config/m88k/t-dguxbcs delete mode 100755 gcc/config/m88k/t-luna delete mode 100755 gcc/config/m88k/t-luna-gas delete mode 100755 gcc/config/m88k/t-m88k delete mode 100755 gcc/config/m88k/t-m88k-gas delete mode 100755 gcc/config/m88k/t-sysv4 delete mode 100755 gcc/config/m88k/tekXD88.h delete mode 100755 gcc/config/m88k/tekXD88.ld delete mode 100755 gcc/config/m88k/x-dgux delete mode 100755 gcc/config/m88k/x-dguxbcs delete mode 100755 gcc/config/m88k/x-dolph delete mode 100755 gcc/config/m88k/x-sysv3 delete mode 100755 gcc/config/m88k/x-sysv4 delete mode 100755 gcc/config/m88k/x-tekXD88 delete mode 100755 gcc/config/m88k/xm-m88k.h delete mode 100755 gcc/config/m88k/xm-sysv3.h delete mode 100755 gcc/config/mips/abi64.h delete mode 100755 gcc/config/mips/big.h delete mode 100755 gcc/config/mips/bsd-4.h delete mode 100755 gcc/config/mips/bsd-5.h delete mode 100755 gcc/config/mips/cross64.h delete mode 100755 gcc/config/mips/dec-bsd.h delete mode 100755 gcc/config/mips/dec-osf1.h delete mode 100755 gcc/config/mips/ecoff.h delete mode 100755 gcc/config/mips/ecoffl.h delete mode 100755 gcc/config/mips/elf.h delete mode 100755 gcc/config/mips/elf5400.h delete mode 100755 gcc/config/mips/elf64.h delete mode 100755 gcc/config/mips/elfb4100.h delete mode 100755 gcc/config/mips/elfb4300.h delete mode 100755 gcc/config/mips/elfb5000.h delete mode 100755 gcc/config/mips/elfl.h delete mode 100755 gcc/config/mips/elfl4100.h delete mode 100755 gcc/config/mips/elfl4300.h delete mode 100755 gcc/config/mips/elfl5000.h delete mode 100755 gcc/config/mips/elfl64.h delete mode 100755 gcc/config/mips/elflorion.h delete mode 100755 gcc/config/mips/elforion.h delete mode 100755 gcc/config/mips/gnu.h delete mode 100755 gcc/config/mips/iris3.h delete mode 100755 gcc/config/mips/iris4.h delete mode 100755 gcc/config/mips/iris4loser.h delete mode 100755 gcc/config/mips/iris5.h delete mode 100755 gcc/config/mips/iris5gas.h delete mode 100755 gcc/config/mips/iris6.h delete mode 100755 gcc/config/mips/linux.h delete mode 100755 gcc/config/mips/little.h delete mode 100755 gcc/config/mips/mips-5.h delete mode 100755 gcc/config/mips/mips.c delete mode 100755 gcc/config/mips/mips.h delete mode 100755 gcc/config/mips/mips.md delete mode 100755 gcc/config/mips/mips16.S delete mode 100755 gcc/config/mips/ncd.h delete mode 100755 gcc/config/mips/netbsd.h delete mode 100755 gcc/config/mips/news4.h delete mode 100755 gcc/config/mips/news5.h delete mode 100755 gcc/config/mips/nws3250v4.h delete mode 100755 gcc/config/mips/osfrose.h delete mode 100755 gcc/config/mips/r3900.h delete mode 100755 gcc/config/mips/rtems64.h delete mode 100755 gcc/config/mips/sni-gas.h delete mode 100755 gcc/config/mips/sni-svr4.h delete mode 100755 gcc/config/mips/svr3-4.h delete mode 100755 gcc/config/mips/svr3-5.h delete mode 100755 gcc/config/mips/svr4-4.h delete mode 100755 gcc/config/mips/svr4-5.h delete mode 100755 gcc/config/mips/svr4-t.h delete mode 100755 gcc/config/mips/t-biendian delete mode 100755 gcc/config/mips/t-bsd delete mode 100755 gcc/config/mips/t-bsd-gas delete mode 100755 gcc/config/mips/t-cross64 delete mode 100755 gcc/config/mips/t-ecoff delete mode 100755 gcc/config/mips/t-elf delete mode 100755 gcc/config/mips/t-iris6 delete mode 100755 gcc/config/mips/t-lsi delete mode 100755 gcc/config/mips/t-mips delete mode 100755 gcc/config/mips/t-mips-gas delete mode 100755 gcc/config/mips/t-ncd delete mode 100755 gcc/config/mips/t-osfrose delete mode 100755 gcc/config/mips/t-r3900 delete mode 100755 gcc/config/mips/t-svr3 delete mode 100755 gcc/config/mips/t-svr3-gas delete mode 100755 gcc/config/mips/t-svr4 delete mode 100755 gcc/config/mips/t-svr4-gas delete mode 100755 gcc/config/mips/t-ultrix delete mode 100755 gcc/config/mips/t-vr4100 delete mode 100755 gcc/config/mips/t-vr4300 delete mode 100755 gcc/config/mips/t-vr5000 delete mode 100755 gcc/config/mips/ultrix.h delete mode 100755 gcc/config/mips/vxworks.h delete mode 100755 gcc/config/mips/x-dec-osf1 delete mode 100755 gcc/config/mips/x-iris delete mode 100755 gcc/config/mips/x-iris3 delete mode 100755 gcc/config/mips/x-iris6 delete mode 100755 gcc/config/mips/x-mips delete mode 100755 gcc/config/mips/x-netbsd delete mode 100755 gcc/config/mips/x-nws3250v4 delete mode 100755 gcc/config/mips/x-osfrose delete mode 100755 gcc/config/mips/x-sni-svr4 delete mode 100755 gcc/config/mips/x-sony delete mode 100755 gcc/config/mips/x-sysv delete mode 100755 gcc/config/mips/x-ultrix delete mode 100755 gcc/config/mips/xm-iris3.h delete mode 100755 gcc/config/mips/xm-iris4.h delete mode 100755 gcc/config/mips/xm-iris5.h delete mode 100755 gcc/config/mips/xm-iris6.h delete mode 100755 gcc/config/mips/xm-mips.h delete mode 100755 gcc/config/mips/xm-netbsd.h delete mode 100755 gcc/config/mips/xm-news.h delete mode 100755 gcc/config/mips/xm-nws3250v4.h delete mode 100755 gcc/config/mips/xm-sysv.h delete mode 100755 gcc/config/mips/xm-sysv4.h delete mode 100755 gcc/config/mn10200/divmod.c delete mode 100755 gcc/config/mn10200/lib1funcs.asm delete mode 100755 gcc/config/mn10200/mn10200.c delete mode 100755 gcc/config/mn10200/mn10200.h delete mode 100755 gcc/config/mn10200/mn10200.md delete mode 100755 gcc/config/mn10200/mn10200_020422.h delete mode 100755 gcc/config/mn10200/t-mn10200 delete mode 100755 gcc/config/mn10200/udivmod.c delete mode 100755 gcc/config/mn10200/udivmodsi4.c delete mode 100755 gcc/config/mn10200/xm-mn10200.h delete mode 100755 gcc/config/mn10300/mn10300.c delete mode 100755 gcc/config/mn10300/mn10300.h delete mode 100755 gcc/config/mn10300/mn10300.md delete mode 100755 gcc/config/mn10300/mn10300_020422.h delete mode 100755 gcc/config/mn10300/t-mn10300 delete mode 100755 gcc/config/mn10300/xm-mn10300.h delete mode 100755 gcc/config/msdos/configur.bat delete mode 100755 gcc/config/msdos/libgcc.mak delete mode 100755 gcc/config/msdos/mklibgcc.c delete mode 100755 gcc/config/msdos/top.sed delete mode 100755 gcc/config/netbsd.h delete mode 100755 gcc/config/netware.h delete mode 100755 gcc/config/nextstep.c delete mode 100755 gcc/config/nextstep.h delete mode 100755 gcc/config/nextstep21.h delete mode 100755 gcc/config/ns32k/encore.h delete mode 100755 gcc/config/ns32k/genix.h delete mode 100755 gcc/config/ns32k/merlin.h delete mode 100755 gcc/config/ns32k/netbsd.h delete mode 100755 gcc/config/ns32k/ns32k.c delete mode 100755 gcc/config/ns32k/ns32k.h delete mode 100755 gcc/config/ns32k/ns32k.md delete mode 100755 gcc/config/ns32k/pc532-mach.h delete mode 100755 gcc/config/ns32k/pc532-min.h delete mode 100755 gcc/config/ns32k/pc532.h delete mode 100755 gcc/config/ns32k/sequent.h delete mode 100755 gcc/config/ns32k/tek6000.h delete mode 100755 gcc/config/ns32k/tek6100.h delete mode 100755 gcc/config/ns32k/tek6200.h delete mode 100755 gcc/config/ns32k/x-genix delete mode 100755 gcc/config/ns32k/xm-genix.h delete mode 100755 gcc/config/ns32k/xm-netbsd.h delete mode 100755 gcc/config/ns32k/xm-ns32k.h delete mode 100755 gcc/config/ns32k/xm-pc532-min.h delete mode 100755 gcc/config/pa/ee.asm delete mode 100755 gcc/config/pa/ee_fp.asm delete mode 100755 gcc/config/pa/lib1funcs.asm delete mode 100755 gcc/config/pa/lib2funcs.asm delete mode 100755 gcc/config/pa/pa-gas.h delete mode 100755 gcc/config/pa/pa-hiux.h delete mode 100755 gcc/config/pa/pa-hpux.h delete mode 100755 gcc/config/pa/pa-hpux10.h delete mode 100755 gcc/config/pa/pa-hpux11.h delete mode 100755 gcc/config/pa/pa-hpux7.h delete mode 100755 gcc/config/pa/pa-hpux9.h delete mode 100755 gcc/config/pa/pa-oldas.h delete mode 100755 gcc/config/pa/pa-osf.h delete mode 100755 gcc/config/pa/pa-pro-end.h delete mode 100755 gcc/config/pa/pa-pro.h delete mode 100755 gcc/config/pa/pa.c delete mode 100755 gcc/config/pa/pa.h delete mode 100755 gcc/config/pa/pa.md delete mode 100755 gcc/config/pa/pa1.h delete mode 100755 gcc/config/pa/rtems.h delete mode 100755 gcc/config/pa/t-dce-thr delete mode 100755 gcc/config/pa/t-pa delete mode 100755 gcc/config/pa/t-pro delete mode 100755 gcc/config/pa/x-pa delete mode 100755 gcc/config/pa/x-pa-hpux delete mode 100755 gcc/config/pa/xm-pa.h delete mode 100755 gcc/config/pa/xm-pahpux.h delete mode 100755 gcc/config/pa/xm-papro.h delete mode 100755 gcc/config/pdp11/2bsd.h delete mode 100755 gcc/config/pdp11/pdp11.c delete mode 100755 gcc/config/pdp11/pdp11.h delete mode 100755 gcc/config/pdp11/pdp11.md delete mode 100755 gcc/config/pdp11/t-pdp11 delete mode 100755 gcc/config/pdp11/xm-pdp11.h delete mode 100755 gcc/config/psos.h delete mode 100755 gcc/config/ptx4.h delete mode 100755 gcc/config/pyr/pyr.c delete mode 100755 gcc/config/pyr/pyr.h delete mode 100755 gcc/config/pyr/pyr.md delete mode 100755 gcc/config/pyr/x-pyr delete mode 100755 gcc/config/pyr/xm-pyr.h delete mode 100755 gcc/config/romp/romp.c delete mode 100755 gcc/config/romp/romp.h delete mode 100755 gcc/config/romp/romp.md delete mode 100755 gcc/config/romp/x-mach delete mode 100755 gcc/config/romp/x-romp delete mode 100755 gcc/config/romp/xm-romp.h delete mode 100755 gcc/config/rs6000/aix31.h delete mode 100755 gcc/config/rs6000/aix3newas.h delete mode 100755 gcc/config/rs6000/aix41.h delete mode 100755 gcc/config/rs6000/aix43.h delete mode 100755 gcc/config/rs6000/beos.h delete mode 100755 gcc/config/rs6000/cygwin.h delete mode 100755 gcc/config/rs6000/eabi-ci.asm delete mode 100755 gcc/config/rs6000/eabi-cn.asm delete mode 100755 gcc/config/rs6000/eabi-ctors.c delete mode 100755 gcc/config/rs6000/eabi.asm delete mode 100755 gcc/config/rs6000/eabi.h delete mode 100755 gcc/config/rs6000/eabiaix.h delete mode 100755 gcc/config/rs6000/eabile.h delete mode 100755 gcc/config/rs6000/eabilesim.h delete mode 100755 gcc/config/rs6000/eabisim.h delete mode 100755 gcc/config/rs6000/linux.h delete mode 100755 gcc/config/rs6000/lynx.h delete mode 100755 gcc/config/rs6000/mach.h delete mode 100755 gcc/config/rs6000/milli.exp delete mode 100755 gcc/config/rs6000/netware.h delete mode 100755 gcc/config/rs6000/nt-ci.asm delete mode 100755 gcc/config/rs6000/nt-cn.asm delete mode 100755 gcc/config/rs6000/ntstack.asm delete mode 100755 gcc/config/rs6000/powerpc.h delete mode 100755 gcc/config/rs6000/rs6000.c delete mode 100755 gcc/config/rs6000/rs6000.h delete mode 100755 gcc/config/rs6000/rs6000.md delete mode 100755 gcc/config/rs6000/rtems.h delete mode 100755 gcc/config/rs6000/sol-c0.c delete mode 100755 gcc/config/rs6000/sol-ci.asm delete mode 100755 gcc/config/rs6000/sol-cn.asm delete mode 100755 gcc/config/rs6000/sol2.h delete mode 100755 gcc/config/rs6000/sysv4.h delete mode 100755 gcc/config/rs6000/sysv4le.h delete mode 100755 gcc/config/rs6000/t-aix43 delete mode 100755 gcc/config/rs6000/t-beos delete mode 100755 gcc/config/rs6000/t-newas delete mode 100755 gcc/config/rs6000/t-ppc delete mode 100755 gcc/config/rs6000/t-ppccomm delete mode 100755 gcc/config/rs6000/t-ppcgas delete mode 100755 gcc/config/rs6000/t-ppcos delete mode 100755 gcc/config/rs6000/t-rs6000 delete mode 100755 gcc/config/rs6000/t-vxworks delete mode 100755 gcc/config/rs6000/t-winnt delete mode 100755 gcc/config/rs6000/t-xnewas delete mode 100755 gcc/config/rs6000/t-xrs6000 delete mode 100755 gcc/config/rs6000/tramp.asm delete mode 100755 gcc/config/rs6000/vxppc.h delete mode 100755 gcc/config/rs6000/vxppcle.h delete mode 100755 gcc/config/rs6000/win-nt.h delete mode 100755 gcc/config/rs6000/x-aix31 delete mode 100755 gcc/config/rs6000/x-aix41 delete mode 100755 gcc/config/rs6000/x-aix43 delete mode 100755 gcc/config/rs6000/x-beos delete mode 100755 gcc/config/rs6000/x-cygwin delete mode 100755 gcc/config/rs6000/x-lynx delete mode 100755 gcc/config/rs6000/x-mach delete mode 100755 gcc/config/rs6000/x-rs6000 delete mode 100755 gcc/config/rs6000/x-sysv4 delete mode 100755 gcc/config/rs6000/xm-beos.h delete mode 100755 gcc/config/rs6000/xm-cygwin.h delete mode 100755 gcc/config/rs6000/xm-lynx.h delete mode 100755 gcc/config/rs6000/xm-mach.h delete mode 100755 gcc/config/rs6000/xm-rs6000.h delete mode 100755 gcc/config/rs6000/xm-sysv4.h delete mode 100755 gcc/config/sh/elf.h delete mode 100755 gcc/config/sh/lib1funcs.asm delete mode 100755 gcc/config/sh/rtems.h delete mode 100755 gcc/config/sh/rtemself.h delete mode 100755 gcc/config/sh/sh.c delete mode 100755 gcc/config/sh/sh.h delete mode 100755 gcc/config/sh/sh.md delete mode 100755 gcc/config/sh/t-sh delete mode 100755 gcc/config/sh/xm-sh.h delete mode 100755 gcc/config/sparc/aout.h delete mode 100755 gcc/config/sparc/bsd.h delete mode 100755 gcc/config/sparc/elf.h delete mode 100755 gcc/config/sparc/gmon-sol2.c delete mode 100755 gcc/config/sparc/hal.h delete mode 100755 gcc/config/sparc/lb1spc.asm delete mode 100755 gcc/config/sparc/lb1spl.asm delete mode 100755 gcc/config/sparc/linux-aout.h delete mode 100755 gcc/config/sparc/linux.h delete mode 100755 gcc/config/sparc/linux64.h delete mode 100755 gcc/config/sparc/lite.h delete mode 100755 gcc/config/sparc/litecoff.h delete mode 100755 gcc/config/sparc/liteelf.h delete mode 100755 gcc/config/sparc/lynx-ng.h delete mode 100755 gcc/config/sparc/lynx.h delete mode 100755 gcc/config/sparc/netbsd.h delete mode 100755 gcc/config/sparc/pbd.h delete mode 100755 gcc/config/sparc/rtems.h delete mode 100755 gcc/config/sparc/sol2-c1.asm delete mode 100755 gcc/config/sparc/sol2-ci.asm delete mode 100755 gcc/config/sparc/sol2-cn.asm delete mode 100755 gcc/config/sparc/sol2-g1.asm delete mode 100755 gcc/config/sparc/sol2-sld-64.h delete mode 100755 gcc/config/sparc/sol2-sld.h delete mode 100755 gcc/config/sparc/sol2.h delete mode 100755 gcc/config/sparc/sp64-aout.h delete mode 100755 gcc/config/sparc/sp64-elf.h delete mode 100755 gcc/config/sparc/sp64-elf_020422.h delete mode 100755 gcc/config/sparc/sp86x-aout.h delete mode 100755 gcc/config/sparc/sp86x-elf.h delete mode 100755 gcc/config/sparc/sparc.c delete mode 100755 gcc/config/sparc/sparc.h delete mode 100755 gcc/config/sparc/sparc.md delete mode 100755 gcc/config/sparc/splet.h delete mode 100755 gcc/config/sparc/sun4gas.h delete mode 100755 gcc/config/sparc/sun4o3.h delete mode 100755 gcc/config/sparc/sunos4.h delete mode 100755 gcc/config/sparc/sysv4.h delete mode 100755 gcc/config/sparc/t-elf delete mode 100755 gcc/config/sparc/t-halos delete mode 100755 gcc/config/sparc/t-linux delete mode 100755 gcc/config/sparc/t-linux64 delete mode 100755 gcc/config/sparc/t-sol2 delete mode 100755 gcc/config/sparc/t-sol2-64 delete mode 100755 gcc/config/sparc/t-sp64 delete mode 100755 gcc/config/sparc/t-sp86x delete mode 100755 gcc/config/sparc/t-sparcbare delete mode 100755 gcc/config/sparc/t-sparclite delete mode 100755 gcc/config/sparc/t-splet delete mode 100755 gcc/config/sparc/t-sunos40 delete mode 100755 gcc/config/sparc/t-sunos41 delete mode 100755 gcc/config/sparc/t-vxsparc delete mode 100755 gcc/config/sparc/vxsim.h delete mode 100755 gcc/config/sparc/vxsparc.h delete mode 100755 gcc/config/sparc/x-sysv4 delete mode 100755 gcc/config/sparc/xm-linux.h delete mode 100755 gcc/config/sparc/xm-lynx.h delete mode 100755 gcc/config/sparc/xm-netbsd.h delete mode 100755 gcc/config/sparc/xm-pbd.h delete mode 100755 gcc/config/sparc/xm-sol2.h delete mode 100755 gcc/config/sparc/xm-sp64.h delete mode 100755 gcc/config/sparc/xm-sparc.h delete mode 100755 gcc/config/sparc/xm-sysv4-64.h delete mode 100755 gcc/config/sparc/xm-sysv4.h delete mode 100755 gcc/config/spur/spur.c delete mode 100755 gcc/config/spur/spur.h delete mode 100755 gcc/config/spur/spur.md delete mode 100755 gcc/config/spur/xm-spur.h delete mode 100755 gcc/config/svr3.h delete mode 100755 gcc/config/svr4.h delete mode 100755 gcc/config/t-gnu delete mode 100755 gcc/config/t-libc-ok delete mode 100755 gcc/config/t-linux delete mode 100755 gcc/config/t-linux-aout delete mode 100755 gcc/config/t-linux-gnulibc1 delete mode 100755 gcc/config/t-netbsd delete mode 100755 gcc/config/t-rtems delete mode 100755 gcc/config/t-svr4 delete mode 100755 gcc/config/tahoe/harris.h delete mode 100755 gcc/config/tahoe/tahoe.c delete mode 100755 gcc/config/tahoe/tahoe.h delete mode 100755 gcc/config/tahoe/tahoe.md delete mode 100755 gcc/config/tahoe/xm-tahoe.h delete mode 100755 gcc/config/tm-dwarf2.h delete mode 100755 gcc/config/v850/lib1funcs.asm delete mode 100755 gcc/config/v850/t-v850 delete mode 100755 gcc/config/v850/v850.c delete mode 100755 gcc/config/v850/v850.h delete mode 100755 gcc/config/v850/v850.md delete mode 100755 gcc/config/v850/v850e.h delete mode 100755 gcc/config/v850/v850ea.h delete mode 100755 gcc/config/v850/xm-v850.h delete mode 100755 gcc/config/vax/netbsd.h delete mode 100755 gcc/config/vax/ultrix.h delete mode 100755 gcc/config/vax/vax.c delete mode 100755 gcc/config/vax/vax.h delete mode 100755 gcc/config/vax/vax.md delete mode 100755 gcc/config/vax/vaxv.h delete mode 100755 gcc/config/vax/vms.h delete mode 100755 gcc/config/vax/x-vax delete mode 100755 gcc/config/vax/xm-vax.h delete mode 100755 gcc/config/vax/xm-vaxv.h delete mode 100755 gcc/config/vax/xm-vms.h delete mode 100755 gcc/config/we32k/we32k.c delete mode 100755 gcc/config/we32k/we32k.h delete mode 100755 gcc/config/we32k/we32k.md delete mode 100755 gcc/config/we32k/x-we32k delete mode 100755 gcc/config/we32k/xm-we32k.h delete mode 100755 gcc/config/winnt/config-nt.bat delete mode 100755 gcc/config/winnt/config-nt.sed delete mode 100755 gcc/config/winnt/dirent.c delete mode 100755 gcc/config/winnt/dirent.h delete mode 100755 gcc/config/winnt/fixinc-nt.c delete mode 100755 gcc/config/winnt/headers.mak delete mode 100755 gcc/config/winnt/ld.c delete mode 100755 gcc/config/winnt/libgcc.mak delete mode 100755 gcc/config/winnt/mklibgcc.c delete mode 100755 gcc/config/winnt/oldnames.c delete mode 100755 gcc/config/winnt/spawnv.c delete mode 100755 gcc/config/winnt/win-nt.h delete mode 100755 gcc/config/winnt/x-winnt delete mode 100755 gcc/config/winnt/xm-winnt.h delete mode 100755 gcc/config/x-linux delete mode 100755 gcc/config/x-linux-aout delete mode 100755 gcc/config/x-lynx delete mode 100755 gcc/config/x-svr4 delete mode 100755 gcc/config/xm-alloca.h delete mode 100755 gcc/config/xm-freebsd.h delete mode 100755 gcc/config/xm-gnu.h delete mode 100755 gcc/config/xm-linux.h delete mode 100755 gcc/config/xm-netbsd.h delete mode 100755 gcc/config/xm-siglist.h delete mode 100755 gcc/config/xm-std32.h delete mode 100755 gcc/config/xm-svr3.h delete mode 100755 gcc/config/xm-svr4.h delete mode 100755 gcc/config/z8k/lib2funcs.c delete mode 100755 gcc/config/z8k/t-z8k delete mode 100755 gcc/config/z8k/xm-z8k.h delete mode 100755 gcc/config/z8k/z8k.c delete mode 100755 gcc/config/z8k/z8k.h delete mode 100755 gcc/config/z8k/z8k.md (limited to 'gcc') diff --git a/gcc/config/1750a/1750a.c b/gcc/config/1750a/1750a.c deleted file mode 100755 index 134f69d..0000000 --- a/gcc/config/1750a/1750a.c +++ /dev/null @@ -1,734 +0,0 @@ -/* Subroutines for insn-output.c for MIL-STD-1750. - Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. - Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define __datalbl -#include "config.h" -#include -#include -#include "rtl.h" -#include "tree.h" -#include "expr.h" -#define HAVE_cc0 -#include "conditions.h" -#include "real.h" -#include "regs.h" - -struct datalabel_array datalbl[DATALBL_ARRSIZ]; -int datalbl_ndx = -1; -struct jumplabel_array jmplbl[JMPLBL_ARRSIZ]; -int jmplbl_ndx = -1; -int label_pending = 0, program_counter = 0; -enum section current_section = Normal; -char *sectname[4] = -{"Init", "Normal", "Konst", "Static"}; - -int -notice_update_cc (exp) - rtx exp; -{ - if (GET_CODE (exp) == SET) - { - enum rtx_code src_code = GET_CODE (SET_SRC (exp)); - /* Jumps do not alter the cc's. */ - if (SET_DEST (exp) == pc_rtx) - return; - /* Moving a register or constant into memory doesn't alter the cc's. */ - if (GET_CODE (SET_DEST (exp)) == MEM - && (src_code == REG || src_code == CONST_INT)) - return; - /* Function calls clobber the cc's. */ - if (src_code == CALL) - { - CC_STATUS_INIT; - return; - } - /* Emulated longword bit-ops leave cc's incorrect */ - if (GET_MODE (SET_DEST (exp)) == HImode ? - src_code == AND || src_code == IOR || - src_code == XOR || src_code == NOT : 0) - { - CC_STATUS_INIT; - return; - } - /* Tests and compares set the cc's in predictable ways. */ - if (SET_DEST (exp) == cc0_rtx) - { - CC_STATUS_INIT; - cc_status.value1 = SET_SRC (exp); - return; - } - /* Anything else will set cc_status. */ - cc_status.flags = CC_NO_OVERFLOW; - cc_status.value1 = SET_SRC (exp); - cc_status.value2 = SET_DEST (exp); - return; - } - else if (GET_CODE (exp) == PARALLEL - && GET_CODE (XVECEXP (exp, 0, 0)) == SET) - { - if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) - return; - if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) - { - CC_STATUS_INIT; - cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); - return; - } - CC_STATUS_INIT; - } - else - { - CC_STATUS_INIT; - } -} - - -rtx -function_arg (cum, mode, type, named) - int cum; - enum machine_mode mode; - tree type; - int named; -{ - int size; - - if (MUST_PASS_IN_STACK (mode, type)) - return (rtx) 0; - if (mode == BLKmode) - size = int_size_in_bytes (type); - else - size = GET_MODE_SIZE (mode); - if (cum + size < 12) - return gen_rtx (REG, mode, cum); - else - return (rtx) 0; -} - - -double -get_double (x) - rtx x; -{ - union - { - double d; - long i[2]; - } - du; - - du.i[0] = CONST_DOUBLE_LOW (x); - du.i[1] = CONST_DOUBLE_HIGH (x); - return du.d; -} - -char * -float_label (code, value) - char code; - double value; -{ - int i = 1; - static char label[32]; - char *p; - - label[0] = code; - p = label + 1; - sprintf (p, "%lf", value); - while (*p) - { - *p = (*p == '+') ? 'p' : - (*p == '-') ? 'm' : *p; - p++; - } - return xstrdup (label); -} - - -char * -movcnt_regno_adjust (op) - rtx *op; -{ - static char outstr[80]; - int op0r = REGNO (op[0]), op1r = REGNO (op[1]), op2r = REGNO (op[2]); -#define dstreg op0r -#define srcreg op1r -#define cntreg op2r -#define cntreg_1750 (op0r + 1) - - if (cntreg == cntreg_1750) - sprintf (outstr, "mov r%d,r%d", op0r, op1r); - else if (dstreg + 1 == srcreg && cntreg > srcreg) - sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op2r, op1r, op0r, op2r); - else if (dstreg == cntreg + 1) - sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op2r, op2r, op1r); - else if (dstreg == srcreg + 1) - sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d", - op0r, op1r, op0r, op2r, op1r, op2r); - else if (cntreg + 1 == srcreg) - sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d", - op2r, op1r, op0r, op2r, op2r, op0r); - else if (cntreg == srcreg + 1) - sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op1r, op1r, op0r); - else - sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d\n\txwr r%d,r%d", - op2r, cntreg_1750, op0r, op1r, op2r, cntreg_1750); - return outstr; -} - -char * -mod_regno_adjust (instr, op) - char *instr; - rtx *op; -{ - static char outstr[40]; - char *r = (!strncmp (instr, "dvr", 3) ? "r" : ""); - int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1; - - if (modregno_gcc == modregno_1750 - || (reg_renumber != NULL - && reg_renumber[modregno_gcc] >= 0 - && reg_renumber[modregno_gcc] == reg_renumber[modregno_1750])) - sprintf (outstr, "%s r%%0,%s%%2", instr, r); - else - sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d", - modregno_gcc, modregno_1750, instr, r, modregno_1750, - modregno_gcc); - return outstr; -} - - -/* Check if op is a valid memory operand for 1750A Load/Store instructions - (memory indirection permitted.) */ - -int -memop_valid (op) - rtx op; -{ - static int recurred = 0; - int valid; - - if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode - && GET_MODE (op) != QImode) - return 0; - switch (GET_CODE (op)) - { - case MEM: - if (!recurred && GET_CODE (XEXP (op, 0)) == REG) - return 1; - case MINUS: - case MULT: - case DIV: - return 0; - case PLUS: - recurred = 1; - valid = memop_valid (XEXP (op, 0)); - if (valid) - valid = memop_valid (XEXP (op, 1)); - recurred = 0; - return valid; - case REG: - if (REGNO (op) > 0) - return 1; - return 0; - case CONST: - case CONST_INT: - case SYMBOL_REF: - case SUBREG: - return 1; - default: - printf ("memop_valid: code=%d\n", (int) GET_CODE (op)); - return 1; - } -} - - -/* predicate for the MOV instruction: */ -int -mov_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG); -} - -/* predicate for the STC instruction: */ -int -small_nonneg_const (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15) - return 1; - return 0; -} - -/* predicate for constant zero: */ -int -zero_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return op == CONST0_RTX (mode); -} - - -/* predicate for 1750 `B' addressing mode (Base Register with Offset) - memory operand */ -int -b_mode_operand (op) - rtx op; -{ - if (GET_CODE (op) == MEM) - { - rtx inner = XEXP (op, 0); - if (GET_CODE (inner) == REG && REG_OK_FOR_INDEX_P (inner)) - return 1; - if (GET_CODE (inner) == PLUS) - { - rtx plus_op0 = XEXP (inner, 0); - if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0)) - { - rtx plus_op1 = XEXP (inner, 1); - if (GET_CODE (plus_op1) == CONST_INT - && INTVAL (plus_op1) >= 0 - && INTVAL (plus_op1) <= 255) - return 1; - } - } - } - return 0; -} - - -/* Decide whether to output a conditional jump as a "Jump Conditional" - or as a "Branch Conditional": */ - -int -find_jmplbl (labelnum) - int labelnum; -{ - int i, found = 0; - - for (i = 0; i <= jmplbl_ndx; i++) - if (labelnum == jmplbl[i].num) - { - found = 1; - break; - } - if (found) - return i; - return -1; -} - -char * -branch_or_jump (condition, targetlabel_number) - char *condition; - int targetlabel_number; -{ - static char buf[30]; - int index; - - if ((index = find_jmplbl (targetlabel_number)) >= 0) - if (program_counter - jmplbl[index].pc < 128) - { - sprintf (buf, "b%s %%l0", condition); - return buf; - } - sprintf (buf, "jc %s,%%l0", condition); - return buf; -} - - -int -unsigned_comparison_operator (insn) - rtx insn; -{ - switch (GET_CODE (insn)) - { - case GEU: - case GTU: - case LEU: - case LTU: - return 1; - default: - return 0; - } -} - -int -next_cc_user_is_unsigned (insn) - rtx insn; -{ - if ( !(insn = next_cc0_user (insn))) - abort (); - else if (GET_CODE (insn) == JUMP_INSN - && GET_CODE (PATTERN (insn)) == SET - && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE) - return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn)), 0)); - else if (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SET) - return unsigned_comparison_operator (SET_SRC (PATTERN (insn))); - else - abort (); -} - - -static int addr_inc; - -/* A C compound statement to output to stdio stream STREAM the - assembler syntax for an instruction operand X. X is an RTL - expression. - - CODE is a value that can be used to specify one of several ways - of printing the operand. It is used when identical operands - must be printed differently depending on the context. CODE - comes from the `%' specification that was used to request - printing of the operand. If the specification was just `%DIGIT' - then CODE is 0; if the specification was `%LTR DIGIT' then CODE - is the ASCII code for LTR. - - If X is a register, this macro should print the register's name. - The names can be found in an array `reg_names' whose type is - `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'. - - When the machine description has a specification `%PUNCT' (a `%' - followed by a punctuation character), this macro is called with - a null pointer for X and the punctuation character for CODE. - - The 1750 specific codes are: - 'J' for the negative of a constant - 'Q' for printing addresses in B mode syntax - 'd' for the second register in a pair - 't' for the third register in a triple - 'b' for the bit number (using 1750 test bit convention) - 'B' for the bit number of the 1's complement (for bit clear) - 'w' for int - 16 -*/ - -print_operand (file, x, letter) - FILE *file; - rtx x; - int letter; -{ - switch (GET_CODE (x)) - { - case REG: - if (letter == 'd') - fprintf (file, "%d", REGNO (x) + 1); - else if (letter == 't') - fprintf (file, "%d", REGNO (x) + 2); - else - fprintf (file, "%d", REGNO (x)); - break; - - case SYMBOL_REF: - fprintf (file, "%s", XSTR (x, 0)); - if (letter == 'A') - fprintf (file, "+1"); - break; - - case LABEL_REF: - case CONST: - case MEM: - if (letter == 'Q') - { - rtx inner = XEXP (x, 0); - switch (GET_CODE (inner)) - { - case REG: - fprintf (file, "r%d,0", REGNO (inner)); - break; - case PLUS: - fprintf (file, "r%d,%d", REGNO (XEXP (inner, 0)), - INTVAL (XEXP (inner, 1))); - break; - default: - fprintf (file, "[ill Q code=%d]", GET_CODE (inner)); - } - } - else - { - addr_inc = (letter == 'A' ? 1 : 0); - output_address (XEXP (x, 0)); - } - break; - - case CONST_DOUBLE: -/* { - double value = get_double (x); - char fltstr[32]; - sprintf (fltstr, "%lf", value); - - if (letter == 'D' || letter == 'E') - { - int i, found = 0; - for (i = 0; i <= datalbl_ndx; i++) - if (strcmp (fltstr, datalbl[i].value) == 0) - { - found = 1; - break; - } - if (!found) - { - strcpy (datalbl[i = ++datalbl_ndx].value, fltstr); - datalbl[i].name = float_label (letter, value); - datalbl[i].size = (letter == 'E') ? 3 : 2; - check_section (Konst); - fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name, - (letter == 'E' ? "ef" : "f"), fltstr); - check_section (Normal); - } - } - else if (letter == 'F' || letter == 'G') - { - int i, found = 0; - for (i = 0; i <= datalbl_ndx; i++) - if (strcmp (fltstr, datalbl[i].value) == 0) - { - found = 1; - break; - } - if (!found) - { - fprintf (stderr, - "float value %lfnot found upon label reference\n", value); - strcpy (datalbl[i = ++datalbl_ndx].value, fltstr); - datalbl[i].name = float_label (letter, value); - datalbl[i].size = (letter == 'G') ? 3 : 2; - check_section (Konst); - fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name, - (letter == 'G' ? "ef" : "f"), fltstr); - check_section (Normal); - } - fprintf (file, "%s ;P_O 'F'", datalbl[i].name); - } - else - fprintf (file, " %s ;P_O cst_dbl ", fltstr); - } - */ - fprintf (file, "%lf", get_double (x)); - break; - - case CONST_INT: - if (letter == 'J') - fprintf (file, "%d", -INTVAL (x)); - else if (letter == 'b') - fprintf (file, "%d", which_bit (INTVAL (x))); - else if (letter == 'B') - fprintf (file, "%d", which_bit (~INTVAL (x))); - else if (letter == 'w') - fprintf (file, "%d", INTVAL (x) - 16); - else - fprintf (file, "%d", INTVAL (x)); - break; - - case CODE_LABEL: - fprintf (file, "L%d", XINT (x, 3)); - break; - - case CALL: - fprintf (file, "CALL nargs=%d, func is either '%s' or '%s'", - XEXP (x, 1), XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1)); - break; - - case PLUS: - { - rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1); - int op0code = GET_CODE (op0), op1code = GET_CODE (op1); - if (op1code == CONST_INT) - switch (op0code) - { - case REG: - fprintf (file, "%d,r%d ; p_o_PLUS for REG and CONST_INT", - INTVAL (op1), REGNO (op0)); - break; - case SYMBOL_REF: - fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0)); - break; - case MEM: - fprintf (file, "%d,[mem:", INTVAL (op1)); - output_address (XEXP (op0, 0)); - fprintf (file, "] ;P_O plus"); - break; - default: - fprintf (file, "p_o_PLUS UFO, code=%d, with CONST=%d", - (int) op0code, INTVAL (op1)); - } - else if (op1code == SYMBOL_REF && op0code == REG) - fprintf (file, "%s,r%d ; P_O: (plus reg sym)", - XSTR (op1, 0), REGNO (op0)); - else - fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code); - } - break; - - default: - fprintf (file, "p_o_UFO code=%d", GET_CODE (x)); - } - - addr_inc = 0; -} - -print_operand_address (file, addr) - FILE *file; - rtx addr; -{ - switch (GET_CODE (addr)) - { - case REG: - fprintf (file, "%d,r%d ; P_O_A", addr_inc, REGNO (addr)); - break; - case PLUS: - { - register rtx x = XEXP (addr, 0), y = XEXP (addr, 1); - switch (GET_CODE (x)) - { - case REG: - switch (GET_CODE (y)) - { - case CONST: - output_address (XEXP (y, 0)); - fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x)); - break; - case CONST_INT: - fprintf (file, "%d,r%d", INTVAL (y) + addr_inc, REGNO (x)); - break; - case SYMBOL_REF: - fprintf (file, "%s", XSTR (y, 0)); - if (addr_inc) - fprintf (file, "+%d", addr_inc); - fprintf (file, ",r%d ; P_O_A reg + sym", REGNO (x)); - break; - case LABEL_REF: - output_address (XEXP (y, 0)); - fprintf (file, ",r%d ; P_O_A reg + label", REGNO (x)); - break; - default: - fprintf (file, "[P_O_A reg%d+UFO code=%d]", - REGNO (x), GET_CODE (y)); - } - break; - case LABEL_REF: - output_address (XEXP (x, 0)); - break; - case SYMBOL_REF: - switch (GET_CODE (y)) - { - case CONST_INT: - fprintf (file, "%d+%s", INTVAL (y) + addr_inc, XSTR (x, 0)); - break; - case REG: - fprintf (file, "%s,r%d ;P_O_A sym + reg", - XSTR (x, 0), REGNO (y)); - break; - default: - fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]", - XSTR (x, 0), GET_CODE (y)); - } - break; - case CONST: - output_address (XEXP (x, 0)); - if (GET_CODE (y) == REG) - fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x)); - else - fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y)); - break; - case MEM: - output_address (y); - fprintf (file, ",[mem:"); - output_address (XEXP (x, 0)); - fprintf (file, "] ;P_O_A plus"); - break; - default: - fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]", - GET_CODE (x), GET_CODE (y)); - } - } - break; - case CONST_INT: - if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000) - fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr)); - else - { - fprintf (file, "[p_o_a=ILLEGAL_CONST]"); - output_addr_const (file, addr); - } - break; - case LABEL_REF: - case SYMBOL_REF: - fprintf (file, "%s", XSTR (addr, 0)); - if (addr_inc) - fprintf (file, "+%d", addr_inc); - break; - case MEM: - fprintf (file, "[memUFO:"); - output_address (XEXP (addr, 0)); - fprintf (file, "]"); - break; - case CONST: - output_address (XEXP (addr, 0)); - fprintf (file, " ;P_O_A const"); - break; - case CODE_LABEL: - fprintf (file, "L%d", XINT (addr, 3)); - break; - default: - fprintf (file, " p_o_a UFO, code=%d val=0x%x", - (int) GET_CODE (addr), INTVAL (addr)); - break; - } - addr_inc = 0; -} - - -/* - * Return non zero if the LS 16 bits of the given value has just one bit set, - * otherwise return zero. Note this function may be used to detect one - * bit clear by inverting the param. - */ -int -one_bit_set_p (x) - int x; -{ - x &= 0xffff; - return x && (x & (x - 1)) == 0; -} - - -/* - * Return the number of the least significant bit set, using the same - * convention for bit numbering as in the MIL-STD-1750 sb instruction. - */ -int -which_bit (x) - int x; -{ - int b = 15; - - while (b > 0 && (x & 1) == 0) - { - b--; - x >>= 1; - } - - return b; -} - - diff --git a/gcc/config/1750a/1750a.h b/gcc/config/1750a/1750a.h deleted file mode 100755 index 5d3b2a0..0000000 --- a/gcc/config/1750a/1750a.h +++ /dev/null @@ -1,1348 +0,0 @@ -/* Definitions of target machine for GNU compiler. - Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. - Contributed by O.M.Kellogg, DASA (oliver.kellogg@space.otn.dasa.de) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -/* Names to predefine in the preprocessor for this target machine. */ - -/* See tm-sun3.h, tm-sun2.h, tm-isi68.h for different CPP_PREDEFINES. */ -#define CPP_PREDEFINES "" - -/* Print subsidiary information on the compiler version in use. */ -#ifdef IEEE -#define TARGET_VERSION fprintf (stderr, " (1750A, IEEE syntax)"); -#else -#define TARGET_VERSION fprintf (stderr, " (MIL-STD-1750A)"); -#endif - -/* Run-time compilation parameters selecting different hardware subsets. */ - -#define TARGET_SWITCHES \ - { {"vaxc-alignment", 2}, \ - { "", TARGET_DEFAULT}} - -/* Default target_flags if no switches specified. */ - -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT 1 -#endif - -/*****************************************************************************/ - -/* SPECIAL ADDITION FOR MIL-STD-1750A by O.M.Kellogg, 15-Apr-1993 */ -/* See file aux-output.c for the actual data instances. */ -struct datalabel_array { - char *name; - char value[14]; - int size; -}; -struct jumplabel_array { - int pc; - int num; -}; -enum section { Init, Normal, Konst, Static }; -#define DATALBL_ARRSIZ 256 -#define JMPLBL_ARRSIZ 256 -#ifndef __datalbl -extern struct datalabel_array datalbl[]; -extern struct jumplabel_array jmplbl[]; -extern int datalbl_ndx, jmplbl_ndx, label_pending, program_counter; -extern enum section current_section; -extern char *sectname[4]; -extern char *float_label(); -extern struct rtx_def *function_arg (); -extern char *movcnt_regno_adjust (); -extern char *mod_regno_adjust (); -extern char *branch_or_jump (); -#endif -/*--------------------------------------------------------------------*/ - -/* target machine storage layout */ - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. - Though 1750 actually counts bits in big-endian fashion, the sign bit - is still the most significant bit, which is leftmost. Therefore leaving - this little-endian. Adjust short before assembler output when needed: - e.g. in QImode, a GCC bit n is a 1750 bit (15-n). */ -#define BITS_BIG_ENDIAN 0 - -/* Define this if most significant byte of a word is the lowest numbered. */ -/* For 1750 we can decide arbitrarily - since there are no machine instructions for them. */ -#define BYTES_BIG_ENDIAN 0 - -/* Define this if most significant word of a multiword value is lowest - numbered. - True for 1750. */ -#define WORDS_BIG_ENDIAN 1 - -/* number of bits in an addressable storage unit */ -#define BITS_PER_UNIT 16 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; - if using 16-bit ints on a 68000, this would still be 32. - But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 16 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 1 - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 16 - -#define PTRDIFF_TYPE "int" - -/* Type to use for `size_t'. If undefined, uses `long unsigned int'. */ -#define SIZE_TYPE "int" - -/* 1750a preliminary - #define TARGET_FLOAT_FORMAT UNKNOWN_FLOAT_FORMAT -*/ - -/* Allocation boundary (in *bits*) for storing pointers in memory. */ -#define POINTER_BOUNDARY 16 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -/* 1750: should have had to make this 32 when BITS_PER_WORD is 32. */ -#define PARM_BOUNDARY 16 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 16 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 16 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 16 - -/* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 16 - -/* Define this to 1 if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 0 - -/* Define number of bits in most basic integer type. - (If undefined, default is BITS_PER_WORD). - #define INT_TYPE_SIZE 16 */ - -/* Define number of bits in short integer type. - (If undefined, default is half of BITS_PER_WORD). */ -#define SHORT_TYPE_SIZE 16 - -/* Define number of bits in long integer type. - (If undefined, default is BITS_PER_WORD). */ -#define LONG_TYPE_SIZE 32 - -/* Define number of bits in long long integer type. - (If undefined, default is twice BITS_PER_WORD). */ -/* 1750 PRELIMINARY : no processor support for `long long', therefore - need to check out the long-long opencodings ! */ -#define LONG_LONG_TYPE_SIZE 64 - -/* Define number of bits in char type. - (If undefined, default is one fourth of BITS_PER_WORD). */ -#define CHAR_TYPE_SIZE 16 - -/* Define number of bits in float type. - (If undefined, default is BITS_PER_WORD). */ -#define FLOAT_TYPE_SIZE 32 - -/* Define number of bits in double type. - (If undefined, default is twice BITS_PER_WORD). */ -#define DOUBLE_TYPE_SIZE 48 - -/*****************************************************************************/ - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. */ -#define FIRST_PSEUDO_REGISTER 16 - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - R15 is the 1750A stack pointer. R14 is the frame pointer. */ - -#define FIXED_REGISTERS \ - { 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 1, 1 } - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. - 1750: return value in R0 foll. (depending on size of retval). - Should be possible to refine this (how many regs are actually used) */ - -#define CALL_USED_REGISTERS \ - { 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1 } - -/* Order in which to allocate registers. Each register must be - listed once, even those in FIXED_REGISTERS. List frame pointer - late and fixed registers last. Note that, in general, we prefer - registers listed in CALL_USED_REGISTERS, keeping the others - available for storage of persistent values. */ - -/* #define REG_ALLOC_ORDER \ - { 2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } - */ - -/* 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. - All 1750 registers are one word long. */ -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) 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, - for any hard reg, then this must be 0 for correct output. */ -#define MODES_TIEABLE_P(MODE1, MODE2) 1 - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* 1750A pc isn't overloaded on a register. */ -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM 15 - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 14 - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms - may be accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED 0 - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM 14 - -/* Define this if successive args to a function occupy decreasing addresses - on the stack. - #define ARGS_GROW_DOWNWARD -*/ - -/* Register in which static-chain is passed to a function. */ -#define STATIC_CHAIN_REGNUM 13 - -/* Place in which caller passes the structure value address. - 0 means push the value on the stack like an argument. - #define STRUCT_VALUE 0 -*/ - -/* Register in which address to store a structure value - arrives in the function. - #define STRUCT_VALUE_INCOMING 0 -*/ - -/* Register in which address to store a structure value - is passed to a function. */ -#define STRUCT_VALUE_REGNUM 12 - -/* Define this to be 1 if all structure return values must be in memory. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/*****************************************************************************/ - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -/* 1750 note: The names (BASE_REGS/INDEX_REGS) are used in their *gcc sense* - (i.e. *opposite* to the MIL-STD-1750A defined meanings). This means that - R1..R15 are called "base" regs and R12..R15 are "index" regs. - Index reg mode (in the gcc sense) is not yet implemented (these are the - 1750 "Base with Index Reg" instructions, LBX etc. See 1750.md) - - Here's an example to drive this point home: in "LBX B12,R5" - B12 shall be called the "index" reg and R5 shall be the "base" reg. - This naming inversion is due to the GCC defined capabilities of - "Base" vs. "Index" regs. */ - -enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLASSES }; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Since GENERAL_REGS is the same class as ALL_REGS, - don't give it a different class number; just make it an alias. */ -#define GENERAL_REGS ALL_REGS - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ - { "NO_REGS", "R2", "R0_1", "INDEX_REGS", "BASE_REGS", "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. - 1750 "index" (remember, in the *GCC* sense!) regs are R12 through R15. - The only 1750 register not usable as BASE_REG is R0. */ - -#define REG_CLASS_CONTENTS {0, 0x0004, 0x0003, 0xf000, 0xfffe, 0xffff} - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ -#define REGNO_REG_CLASS(REGNO) ((REGNO) == 2 ? R2 : (REGNO) == 0 ? R0_1 : \ - (REGNO) >= 12 ? INDEX_REGS : (REGNO) > 0 ? BASE_REGS : ALL_REGS) - -/* The class value for index registers, and the one for base regs. */ - -#define BASE_REG_CLASS BASE_REGS -#define INDEX_REG_CLASS INDEX_REGS - -/* Get reg_class from a letter such as appears in the machine description. - For the 1750, we have 'z' for R0_1, 't' for R2, 'b' for gcc Base regs - and 'x' for gcc Index regs. */ - -#define REG_CLASS_FROM_LETTER(C) ((C) == 't' ? R2 : \ - (C) == 'z' ? R0_1 : \ - (C) == 'b' ? BASE_REGS : \ - (C) == 'x' ? INDEX_REGS : NO_REGS) - -/* The letters I,J,K,.. to P in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. - - For the 1750A, - `I' is used for ISP mode instructions, - `J' is used for ISN mode instructions, - `K' is used for the STC instruction's constant range, - `L' is used for unsigned 8-bit address displacements in instructions - of addressing mode "Base Relative", - `M' is for IM mode instructions et al., - `O' is a synonym for (const_int 0). */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (VALUE) > 0 && (VALUE) <= 16 : \ - (C) == 'J' ? (VALUE) < 0 && (VALUE) >= -16 : \ - (C) == 'K' ? (VALUE) >= 0 && (VALUE) <= 15 : \ - (C) == 'L' ? (VALUE) >= 0 && (VALUE) <= 0xFF : \ - (C) == 'M' ? (VALUE) >= -0x8000 && (VALUE) <= 0x7FFF : \ - (C) == 'O' ? (VALUE) == 0 : 0) - -/* Similar, but for floating constants, and defining letter 'G'. - Here VALUE is the CONST_DOUBLE rtx itself. */ -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' ? ((VALUE) == CONST0_RTX (HFmode) \ - || (VALUE) == CONST0_RTX (TQFmode)) : 0) - -/* Optional extra constraints for this machine. - - For the 1750, `Q' means that this is a memory operand consisting - of the sum of an Index Register (in the GCC sense, i.e. R12..R15) - and a constant in the range 0..255. This constraint is used for - the Base Register with Offset address mode instructions (LB,STB,AB,..) */ - -#define EXTRA_CONSTRAINT(OP, C) \ - ((C) == 'Q' && b_mode_operand (OP)) - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. - On the 1750A, this is the size of MODE in words, - since class doesn't make any difference. */ -#define CLASS_MAX_NREGS(CLASS,MODE) GET_MODE_SIZE(MODE) - -/*****************************************************************************/ - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -#define STACK_GROWS_DOWNWARD 1 - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - goes at a more negative offset in the frame. - #define FRAME_GROWS_DOWNWARD -*/ - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. -*/ -#define STARTING_FRAME_OFFSET 1 - -/* This is the default anyway: - #define DYNAMIC_CHAIN_ADDRESS(FRAMEADDR) FRAMEADDR -*/ - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. - 1750 note: what GCC calls a "byte" is really a 16-bit word, - because BITS_PER_UNIT is 16. */ - -#define PUSH_ROUNDING(BYTES) (BYTES) - -/* Define this macro if functions should assume that stack space has - been allocated for arguments even when their values are passed in - registers. - Size, in bytes, of the area reserved for arguments passed in - registers for the function represented by FNDECL. - #define REG_PARM_STACK_SPACE(FNDECL) 14 */ - -/* Define this if it is the responsibility of the caller to allocate - the area reserved for arguments passed in registers. - #define OUTGOING_REG_PARM_STACK_SPACE */ - -/* Offset of first parameter from the argument pointer register value. - 1750 note: - Parameters appear in reversed order on the frame (so when they are - popped, they come off in the normal left-to-right order.) - Computed as follows: - one word for the caller's (PC+1) (i.e. the return address) - plus total size of called function's "auto" variables - plus one word for the caller's frame pointer (i.e. the old FP) */ - -#define FIRST_PARM_OFFSET(FNDECL) \ - (1 + get_frame_size() + 1) - -/* Value is 1 if returning from a function call automatically - pops the arguments described by the number-of-args field in the call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. -*/ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx(REG,TYPE_MODE(VALTYPE),0) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ -/* 1750 note: no libcalls yet */ - -#define LIBCALL_VALUE(MODE) printf("LIBCALL_VALUE called!\n"), \ - gen_rtx(REG,MODE,0) - -/* 1 if N is a possible register number for a function value. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) - -/* 1 if the tree TYPE should be returned in memory instead of in regs. - #define RETURN_IN_MEMORY(TYPE) \ - (int_size_in_bytes(TYPE) > 12) -*/ - -/* Define this if PCC uses the nonreentrant convention for returning - structure and union values. - #define PCC_STATIC_STRUCT_RETURN */ - -/* 1 if N is a possible register number for function argument passing. */ - -#define FUNCTION_ARG_REGNO_P(N) ((N) < 12) - -/*****************************************************************************/ - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. - - For 1750A, this is a single integer, which is a number of words - of arguments scanned so far. */ - -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. - - For 1750A, the offset starts at 0. */ - -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) ((CUM) = 0) - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) - - 1750 note: "int_size_in_bytes()" returns a unit relative to - BITS_PER_UNIT, so in our case not bytes, but 16-bit words. */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - ((CUM) += (MODE) == BLKmode ? int_size_in_bytes(TYPE) : GET_MODE_SIZE(MODE)) - -/* Define where to put the arguments to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) function_arg (CUM,MODE,TYPE,NAMED) - -/* Define the following macro if function calls on the target machine - do not preserve any registers; in other words, if `CALL_USED_REGISTERS' - has 1 for all registers. This macro enables `-fcaller-saves' by - default. Eventually that option will be enabled by default on all - machines and both the option and this macro will be eliminated. */ - -#define DEFAULT_CALLER_SAVES - - -/* This macro generates the assembly code for function entry. - FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - 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. */ - - -#define FUNCTION_PROLOGUE(FILE, SIZE) { \ - if (flag_verbose_asm) \ - { \ - int regno, regs_used = 0; \ - fprintf (FILE, "\t; registers used: "); \ - for (regno = 0; regno < 14; regno++) \ - if (regs_ever_live[regno]) \ - { \ - fprintf (FILE, " %s", reg_names[regno]); \ - regs_used++; \ - } \ - if (regs_used == 0) \ - fprintf (FILE, "(none)"); \ - } \ - if (SIZE > 0) \ - { \ - fprintf (FILE, "\n\t%s\tr15,%d", \ - (SIZE <= 16 ? "sisp" : "sim"), SIZE); \ - if (flag_verbose_asm) \ - fprintf (FILE, " ; reserve local-variable space"); \ - } \ - if (frame_pointer_needed) \ - { \ - fprintf(FILE, "\n\tpshm\tr14,r14"); \ - if (flag_verbose_asm) \ - fprintf (FILE, " ; push old frame"); \ - fprintf (FILE, "\n\tlr\tr14,r15"); \ - if (flag_verbose_asm) \ - fprintf (FILE, " ; set new frame"); \ - } \ - fprintf (FILE, "\n"); \ - program_counter = 0; \ - jmplbl_ndx = -1; \ -} - -/************* 1750: PROFILER HANDLING NOT YET DONE !!!!!!! *************/ -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - fprintf (FILE, "; got into FUNCTION_PROFILER with label # %d\n", (LABELNO)) - -/* Output assembler code to FILE to initialize this source file's - basic block profiling info, if that has not already been done. */ -#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \ - fprintf (FILE, "; got into FUNCTION_BLOCK_PROFILER with label # %d\n",LABELNO) - -/* Output assembler code to FILE to increment the entry-count for - the BLOCKNO'th basic block in this source file. */ -#define BLOCK_PROFILER(FILE, BLOCKNO) \ - fprintf (FILE, "; got into BLOCK_PROFILER with block # %d\n",BLOCKNO) - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. */ - -#define EXIT_IGNORE_STACK 0 - -/* This macro generates the assembly code for function exit, - on machines that need it. If FUNCTION_EPILOGUE is not defined - then individual return instructions are generated for each - return statement. Args are same as for FUNCTION_PROLOGUE. - - The function epilogue should not depend on the current stack pointer! - It should use the frame pointer only. This is mandatory because - of alloca; we also take advantage of it to omit stack adjustments - before returning. */ - -#define FUNCTION_EPILOGUE(FILE, SIZE) { \ - if (frame_pointer_needed) \ - { \ - fprintf (FILE, "\tlr\tr15,r14"); \ - if (flag_verbose_asm) \ - fprintf (FILE, " ; set stack ptr to frame ptr"); \ - fprintf (FILE, "\n\tpopm\tr14,r14"); \ - if (flag_verbose_asm) \ - fprintf (FILE, " ; restore previous frame ptr"); \ - fprintf (FILE, "\n"); \ - } \ - if (SIZE > 0) \ - { \ - fprintf (FILE, "\t%s\tr15,%d", \ - (SIZE <= 16 ? "aisp" : "aim"), SIZE); \ - if (flag_verbose_asm) \ - fprintf (FILE, " ; free up local-var space"); \ - fprintf (FILE, "\n"); \ - } \ - fprintf (FILE, "\turs\tr15\n\n"); \ -} - -/* If the memory address ADDR is relative to the frame pointer, - correct it to be relative to the stack pointer instead. - This is for when we don't use a frame pointer. - ADDR should be a variable name. - - #define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) -*/ - -/* Store in the variable DEPTH the initial difference between the - frame pointer reg contents and the stack pointer reg contents, - as of the start of the function body. This depends on the layout - of the fixed parts of the stack frame and on how registers are saved. -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) DEPTH = 0 -*/ - -#define ELIMINABLE_REGS { \ - { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM } } - -#define CAN_ELIMINATE(FROM, TO) 1 - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ - OFFSET = (TO == STACK_POINTER_REGNUM) ? -1 : 0 - - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. */ - -#define TRAMPOLINE_TEMPLATE(FILE) fprintf(FILE,"TRAMPOLINE_TEMPLATE called\n") - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 2 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) printf("INITIALIZE_TRAMPO called\n") -/* { \ - emit_move_insn (gen_rtx (MEM, QImode, plus_constant (TRAMP, 1)), CXT); \ - emit_move_insn (gen_rtx (MEM, QImode, plus_constant (TRAMP, 6)), FNADDR); \ -} */ - - -/*****************************************************************************/ - -/* Addressing modes, and classification of registers for them. */ - -/* 1750 doesn't have a lot of auto-incr./decr. - just for the stack ptr. */ - -/* #define HAVE_POST_INCREMENT 0 just for R15 (stack pointer) */ -/* #define HAVE_POST_DECREMENT 0 */ -/* #define HAVE_PRE_DECREMENT 0 just for R15 (stack pointer) */ -/* #define HAVE_PRE_INCREMENT 0 */ - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. - 1750 note: The words BASE and INDEX are used in their GCC senses: - The "Index Registers", R12 through R15, are used in the 1750 - instructions LB,STB,AB,SBB,MB,DB,LBX,STBX,... - */ - -#define REGNO_OK_FOR_BASE_P(REGNO) \ - ((REGNO) > 0 && (REGNO) <= 15 || \ - reg_renumber[REGNO] > 0 && reg_renumber[REGNO] <= 15) -#define REGNO_OK_FOR_INDEX_P(REGNO) \ - ((REGNO) >= 12 && (REGNO) <= 15 || \ - reg_renumber[REGNO] >= 12 && reg_renumber[REGNO] <= 15) - -/* Now macros that check whether X is a register and also, - strictly, whether it is in a specified class. - -/* 1 if X is an address register */ - -#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) - -/* Maximum number of registers that can appear in a valid memory address. */ -#define MAX_REGS_PER_ADDRESS 1 - -/* Recognize any constant value that is a valid address. */ - -#define CONSTANT_ADDRESS_P(X) CONSTANT_P(X) - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ - -#define LEGITIMATE_CONSTANT_P(X) 1 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifdef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P(REGNO(X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P(REGNO(X)) - -#else - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) (REGNO (X) >= 12) -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) (REGNO (X) > 0) - -#endif - - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. - - 1750 note: Currently we don't implement address expressions that use - GCC "Index"-class regs. To be expanded to handle the 1750 "Base with Index" - instructions (see also MAX_REGS_PER_ADDRESS and others). */ - -#define GO_IF_BASED_ADDRESS(X, ADDR) { \ - if ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P(X))) \ - goto ADDR; \ - if (GET_CODE (X) == PLUS) \ - { register rtx x0 = XEXP(X,0), x1 = XEXP(X,1); \ - if ((REG_P(x0) && REG_OK_FOR_BASE_P(x0) && CONSTANT_ADDRESS_P(x1)) \ - || (REG_P(x1) && REG_OK_FOR_BASE_P(x1) && CONSTANT_ADDRESS_P(x0))) \ - goto ADDR; } } - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) { \ - if (CONSTANT_ADDRESS_P(X)) goto ADDR; \ - GO_IF_BASED_ADDRESS(X,ADDR) } - - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. - On the 68000, only predecrement and postincrement address depend thus - (the amount of decrement or increment being the length of the operand). */ -/* 1750: not used. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) - -/*****************************************************************************/ - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE QImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE 1 */ - -/* Specify the tree operation to be used to convert reals to integers. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* This is the kind of divide that is easiest to do in the general case. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 65536 - -/* If a memory-to-memory move would take MOVE_RATIO or more simple - move-instruction pairs, we will do a movstr or libcall instead. */ -#define MOVE_RATIO 4 - -/* Define this if zero-extension is slow (more than one real instruction). */ -/* #define SLOW_ZERO_EXTEND */ - -/* Nonzero if access to memory by bytes is slow and undesirable. */ -#define SLOW_BYTE_ACCESS 0 - -/* Define if shifts truncate the shift count - which implies one can omit a sign-extension or zero-extension - of a shift count. */ -/* #define SHIFT_COUNT_TRUNCATED 1 */ - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* We assume that the store-condition-codes instructions store 0 for false - and some other value for true. This is the value stored for true. */ - -#define STORE_FLAG_VALUE 1 - -/* When a prototype says `char' or `short', really pass an `int'. - 1750: for now, `char' is 16 bits wide anyway. - #define PROMOTE_PROTOTYPES */ - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -#define Pmode QImode - -/* A function address in a call instruction - is a 16-bit address (for indexing purposes) */ -#define FUNCTION_MODE QImode - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. */ - -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - return (INTVAL(RTX) >= -16 && INTVAL(RTX) <= 16) ? 1 : 3; \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - return 3; \ - case CONST_DOUBLE: \ - return 4; - -#define ADDRESS_COST(ADDRESS) (memop_valid (ADDRESS) ? 3 : 10) - -#define REGISTER_MOVE_COST(FROM,TO) 2 - -#define MEMORY_MOVE_COST(M,C,I) 4 - -/* Tell final.c how to eliminate redundant test instructions. */ - -/* Here we define machine-dependent flags and fields in cc_status - (see `conditions.h'). */ -/* MIL-STD-1750: none -- just has the garden variety C,P,Z,N flags. */ - -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. - 1750: See file out-1750a.c for notice_update_cc(). */ - -#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP) - -/**********************************************/ -/* Produce debugging info in the DWARF format - #define DWARF_DEBUGGING_INFO -*/ - -/*****************************************************************************/ - -/* Control the assembler format that we output. */ - -/* Output at beginning of assembler file. */ - -#define ASM_FILE_START(FILE) { \ - char *p, name[40]; \ - if ((p = (char *)strrchr(main_input_filename,'/')) != NULL ? 1 : \ - (p = (char *)strrchr(main_input_filename,']')) != NULL) \ - p++; \ - else \ - p = main_input_filename; \ - strcpy(name,p); \ - if (p = (char *)strchr(name,'.')) \ - *p = '\0'; \ - fprintf(FILE,"\tname %s\n",name); \ - fprintf(FILE,"\tnolist\n\tinclude \"ms1750.inc\"\n\tlist\n\n"); \ - fprintf(FILE,"\tglobal\t__main\n\n"); } - -/* Output at end of assembler file. - For 1750, we copy the data labels accrued in datalbl[] from the Constants - section (Konst) to the Writable-Data section (Static). */ - -#define ASM_FILE_END(FILE) \ - do { \ - if (datalbl_ndx >= 0) { \ - int i, cum_size=0; \ - fprintf(FILE,"\n\tstatic\ninit_srel\n"); \ - for (i = 0; i <= datalbl_ndx; i++) { \ - if (datalbl[i].name == NULL) \ - { \ - fprintf(stderr, "asm_file_end internal datalbl err\n"); \ - exit (0); \ - } \ - fprintf(FILE,"%s \tblock %d\n", \ - datalbl[i].name,datalbl[i].size); \ - cum_size += datalbl[i].size; \ - } \ - fprintf(FILE,"\n\tinit\n"); \ - fprintf(FILE,"\tlim\tr0,init_srel\n"); /* destin. */ \ - fprintf(FILE,"\tlim\tr1,%d\n",cum_size); /* count */ \ - fprintf(FILE,"\tlim\tr2,K%s\n",datalbl[0].name); /* source */ \ - fprintf(FILE,"\tmov\tr0,r2\n"); \ - fprintf(FILE,"\n\tnormal\n"); \ - datalbl_ndx = -1; /* reset stuff */ \ - for (i = 0; i < DATALBL_ARRSIZ; i++) \ - datalbl[i].size = 0; \ - } \ - fprintf(FILE,"\n\tend\n"); \ - } while (0) - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "; ASM_APP_ON\n" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF "; ASM_APP_OFF\n" - - -#define EXTRA_SECTIONS in_readonly_data - -#define EXTRA_SECTION_FUNCTIONS \ - void const_section() \ - { \ - fprintf(asm_out_file,"\tkonst\n"); \ - current_section = Konst; \ - } \ - check_section(sect) \ - enum section sect; \ - { \ - if (current_section != sect) { \ - fprintf(asm_out_file,"\t%s\n",sectname[(int)sect]); \ - current_section = sect; \ - } \ - switch (sect) { \ - case Init: \ - case Normal: \ - in_section = in_text; \ - break; \ - case Static: \ - in_section = in_data; \ - break; \ - case Konst: \ - in_section = in_readonly_data; \ - break; \ - } \ - } - - -/* Function that switches to the read-only data section (optional) */ -#define READONLY_DATA_SECTION const_section - -/* Output before program init section */ -#define INIT_SECTION_ASM_OP "\n\tinit ; init_section\n" - -/* Output before program text section */ -#define TEXT_SECTION_ASM_OP "\n\tnormal ; text_section\n" - -/* Output before writable data. - 1750 Note: This is actually read-only data. The copying from read-only - to writable memory is done elsewhere (in ASM_FILE_END.) - */ -#define DATA_SECTION_ASM_OP "\n\tkonst ; data_section\n" - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ - { "0", "1", "2", "3", "4", "5", "6", "7", \ - "8", "9","10","11","12","13","14","15" } - -/* How to renumber registers for dbx and gdb. */ - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/****************** Assembler output formatting **********************/ - -#define ASM_IDENTIFY_GCC(FILE) fputs ("; gcc2_compiled:\n", FILE) - -#define ASM_COMMENT_START ";" - -#define ASM_OUTPUT_FUNNAM(FILE,NAME) \ - fprintf(FILE,"%s\n",NAME) - -#define ASM_OUTPUT_OPCODE(FILE,PTR) do { \ - while (*(PTR) != '\0' && *(PTR) != ' ') { \ - putc (*(PTR), FILE); \ - (PTR)++; \ - } \ - while (*(PTR) == ' ') \ - (PTR)++; \ - putc ('\t', FILE); \ - program_counter += 2; \ - } while (0) - -#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ - fprintf(FILE,"%s\n",NAME) - -/* This is how to output the definition of a user-level label named NAME, - such as the label on a static function or variable NAME. */ -/* 1750 note: Labels are prefixed with a 'K'. This is because handling - has been changed for labels to be output in the "Constants" section - (named "Konst"), and special initialization code takes care of copying - the Const-section data into the writable data section (named "Static"). - In the Static section we therefore have the true label names (i.e. - not prefixed with 'K'). */ - -#define ASM_OUTPUT_LABEL(FILE,NAME) \ - do { if (NAME[0] == '.') { \ - fprintf(stderr,"Oops! label %s can't begin with '.'\n",NAME); \ - abort(); \ - } \ - else { \ - check_section(Konst); \ - fprintf(FILE,"K%s\n",NAME); \ - fflush(FILE); \ - datalbl[++datalbl_ndx].name = (char *)xstrdup (NAME);\ - datalbl[datalbl_ndx].size = 0; \ - label_pending = 1; \ - } \ - } while (0) - - -/* This is how to output a command to make the user-level label named NAME - defined for reference from other files. */ - -#define ASM_GLOBALIZE_LABEL(FILE,NAME) do { \ - fprintf (FILE, "\tglobal %s\t; export\n", NAME); \ - } while (0) - -/* The prefix to add to user-visible assembler symbols. */ - -#define USER_LABEL_PREFIX "" - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ - -#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - do { \ - if (strcmp(PREFIX,"LC") == 0) { \ - label_pending = 1; \ - datalbl[++datalbl_ndx].name = (char *) malloc (9); \ - sprintf(datalbl[datalbl_ndx].name,"LC%d",NUM); \ - datalbl[datalbl_ndx].size = 0; \ - check_section(Konst); \ - fprintf(FILE,"K%s%d\n",PREFIX,NUM); \ - } \ - else if (find_jmplbl(NUM) < 0) { \ - jmplbl[++jmplbl_ndx].num = NUM; \ - jmplbl[jmplbl_ndx].pc = program_counter; \ - fprintf(FILE, "%s%d\n", PREFIX, NUM); \ - } \ - fflush(FILE); \ - } while (0) - - -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "%s%d", PREFIX, NUM) - -/* Output at the end of a jump table. - 1750: To be uncommented when we can put jump tables in Konst. - #define ASM_OUTPUT_CASE_END(FILE,NUM,INSN) \ - fprintf (FILE, "\tnormal\t; case_end\n") - */ - -/* Currently, it is not possible to put jump tables in section Konst. - This is because there is a one-to-one relation between sections Konst - and Static (i.e., all Konst data are copied to Static, and the order - of data is the same between the two sections.) However, jump tables are - not copied to Static, which destroys the equivalence between Konst and - Static. When a more intelligent Konst-to-Static copying mechanism is - implemented (i.e. one that excludes the copying of jumptables), then - ASM_OUTPUT_CASE_END shall be defined, and JUMP_LABELS_IN_TEXT_SECTION - shall be undefined. */ - -#define JUMP_TABLES_IN_TEXT_SECTION 1 - -/* This is how to output an assembler line defining a 1750A `float' - constant. */ - -#define ASM_OUTPUT_SHORT_FLOAT(FILE,VALUE) \ - do { \ - if (label_pending) { \ - label_pending = 0; \ - sprintf (datalbl[datalbl_ndx].value, "%lf", (double) VALUE); \ - } \ - datalbl[datalbl_ndx].size += 2; \ - fprintf (FILE, "\tdataf\t%lf\n",VALUE); \ - } while(0) - -/* This is how to output an assembler line defining a 1750A `double' - constant. */ - -#define ASM_OUTPUT_THREE_QUARTER_FLOAT(FILE,VALUE) \ - do { \ - if (label_pending) { \ - label_pending = 0; \ - sprintf (datalbl[datalbl_ndx].value, "%lf", VALUE); \ - } \ - datalbl[datalbl_ndx].size += 3; \ - fprintf(FILE,"\tdataef\t%lf\n",VALUE); \ - } while (0) - -/* This is how to output an assembler line defining a string constant. */ - -#define ASM_OUTPUT_ASCII(FILE, PTR, LEN) do { \ - int i; \ - if (label_pending) \ - label_pending = 0; \ - datalbl[datalbl_ndx].size += LEN; \ - for (i = 0; i < LEN; i++) { \ - if ((i % 15) == 0) { \ - if (i != 0) \ - fprintf(FILE,"\n"); \ - fprintf(FILE,"\tdata\t"); \ - } \ - else \ - fprintf(FILE,","); \ - if (PTR[i] >= 32 && PTR[i] < 127) \ - fprintf(FILE,"'%c'",PTR[i]); \ - else \ - fprintf(FILE,"%d",PTR[i]); \ - } \ - fprintf(FILE,"\n"); \ - } while (0) - -/* This is how to output an assembler line defining a `char', `short', or - `int' constant. - 1750 NOTE: The reason why this macro also outputs `short' and `int' - constants is that for the 1750, BITS_PER_UNIT is 16 (as opposed to the - usual 8.) This behavior is different from the usual, where - ASM_OUTPUT_CHAR only outputs character constants. The name - of this macro should perhaps be `ASM_OUTPUT_QUARTER_INT' or so. - */ - -#define ASM_OUTPUT_CHAR(FILE,VALUE) do { \ - if (label_pending) \ - label_pending = 0; \ - datalbl[datalbl_ndx].size++; \ - fprintf(FILE, "\tdata\t"); \ - output_addr_const(FILE, VALUE); \ - fprintf(FILE, "\n"); \ - } while (0) - -/* This is how to output an assembler line defining a `long int' constant. - 1750 NOTE: The reason why this macro outputs `long' instead of `short' - constants is that for the 1750, BITS_PER_UNIT is 16 (as opposed to the - usual 8.) The name of this macro should perhaps be `ASM_OUTPUT_HALF_INT'. - */ - -#define ASM_OUTPUT_SHORT(FILE,VALUE) do { \ - if (label_pending) \ - label_pending = 0; \ - datalbl[datalbl_ndx].size += 2; \ - fprintf(FILE, "\tdatal\t%d\n",INTVAL(VALUE)); \ - } while (0) - -/* This is how to output an assembler line for a numeric constant byte. */ - -#define ASM_OUTPUT_BYTE(FILE,VALUE) do { \ - if (label_pending) \ - label_pending = 0; \ - datalbl[datalbl_ndx].size++; \ - fprintf(FILE, "\tdata\t#%x\n", VALUE); \ - } while (0) - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tPSHM R%s,R%s\n", reg_names[REGNO]) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tPOPM R%s,R%s\n", reg_names[REGNO]) - -/* This is how to output an element of a case-vector that is absolute. */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\tdata\tL%d ;addr_vec_elt\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\tdata\tL%d-L%d ;addr_diff_elt\n", VALUE,REL) - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - fprintf(FILE,"; in ASM_OUTPUT_ALIGN: pwr_of_2_bytcnt=%d\n",LOG) - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf(FILE,"; in ASM_OUTPUT_SKIP: size=%d\n",SIZE) - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) do { \ - check_section(Static); \ - fprintf (FILE, "\tcommon %s,%d\n", NAME, SIZE); \ - } while (0) - -#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) do { \ - fprintf (FILE, "\tglobal %s\t; import\n", NAME); \ - } while (0) - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) do { \ - check_section (Static); \ - fprintf(FILE,"%s \tblock %d\t; local common\n",NAME,SIZE); \ - } while (0) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) - -#define ASM_OUTPUT_CONSTRUCTOR(FILE, NAME) do { \ - fprintf(FILE, "\tinit\n\t"); assemble_name(FILE, NAME); \ - fprintf(FILE," ;constructor\n"); } while (0) - -#define ASM_OUTPUT_DESTRUCTOR(FILE, NAME) do { \ - fprintf(FILE, "\tinit\n\t"); assemble_name(FILE, NAME); \ - fprintf(FILE," ;destructor\n"); } while (0) - -/* Define the parentheses used to group arithmetic operations - in assembler code. */ - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* Define results of standard character escape sequences. */ -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. - 1750 note: there are three special CODE characters: - 'D', 'E': print a reference to a floating point constant (D=double, - E=single precision) label name - 'F': print a label defining a floating-point constant value - 'J': print the absolute value of a negative INT_CONST - (this is used in LISN/CISN/MISN/SISP and others) - 'Q': print a 1750 Base-Register-with-offset instruction's operands - */ - -/* 1750A: see file aux-output.c */ -#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE,X,CODE) -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address(FILE,ADDR) - diff --git a/gcc/config/1750a/1750a.md b/gcc/config/1750a/1750a.md deleted file mode 100755 index cff2d92..0000000 --- a/gcc/config/1750a/1750a.md +++ /dev/null @@ -1,1436 +0,0 @@ -;;- Machine description for GNU compiler -;;- MIL-STD-1750A version. -;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. -;; Contributed by O.M.Kellogg, DASA (oliver.kellogg@space.otn.dasa.de). - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 1, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - -;;- instruction definitions - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;;- When naming insn's (operand 0 of define_insn) be careful about using -;;- names from other targets machine descriptions. - -;; MIL-STD-1750 specific remarks: -;; -;; 1) BITS_PER_UNIT = 16 -;; -;; 2) GCC to MIL-STD-1750 data type mappings: -;; QImode => single integer (16 bits or 1 reg). -;; HImode => double integer (32 bits or 2 regs). -;; HFmode => single precision float (32 bits or 2 regs). -;; TQFmode => extended precision float (48 bits or 3 regs). -;; -;; 3) Immediate integer operands Constraints: -;; 'I' 1 .. 16 -;; 'J' -1 ..-16 -;; 'K' 0 .. 15 -;; 'L' 0 .. 255 -;; 'M' -32768 .. 32767 -;; 'O' => 0 (for optimizations and GCC quirks) -;; -;; Further notes: -;;- Assembly output ending in ".M" are macros in file M1750.INC - - -;; stackpush -(define_insn "" - [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "general_operand" "r"))] - "" - "pshm r%1,r%1") - -(define_insn "" - [(set (match_operand:HI 0 "push_operand" "=<") - (match_operand:HI 1 "general_operand" "r"))] - "" - "pshm r%1,r%d1") - -(define_insn "" - [(set (match_operand:HF 0 "push_operand" "=<") - (match_operand:HF 1 "general_operand" "r"))] - "" - "pshm r%1,r%d1") - -(define_insn "" - [(set (match_operand:TQF 0 "push_operand" "=<") - (match_operand:TQF 1 "general_operand" "r"))] - "" - "pshm r%1,r%t1") - -;; stackpop -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=r") - (match_operand:QI 1 "push_operand" ">"))] - "" - "popm r%1,r%1") - -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=r") - (match_operand:HI 1 "push_operand" ">"))] - "" - "popm r%1,r%d1") - -(define_insn "" - [(set (match_operand:HF 0 "general_operand" "=r") - (match_operand:HF 1 "push_operand" ">"))] - "" - "popm r%1,r%d1") - -(define_insn "" - [(set (match_operand:TQF 0 "general_operand" "=r") - (match_operand:TQF 1 "push_operand" ">"))] - "" - "popm r%1,r%t1") - - -;; Test operations. - -(define_insn "tstqi" - [(set (cc0) - (match_operand:QI 0 "register_operand" "r"))] - "" - "lr r%0,r%0 ; from tstqi") - -(define_insn "tsthi" - [(set (cc0) - (match_operand:HI 0 "register_operand" "r"))] - "" - "dlr r%0,r%0 ; from tsthi") - -; With 1750A floats, testing the most significant word suffices. - -(define_insn "tsthf" - [(set (cc0) - (match_operand:HF 0 "register_operand" "r"))] - "" - "lr r%0,r%0 ; tsthf") - -(define_insn "tsttqf" - [(set (cc0) - (match_operand:TQF 0 "register_operand" "r"))] - "" - "lr r%0,r%0 ; tsttqf") - - -;; block move. - -(define_insn "movstrqi" - [(set (match_operand:BLK 0 "mov_memory_operand" "m") - (match_operand:BLK 1 "mov_memory_operand" "m")) - (use (match_operand:QI 2 "general_operand" "r")) - (match_operand 3 "" "") - (clobber (match_dup 0)) - (clobber (match_dup 1)) - (clobber (match_dup 2))] - "" - "* - { - rtx regops[3]; - - regops[0] = XEXP (operands[0], 0); - regops[1] = XEXP (operands[1], 0); - regops[2] = operands[2]; - - return movcnt_regno_adjust (regops); - } ") - - -;; compare instructions. - -(define_insn "cmpqi" - [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "r,r,r,r,r") - (match_operand:QI 1 "general_operand" "I,J,i,r,m")))] - "" - "* - { - if (next_cc_user_is_unsigned (insn)) - switch (which_alternative) - { - case 0: - case 1: - case 2: - return \"ucim.m %0,%1\"; - case 3: - return \"ucr.m %0,%1\"; - case 4: - return \"uc.m %0,%1\"; - } - else - switch (which_alternative) - { - case 0: - return \"cisp r%0,%1\"; - case 1: - return \"cisn r%0,%J1\"; - case 2: - return \"cim r%0,%1\"; - case 3: - return \"cr r%0,r%1\"; - case 4: - return \"c r%0,%1\"; - } - } ") - -(define_insn "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "general_operand" "r,r") - (match_operand:HI 1 "general_operand" "r,m")))] - "" - "* - { - if (next_cc_user_is_unsigned (insn)) - { - if (which_alternative == 0) - return \"ducr.m %0,%1\"; - return \"duc.m %0,%1\"; - } - else - { - if (which_alternative == 0) - return \"dcr r%0,r%1\"; - return \"dc r%0,%1\"; - } - } ") - -(define_insn "cmphf" - [(set (cc0) - (compare (match_operand:HF 0 "general_operand" "r,r") - (match_operand:HF 1 "general_operand" "r,m")))] - "" - "@ - fcr r%0,r%1 - fc r%0,%1 ") - -(define_insn "cmptqf" - [(set (cc0) - (compare (match_operand:TQF 0 "general_operand" "r,r") - (match_operand:TQF 1 "general_operand" "r,m")))] - "" - "@ - efcr r%0,r%1 - efc r%0,%1 ") - - -;; truncation instructions -;;- 1750: any needed? - -(define_insn "trunchiqi2" - [(set (match_operand:QI 0 "register_operand" "=r") - (truncate:QI (match_operand:HI 1 "register_operand" "r")))] - "" - "lr r%0,r%d1") - - -;; zero extension instructions: not defined, GCC can synthesize - -;; sign extension instructions - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (sign_extend:HI (match_operand:QI 1 "general_operand" "r,m")) )] - "" - "* - if (which_alternative == 0) - { - if (REGNO (operands [0]) != REGNO (operands [1])) - output_asm_insn (\"lr r%0,r%1\", operands); - } - else - output_asm_insn (\"l r%0,%1\", operands); - return \"dsra r%0,16 ;extendqihi2\"; - ") - - -;; Conversions between float and double. - -; 1750 HF-to-TQF extend: just append 16 bits (least signif.) with all bits zero -(define_insn "extendhftqf2" - [(set (match_operand:TQF 0 "register_operand" "=r,r") - (float_extend:TQF (match_operand:HF 1 "general_operand" "r,m")))] - "" - "* - output_asm_insn(\"xorr r%t0,r%t0 ;extendhftqf2\", operands); - if (which_alternative == 0) - { - if (REGNO (operands[1]) != REGNO (operands[0])) - return \"dlr r%0,r%1\"; - else - return \";\"; - } - else - return \"dl r%0,%1\"; - ") - -; 1750 TQF-to-HF truncate is a no-op: just leave away the least signif. 16 bits -(define_insn "trunctqfhf2" - [(set (match_operand:HF 0 "register_operand" "=r,r") - (float_truncate:HF - (match_operand:TQF 1 "general_operand" "r,m")))] - "" - "@ - dlr r%0,r%1 ;trunctqfhf2 - dl r%0,%1 ;trunctqfhf2 ") - - -;; Conversion between fixed point and floating point. - -(define_insn "floatqihf2" - [(set (match_operand:HF 0 "register_operand" "=r") - (float:HF (match_operand:QI 1 "register_operand" "r")))] - "" - "flt r%0,r%1") - -(define_insn "floathitqf2" - [(set (match_operand:TQF 0 "register_operand" "=r") - (float:TQF (match_operand:HI 1 "register_operand" "r")))] - "" - "eflt r%0,r%1") - - -;; Convert floats to ints - -(define_insn "fix_trunchfqi2" - [(set (match_operand:QI 0 "register_operand" "=r") - (fix:QI (fix:HF (match_operand:HF 1 "register_operand" "r"))))] - "" - "fix r%0,r%1") - -(define_insn "fix_trunctqfhi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (fix:HI (fix:TQF (match_operand:TQF 1 "register_operand" "r"))))] - "" - "efix r%0,r%1") - - -;; Move instructions - -;; We can't deal with normal byte-size characters, only with WIDE characters! -;; This may appear as a serious restriction, but it also opens the doors -;; for ISO 10646 :-) - -;; 16-bit moves - -; memory indirect to reg -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (mem:QI (match_operand 1 "memory_operand" "m")))] - "" - "li r%0,%1") - -; reg/const to memory indirect -(define_insn "" - [(set (mem:QI (match_operand 0 "memory_operand" "=m,m")) - (match_operand:QI 1 "nonmemory_operand" "r,K"))] - "" - "@ - sti r%1,%0 - stci %1,%0") - -; general case -(define_insn "movqi" - [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,r,r,m,m") - (match_operand:QI 1 "general_operand" "O,I,J,i,r,m,r,K"))] - "" - "@ - xorr r%0,r%0 - lisp r%0,%1 - lisn r%0,%J1 - lim r%0,%1 - lr r%0,r%1 - l r%0,%1 - st r%1,%0 - stc %1,%0 ") - -;; 32-bit moves - -; memory indirect to reg -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (mem:HI (match_operand 1 "memory_operand" "m")))] - "" - "dli r%0,%1") - -; reg to memory indirect -(define_insn "" - [(set (mem:HI (match_operand 0 "memory_operand" "=m")) - (match_operand:HI 1 "register_operand" "r"))] - "" - "dsti r%1,%0") - -; general case -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=r,r,r,r,r,m,m") - (match_operand:HI 1 "general_operand" "O,I,J,r,m,r,K"))] - "" - "@ - xorr r%0,r%0\;xorr r%d0,r%d0 - xorr r%0,r%0\;lisp r%d0,%1 - lisn r%0,1 \;lisn r%d0,%J1 - dlr r%0,r%1 - dl r%0,%1 - dst r%1,%0 - stc 0,%0 \;stc %1,%A0 ") - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "=g") - (match_operand:HI 1 "general_operand" "g"))] - "" - " - { - rtx op1 = operands[1]; - if (GET_CODE (operands[0]) == MEM) - { - if (GET_CODE (op1) == MEM - || (GET_CODE (op1) == CONST_INT - && (INTVAL (op1) < 0 || INTVAL (op1) > 15))) - operands[1] = force_reg (HImode, operands[1]); - } - else if (GET_CODE (op1) == CONST_INT - && (INTVAL (op1) < -16 || INTVAL (op1) > 16)) - operands[1] = force_const_mem (HImode, operands[1]); - }") - - -;; Single-Float moves - -(define_insn "" - [(set (match_operand:HF 0 "general_operand" "=r,r,m,m") - (match_operand:HF 1 "general_operand" "r,m,r,G"))] - "" - "@ - dlr r%0,r%1 - dl r%0,%1 - dst r%1,%0 - stc 0,%0 \;stc 0,%A0 ") - -(define_expand "movhf" - [(set (match_operand:HF 0 "general_operand" "") - (match_operand:HF 1 "general_operand" ""))] - "" - " - { - enum rtx_code op1code = GET_CODE (operands[1]); - if (GET_CODE (operands[0]) == MEM) - { - if (op1code == MEM || (op1code == CONST_DOUBLE - && !rtx_equal_p (operands[1], CONST0_RTX (HFmode)))) - operands[1] = force_reg (HFmode, operands[1]); - } - else if (op1code == CONST_DOUBLE) - operands[1] = force_const_mem (HFmode, operands[1]); - }") - - -;; Longfloat moves - -(define_insn "" - [(set (match_operand:TQF 0 "general_operand" "=r,r,m") - (match_operand:TQF 1 "general_operand" "r,m,r"))] - "" - "@ - eflr.m %0,%1 - efl r%0,%1 - efst r%1,%0 ") - -(define_expand "movtqf" - [(set (match_operand:TQF 0 "general_operand" "") - (match_operand:TQF 1 "general_operand" ""))] - "" - " - { - enum rtx_code op1code = GET_CODE (operands[1]); - if (GET_CODE (operands[0]) == MEM) - { - if (op1code == MEM || op1code == CONST_DOUBLE) - operands[1] = force_reg (TQFmode, operands[1]); - } - else if (op1code == CONST_DOUBLE) - operands[1] = force_const_mem (TQFmode, operands[1]); - }") - - -;; add instructions - -;; single integer - -(define_insn "addqi3" - [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,r,m,m") - (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0,0") - (match_operand:QI 2 "general_operand" "I,J,i,r,m,I,J")))] - "" - "* - switch (which_alternative) - { - case 0: - return \"aisp r%0,%2\"; - case 1: - return \"sisp r%0,%J2\"; - case 2: - if (INTVAL(operands[2]) < 0) - return \"sim r%0,%J2\"; - else - return \"aim r%0,%2\"; - case 3: - return \"ar r%0,r%2\"; - case 4: - return \"a r%0,%2\"; - case 5: - return \"incm %2,%0\"; - case 6: - return \"decm %J2,%0\"; - } ") - -;; double integer -(define_insn "addhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (plus:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "general_operand" "r,m")))] - "" - "@ - dar r%0,r%2 - da r%0,%2 ") - -(define_insn "addhf3" - [(set (match_operand:HF 0 "register_operand" "=r,r") - (plus:HF (match_operand:HF 1 "register_operand" "%0,0") - (match_operand:HF 2 "general_operand" "r,m")))] - "" - "@ - far r%0,r%2 - fa r%0,%2 ") - -(define_insn "addtqf3" - [(set (match_operand:TQF 0 "register_operand" "=r,r") - (plus:TQF (match_operand:TQF 1 "register_operand" "%0,0") - (match_operand:TQF 2 "general_operand" "r,m")))] - "" - "@ - efar r%0,r%2 - efa r%0,%2 ") - - -;; subtract instructions - -;; single integer -(define_insn "subqi3" - [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,m") - (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0,0") - (match_operand:QI 2 "general_operand" "I,i,r,m,I")))] - "" - "@ - sisp r%0,%2 - sim r%0,%2 - sr r%0,r%2 - s r%0,%2 - decm %2,%0 ") - -;; double integer -(define_insn "subhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (minus:HI (match_operand:HI 1 "register_operand" "0,0") - (match_operand:HI 2 "general_operand" "r,m")))] - "" - "@ - dsr r%0,r%2 - ds r%0,%2 ") - -(define_insn "subhf3" - [(set (match_operand:HF 0 "register_operand" "=r,r") - (minus:HF (match_operand:HF 1 "register_operand" "0,0") - (match_operand:HF 2 "general_operand" "r,m")))] - "" - "@ - fsr r%0,r%2 - fs r%0,%2 ") - -(define_insn "subtqf3" - [(set (match_operand:TQF 0 "register_operand" "=r,r") - (minus:TQF (match_operand:TQF 1 "register_operand" "0,0") - (match_operand:TQF 2 "general_operand" "r,m")))] - "" - "@ - efsr r%0,r%2 - efs r%0,%2 ") - - -;; multiply instructions - -(define_insn "mulqi3" - [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r") - (mult:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0") - (match_operand:QI 2 "general_operand" "I,J,M,r,m")))] - "" - "@ - misp r%0,%2 - misn r%0,%J2 - msim r%0,%2 - msr r%0,r%2 - ms r%0,%2 ") - - -; 32-bit product -(define_insn "mulqihi3" - [(set (match_operand:HI 0 "register_operand" "=r,r,r") - (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%r,r,r")) - (sign_extend:HI (match_operand:QI 2 "general_operand" "r,m,i"))))] - "" - "* - if (REGNO (operands[1]) != REGNO (operands[0])) - output_asm_insn (\"lr r%0,r%1\", operands); - - switch (which_alternative) - { - case 0: - return \"mr r%0,r%2\"; - case 1: - return \"m r%0,%2\"; - case 2: - return \"mim r%0,%2\"; - } - ") - - -(define_insn "mulhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (mult:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "general_operand" "r,m")))] - "" - "@ - dmr r%0,r%2 - dm r%0,%2 ") - -; not available on 1750: "umulhi3","umulhisi3","umulsi3" (unsigned multiply's) - -(define_insn "mulhf3" - [(set (match_operand:HF 0 "register_operand" "=r,r") - (mult:HF (match_operand:HF 1 "register_operand" "%0,0") - (match_operand:HF 2 "general_operand" "r,m")))] - "" - "@ - fmr r%0,r%2 - fm r%0,%2 ") - -(define_insn "multqf3" - [(set (match_operand:TQF 0 "register_operand" "=r,r") - (mult:TQF (match_operand:TQF 1 "register_operand" "%0,0") - (match_operand:TQF 2 "general_operand" "r,m")))] - "" - "@ - efmr r%0,r%2 - efm r%0,%2 ") - - -;; divide instructions -;; The 1750 16bit integer division instructions deliver a 16-bit -;; quotient and a 16-bit remainder, where the remainder is in the next higher -;; register number above the quotient. For now, we haven't found a way -;; to give the reload pass knowledge of this property. So we make do with -;; whatever registers the allocator wants, and willy-nilly output a pair of -;; register-copy ops when needed. (See mod_regno_adjust() in file aux-output.c) -;; A comment in the description of `divmodM4' suggests that one leave the divM3 -;; undefined when there is a divmodM4 available. - -(define_insn "divmodqi4" - [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r") - (div:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0") - (match_operand:QI 2 "general_operand" "I,J,M,r,m"))) - (set (match_operand:QI 3 "register_operand" "=r,r,r,r,r") - (mod:QI (match_dup 1) (match_dup 2)))] - "" - "* - { - char *istr; - switch(which_alternative) - { - case 0: - istr = \"disp\"; - break; - case 1: - { - rtx new_opnds[4]; - new_opnds[0] = operands[0]; - new_opnds[1] = operands[1]; - new_opnds[2] = GEN_INT (-INTVAL(operands[2])); - new_opnds[3] = operands[3]; - istr = \"disn\"; - return mod_regno_adjust (istr, new_opnds); - } - break; - case 2: - istr = \"dvim\"; - break; - case 3: - istr = \"dvr \"; - break; - case 4: - istr = \"dv \"; - break; - } - return mod_regno_adjust (istr, operands); - }") - -;; Division for other types is straightforward. - -(define_insn "divhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (div:HI (match_operand:HI 1 "register_operand" "0,0") - (match_operand:HI 2 "general_operand" "r,m")))] - "" - "@ - ddr r%0,r%2 - dd r%0,%2 ") - -(define_insn "divhf3" - [(set (match_operand:HF 0 "register_operand" "=r,r") - (div:HF (match_operand:HF 1 "register_operand" "0,0") - (match_operand:HF 2 "general_operand" "r,m")))] - "" - "@ - fdr r%0,r%2 - fd r%0,%2 ") - -(define_insn "divtqf3" - [(set (match_operand:TQF 0 "register_operand" "=r,r") - (div:TQF (match_operand:TQF 1 "register_operand" "0,0") - (match_operand:TQF 2 "general_operand" "r,m")))] - "" - "@ - efdr r%0,r%2 - efd r%0,%2 ") - - -;; Other arithmetic instructions: - -;; Absolute value - -(define_insn "absqi2" - [(set (match_operand:QI 0 "register_operand" "=r") - (abs:QI (match_operand:QI 1 "register_operand" "r")))] - "" - "abs r%0,r%1") - -(define_insn "abshi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (abs:HI (match_operand:HI 1 "register_operand" "r")))] - "" - "dabs r%0,r%1") - -(define_insn "abshf2" - [(set (match_operand:HF 0 "register_operand" "=r") - (abs:HF (match_operand:HF 1 "register_operand" "r")))] - "" - "fabs r%0,r%1") - - -;; Negation - -(define_insn "negqi2" - [(set (match_operand:QI 0 "register_operand" "=r") - (neg:QI (match_operand:QI 1 "register_operand" "r")))] - "" - "neg r%0,r%1") - -(define_insn "neghi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (neg:HI (match_operand:HI 1 "register_operand" "r")))] - "" - "dneg r%0,r%1") - -(define_insn "neghf2" - [(set (match_operand:HF 0 "register_operand" "=r") - (neg:HF (match_operand:HF 1 "register_operand" "r")))] - "" - "fneg r%0,r%1") - -; The 1750A does not have an extended float negate instruction, so simulate. -(define_expand "negtqf2" - [(set (match_operand:TQF 0 "register_operand" "=&r") - (neg:TQF (match_operand:TQF 1 "register_operand" "r")))] - "" - " - emit_insn(gen_rtx(SET,VOIDmode,operands[0],CONST0_RTX(TQFmode))); - emit_insn(gen_rtx(SET,VOIDmode,operands[0], - gen_rtx(MINUS,TQFmode,operands[0],operands[1]))); - DONE; - ") - - -;; bit-logical instructions - -;; Set Bit -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=r,m") - (ior:QI (match_operand:QI 1 "general_operand" "0,0") - (match_operand:QI 2 "const_int_operand" "i,i")))] - "one_bit_set_p (INTVAL (operands [2]))" - "@ - sbr %b2,r%0 - sb %b2,%0") - -;; Reset Bit -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=r,m") - (and:QI (match_operand:QI 1 "general_operand" "0,0") - (match_operand:QI 2 "const_int_operand" "i,i")))] - "one_bit_set_p ((~INTVAL (operands [2])) & 0xffff)" - "@ - rbr %B2,r%0 - rb %B2,%0") - -;; Set Variable Bit -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (ior:QI (match_operand:QI 1 "register_operand" "0") - (lshiftrt:QI (const_int 0x8000) - (match_operand:QI 2 "register_operand" "r"))))] - "" - "svbr r%2,%r0") - -;; Reset Variable Bit -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=r") - (and:QI (match_operand:QI 1 "general_operand" "0") - (not:QI (lshiftrt:QI (const_int 0x8000) - (match_operand:QI 2 "register_operand" "r")))))] - "" - "rvbr r%2,%r0") - - -;; AND - -(define_insn "andqi3" - [(set (match_operand:QI 0 "general_operand" "=r,r,r") - (and:QI (match_operand:QI 1 "general_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "M,r,m")))] - "" - "@ - andm r%0,%2 - andr r%0,r%2 - and r%0,%2 ") - -; This sets incorrect condition codes. See notice_update_cc() -(define_insn "andhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (and:HI (match_operand:HI 1 "register_operand" "%0") - (match_operand:HI 2 "register_operand" "r")))] - "" - "danr.m %0,%2") - -;; OR - -(define_insn "iorqi3" - [(set (match_operand:QI 0 "general_operand" "=r,r,r") - (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "M,r,m")))] - "" - "@ - orim r%0,%2 - orr r%0,r%2 - or r%0,%2 ") - -; This sets incorrect condition codes. See notice_update_cc() -(define_insn "iorhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (ior:HI (match_operand:HI 1 "register_operand" "%0") - (match_operand:HI 2 "register_operand" "r")))] - "" - "dorr.m %0,%2") - -;; XOR - -(define_insn "xorqi3" - [(set (match_operand:QI 0 "register_operand" "=r,r,r") - (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "M,r,m")))] - "" - "@ - xorm r%0,%2 - xorr r%0,r%2 - xor r%0,%2 ") - -; This sets incorrect condition codes. See notice_update_cc() -(define_insn "xorhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (xor:HI (match_operand:HI 1 "register_operand" "%0") - (match_operand:HI 2 "register_operand" "r")))] - "" - "dxrr.m %0,%2") - -;; NAND - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r,r,r") - (ior:QI (not:QI (match_operand:QI 1 "register_operand" "%0,0,0")) - (not:QI (match_operand:QI 2 "general_operand" "M,r,m"))))] - "" - "@ - nim r%0,%2 - nr r%0,r%2 - n r%0,%2 ") - -; This sets incorrect condition codes. See notice_update_cc() -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (ior:HI (not:HI (match_operand:HI 1 "register_operand" "%0")) - (not:HI (match_operand:HI 2 "register_operand" "r"))))] - "" - "dnr.m %0,%2") - -;; NOT - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "register_operand" "=r") - (not:QI (match_operand:QI 1 "register_operand" "0")))] - "" - "nr r%0,r%0") - -; This sets incorrect condition codes. See notice_update_cc() -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (not:HI (match_operand:HI 1 "register_operand" "0")))] - "" - "dnr.m %0,%0") - - -;; Shift instructions - -; (What to the 1750 is logical-shift-left, GCC likes to call "arithmetic") -(define_insn "ashlqi3" - [(set (match_operand:QI 0 "register_operand" "=r,r") - (ashift:QI (match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,r")))] - "" - "@ - sll r%0,%2 - slr r%0,r%2 ") - -(define_insn "ashlhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (ashift:HI (match_operand:HI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "L,r")))] - "" ; the 'L' constraint is a slight imprecise... - "* - if (which_alternative == 1) - return \"dslr r%0,r%2\"; - else if (INTVAL(operands[2]) <= 16) - return \"dsll r%0,%2\"; - else - { - output_asm_insn (\"dsll r%0,16 ; ashlhi3 shiftcnt > 16\", operands); - return \"sll r%0,%w2\"; - } - ") - - -;; Right shift by a variable shiftcount works by negating the shift count, -;; then emitting a right shift with the shift count negated. This means -;; that all actual shift counts in the RTL will be positive. This -;; prevents converting shifts to ZERO_EXTRACTs with negative positions, -;; which isn't valid. -(define_expand "lshrqi3" - [(set (match_operand:QI 0 "register_operand" "=r") - (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "g")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, QImode, negate_rtx (QImode, operands[2])); -}") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "immediate_operand" "I")))] - "" - "srl r%0,%2") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "r"))))] - "" - "slr r%0,r%2 ") - -;; Same thing for HImode. - -(define_expand "lshrhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "g")))] - "" - " - { - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, QImode, negate_rtx (QImode, operands[2])); - }") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "immediate_operand" "L")))] - "" - "* - if (INTVAL (operands[2]) <= 16) - return \"dsrl r%0,%2\"; - output_asm_insn (\"dsrl r%0,16 ; lshrhi3 shiftcount > 16\", operands); - return \"srl r%d0,%w2\"; - ") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "r"))))] - "" - "dslr r%0,r%2 ") - -;; Same applies for arithmetic shift right. -(define_expand "ashrqi3" - [(set (match_operand:QI 0 "register_operand" "=r") - (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "g")))] - "" - " - { - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, QImode, negate_rtx (QImode, operands[2])); - }") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "immediate_operand" "I")))] - "" - "sra r%0,%2") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "r"))))] - "" - "sar r%0,r%2 ") - -;; HImode arithmetic shift right. -(define_expand "ashrhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "g")))] - "" - " - { - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, QImode, negate_rtx (QImode, operands[2])); - }") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "immediate_operand" "L")))] - "" - "* - if (INTVAL (operands[2]) <= 16) - return \"dsra r%0,%2\"; - output_asm_insn (\"dsra r%0,16 ; ashrhi3 shiftcount > 16\", operands); - return \"sra r%d0,%w2\"; - ") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "r"))))] - "" - "dsar r%0,r%2 ") - - -;; rotate instructions - -(define_insn "rotlqi3" - [(set (match_operand:QI 0 "register_operand" "=r,r") - (rotate:QI (match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,r")))] - "" - "@ - slc r%0,%2 - scr r%0,r%2 ") - -(define_insn "rotlhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (rotate:HI (match_operand:HI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "I,r")))] - "" - "@ - dslc r%0,%2 - dscr r%0,r%2 ") - -(define_insn "rotrqi3" - [(set (match_operand:QI 0 "register_operand" "=r") - (rotatert:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "r")))] - "" - "neg r%2,r%2\;scr r%0,r%2 ") - -(define_insn "rotrhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (rotatert:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "r")))] - "" - "neg r%2,r%2\;dscr r%0,r%2 ") - - - -;; Special cases of bit-field insns which we should -;; recognize in preference to the general case. -;; These handle aligned 8-bit and 16-bit fields, -;; which can usually be done with move instructions. -; 1750: t.b.d. -;******************** - -;; Bit field instructions, general cases. -;; "o,d" constraint causes a nonoffsettable memref to match the "o" -;; so that its address is reloaded. - -;; (define_insn "extv" ... - -;; (define_insn "extzv" ... - -;; (define_insn "insv" ... - -;; Now recognize bit field insns that operate on registers -;; (or at least were intended to do so). -;[unnamed only] - -;; Special patterns for optimizing bit-field instructions. -;************************************** - -; cc status test ops n.a. on 1750 ......... e.g. "sleu" on 68k: -; [(set (match_operand:QI 0 "general_operand" "=d") -; (leu (cc0) (const_int 0)))] -; "" -; "* cc_status = cc_prev_status; -; return \"sls %0\"; ") - - -;; Basic conditional jump instructions. - -(define_insn "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return branch_or_jump (\"ez\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return branch_or_jump (\"nz\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return branch_or_jump (\"gt\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return branch_or_jump (\"lt\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return branch_or_jump (\"ge\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return branch_or_jump (\"le\", CODE_LABEL_NUMBER (operands[0])); - ") - - -; no unsigned branches available on 1750. But GCC still needs them, so faking: - -(define_insn "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "jc gt,%l0 ; Warning: this should be an *unsigned* test!") - -(define_insn "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "jc lt,%l0 ; Warning: this should be an *unsigned* test!") - -(define_insn "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "jc ge,%l0 ; Warning: this should be an *unsigned* test!") - -(define_insn "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "jc le,%l0 ; Warning: this should be an *unsigned* test!") - - -;; Negated conditional jump instructions. - -(define_insn "" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return branch_or_jump (\"nz\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return branch_or_jump (\"ez\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return branch_or_jump (\"le\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return branch_or_jump (\"ge\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return branch_or_jump (\"lt\", CODE_LABEL_NUMBER (operands[0])); - ") - -(define_insn "" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return branch_or_jump (\"gt\", CODE_LABEL_NUMBER (operands[0])); - ") - - -;; Negated unsigned conditional jump instructions (faked for 1750). - -(define_insn "" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "jc le,%l0 ;inv.cond. ;Warning: this should be an *unsigned* test!") - -(define_insn "" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "jc ge,%l0 ;inv.cond. ;Warning: this should be an *unsigned* test!") - -(define_insn "" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "jc lt,%l0 ;inv.cond. ;Warning: this should be an *unsigned* test!") - -(define_insn "" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "jc gt,%l0 ;inv.cond. ;Warning: this should be an *unsigned* test!") - -;; Tablejump -;; 1750 note: CASE_VECTOR_PC_RELATIVE is not defined -(define_insn "tablejump" - [(set (pc) - (match_operand:QI 0 "register_operand" "b")) - (use (label_ref (match_operand 1 "" "")))] - "" - "jc 15,0,r%0 ; tablejump label_ref=%1") - - -;; Unconditional jump -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "jc 15,%0") - -;; Call subroutine, returning value in operand 0 -;; (which must be a hard register). -(define_insn "call_value" - [(set (match_operand 0 "register_operand" "r") - (call (match_operand:QI 1 "memory_operand" "m") - (match_operand:QI 2 "general_operand" "g")))] - ;; Operand 2 not really used for 1750. - "" - "sjs r15,%1 ; return value in R0") - -;; Call subroutine with no return value. - -;; Operand 1 not really used in MIL-STD-1750. -(define_insn "" - [(call (match_operand:QI 0 "memory_operand" "mp") - (match_operand:QI 1 "general_operand" ""))] - "" - "sjs r15,%0 ; no return value") - -;;;;;;;;;;;; 1750: NOT READY YET. -(define_insn "call" - [(call (match_operand:QI 0 "" "") - (match_operand:QI 1 "" ""))] - "" - "ANYCALL %0") - - -; (define_insn "return" -; [(return)] -; "" -; "* -; { -; rtx oprnd = GEN_INT (get_frame_size()); -; output_asm_insn(\"ret.m %0\",&oprnd); -; return \"\;\"; -; } ") - -(define_insn "indirect_jump" - [(set (pc) (match_operand:QI 0 "address_operand" "p"))] - "" - "jci 15,%0") - -(define_insn "nop" - [(const_int 0)] - "" - "nop") - - -;; Subtract One and Jump (if non-zero) -(define_peephole - [(set (match_operand:QI 0 "register_operand" "=r") - (plus:QI (match_operand:QI 1 "register_operand" "%0") - (match_operand:QI 2 "immediate_operand" "J"))) - (set (cc0) (match_dup 0)) - (set (pc) - (if_then_else (ne (cc0) (const_int 0)) - (label_ref (match_operand 3 "" "")) - (pc))) - ] - "INTVAL(operands[2]) == -1" - "soj r%0,%3") - -;; Combine a Load Register with subsequent increment/decrement into a LIM -(define_peephole - [(set (match_operand:QI 0 "register_operand" "=r") - (match_operand:QI 1 "register_operand" "b")) - (set (match_dup 0) - (plus:QI (match_dup 0) - (match_operand:QI 2 "immediate_operand" "i")))] - "REGNO(operands[1]) > 0" - "lim r%0,%2,r%1 ; LR,inc/dec peephole") - -;; Eliminate the redundant load in a store/load sequence -(define_peephole - [(set (mem:QI (plus:QI (match_operand:QI 0 "register_operand" "r") - (match_operand:QI 1 "immediate_operand" "i"))) - (match_operand:QI 2 "register_operand" "r")) - (set (match_operand:QI 3 "register_operand" "=r") - (mem:QI (plus:QI (match_dup 0) - (match_dup 1)))) - ] - "REGNO(operands[2]) == REGNO(operands[3])" - "st r%2,%1,r%0 ; eliminated previous redundant load") - -;;;End. diff --git a/gcc/config/1750a/ms1750.inc b/gcc/config/1750a/ms1750.inc deleted file mode 100755 index cb41e95..0000000 --- a/gcc/config/1750a/ms1750.inc +++ /dev/null @@ -1,158 +0,0 @@ -;; GCC assembler includefile for AS1750 -;; -;; Macros defined: -;; EFLR.M #d,#s Load the three regs starting at R#s to R#d following. -;; RET.M #fs Return from function (uses the framesize #fs) - - -UC SET 15 - -; Return from function ; parameter: framesize - MACRO RET.M - IF `1` > 0 - IF `1` <= 16 - AISP R14,`1` - ELSE - AIM R14,`1` - ENDIF - ENDIF - LR R15,R14 - URS R15 - ENDMACRO - -; Useful instructions missing from the 1750A standard: - -; Extended Float Load from Registers - MACRO EFLR.M ; args : #1=dest-regno, #2=source-regno -ONE SET `1` + 2 -TWO SET `2` + 2 - IF `1` >= `2` || `1`+2 < `2` - LR R`ONE`,R`TWO` - DLR R`1`,R`2` - ELSE - DLR R`1`,R`2` - LR R`ONE`,R`TWO` - DLR R`1`,R`1` ; Just to update condition codes - ENDIF - ENDMACRO - -; The following leave the condition codes haywire. But that is -; accounted for (see notice_update_cc in config/1750a.c.) - -; Double ANd Register with Register - MACRO DANR.M -ONE SET `1` + 1 -TWO SET `2` + 1 - ANDR R`1`,R`2` - ANDR R`ONE`,R`TWO` - ENDMACRO - -; Double OR Register with Register - MACRO DORR.M -ONE SET `1` + 1 -TWO SET `2` + 1 - ORR R`1`,R`2` - ORR R`ONE`,R`TWO` - ENDMACRO - -; Double eXoR Register with Register - MACRO DXRR.M -ONE SET `1` + 1 -TWO SET `2` + 1 - XORR R`1`,R`2` - XORR R`ONE`,R`TWO` - ENDMACRO - -; Double Nand Register with register - MACRO DNR.M -ONE SET `1` + 1 -TWO SET `2` + 1 - NR R`1`,R`2` - NR R`ONE`,R`TWO` - ENDMACRO - -; Unsigned Compare Immediate - - MACRO UCIM.M -LAST SET `1` + 3 - PSHM R`1`,R`LAST` -LO SET `1` + 1 - LR R`LO`,R`1` - XORR R`1`,R`1` -HI SET `1` + 2 - XORR R`HI`,R`HI` - LIM R`LAST`,`2` - DCR R`1`,R`HI` - POPM R`1`,R`LAST` - ENDMACRO - - -; Unsigned Compare Register with register - - MACRO UCR.M - PSHM R10,R13 ; R12 and R13 are assumed not to be input parameters - LR R13,R`2` - LR R11,R`1` - XORR R12,R12 - XORR R10,R10 - DCR R10,R12 - POPM R10,R13 - ENDMACRO - - -; Unsigned Compare register with memory - - MACRO UC.M - PSHM R10,R13 - L R13,`2` - LR R11,R`1` - XORR R12,R12 - XORR R10,R10 - DCR R10,R12 - POPM R10,R13 - ENDMACRO - - -; Double Unsigned Compare Register with register - - MACRO DUCR.M - PSHM R13,R14 ; R13 and R14 are assumed not to be input parameters -LOW1 SET `1` + 1 -LOW2 SET `2` + 1 - PSHM R`1`,R`LOW1` - PSHM R`2`,R`LOW2` - LR R13,R`LOW1` - LR R14,R`LOW2` - DSRL R`1`,1 - DSRL R`2`,1 - DCR R`1`,R`2` - BNE +6 - ANDM R13,1 - ANDM R14,1 - CR R13,R14 - POPM R`2`,R`LOW2` - POPM R`1`,R`LOW1` - POPM R13,R14 - ENDMACRO - - -; Double Unsigned Compare register with memory - - MACRO DUC.M - PSHM R13,R14 ; R13 and R14 are assumed not to be input parameters -LOW1 SET `1` + 1 - PSHM R`1`,R`LOW1` - DL R13,`2` - DSRL R`1`,1 - DSRL R13,1 - DCR R`1`,R13 - BNE +10 ; done, go pop the saved regs - DL R13,`2` ; interested in the *low* word (R14) - L R13,1,R15 - ANDM R13,1 - ANDM R14,1 - CR R13,R14 - POPM R`1`,R`LOW1` - POPM R13,R14 - ENDMACRO - diff --git a/gcc/config/1750a/xm-1750a.h b/gcc/config/1750a/xm-1750a.h deleted file mode 100755 index 81f5e69..0000000 --- a/gcc/config/1750a/xm-1750a.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Configuration for GNU C-compiler for MIL-STD-1750a. - Copyright (C) 1995 Free Software Foundation, Inc. - - This file is part of GNU CC. - - GNU CC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. - - GNU CC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNU CC; see the file COPYING. If not, write to - the Free Software Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - -*/ - -#error Gcc cannot run on a 1750a due to size problems! diff --git a/gcc/config/README b/gcc/config/README deleted file mode 100755 index 60328ec..0000000 --- a/gcc/config/README +++ /dev/null @@ -1,5 +0,0 @@ -This directory contains machine-specific files for the GNU C compiler. -It has a subdirectory for each basic CPU type. -The only files in this directory itself -are some .h files that pertain to particular operating systems -and are used for more than one CPU type. diff --git a/gcc/config/a29k/a29k.c b/gcc/config/a29k/a29k.c deleted file mode 100755 index 395a6ff..0000000 --- a/gcc/config/a29k/a29k.c +++ /dev/null @@ -1,1538 +0,0 @@ -/* Subroutines used for code generation on AMD Am29000. - Copyright (C) 1987, 88, 90-94, 1995, 1997 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@nyu.edu) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "recog.h" -#include "expr.h" -#include "obstack.h" -#include "tree.h" -#include "reload.h" - -#define min(A,B) ((A) < (B) ? (A) : (B)) - -/* This gives the size in words of the register stack for the current - procedure. */ - -static int a29k_regstack_size; - -/* True if the current procedure has a call instruction. */ - -static int a29k_makes_calls; - -/* This points to the last insn of the insn prologue. It is set when - an insn without a filled delay slot is found near the start of the - function. */ - -static char *a29k_last_prologue_insn; - -/* This points to the first insn that will be in the epilogue. It is null if - no epilogue is required. */ - -static char *a29k_first_epilogue_insn; - -/* This is nonzero if a a29k_first_epilogue_insn was put in a delay slot. It - indicates that an intermediate label needs to be written. */ - -static int a29k_first_epilogue_insn_used; - -/* Location to hold the name of the current function. We need this prolog to - contain the tag words prior to the declaration. So the name must be stored - away. */ - -char *a29k_function_name; - -/* Mapping of registers to debug register numbers. The only change is - for the frame pointer and the register numbers used for the incoming - arguments. */ - -int a29k_debug_reg_map[FIRST_PSEUDO_REGISTER]; - -/* Save information from a "cmpxx" operation until the branch or scc is - emitted. */ - -rtx a29k_compare_op0, a29k_compare_op1; -int a29k_compare_fp_p; - -/* Gives names for registers. */ -extern char *reg_names[]; - -/* Returns 1 if OP is a 8-bit constant. */ - -int -cint_8_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffffff00) == 0; -} - -/* Returns 1 if OP is a 16-bit constant. */ - -int -cint_16_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0; -} - -/* Returns 1 if OP is a constant that cannot be moved in a single insn. */ - -int -long_const_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (! CONSTANT_P (op)) - return 0; - - if (TARGET_29050 && GET_CODE (op) == CONST_INT - && (INTVAL (op) & 0xffff) == 0) - return 0; - - return (GET_CODE (op) != CONST_INT - || ((INTVAL (op) & 0xffff0000) != 0 - && (INTVAL (op) & 0xffff0000) != 0xffff0000 - && INTVAL (op) != 0x80000000)); -} - -/* The following four functions detect constants of 0, 8, 16, and 24 used as - a position in ZERO_EXTRACT operations. They can either be the appropriate - constant integer or a shift (which will be produced by combine). */ - -static int -shift_constant_operand (op, mode, val) - rtx op; - enum machine_mode mode; - int val; -{ - return ((GET_CODE (op) == CONST_INT && INTVAL (op) == val) - || (GET_CODE (op) == ASHIFT - && GET_CODE (XEXP (op, 0)) == CONST_INT - && INTVAL (XEXP (op, 0)) == val / 8 - && GET_CODE (XEXP (op, 1)) == CONST_INT - && INTVAL (XEXP (op, 1)) == 3)); -} - -int -const_0_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return shift_constant_operand (op, mode, 0); -} - -int -const_8_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return shift_constant_operand (op, mode, 8); -} - -int -const_16_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return shift_constant_operand (op, mode, 16); -} - -int -const_24_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return shift_constant_operand (op, mode, 24); -} - -/* Returns 1 if OP is a floating-point constant of the proper mode. */ - -int -float_const_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == mode; -} - -/* Returns 1 if OP is a floating-point constant of the proper mode or a - general-purpose register. */ - -int -gpc_reg_or_float_constant_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return float_const_operand (op, mode) || gpc_reg_operand (op, mode); -} - -/* Returns 1 if OP is an integer constant of the proper mode or a - general-purpose register. */ - -int -gpc_reg_or_integer_constant_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return ((GET_MODE (op) == VOIDmode - && (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)) - || gpc_reg_operand (op, mode)); -} - -/* Returns 1 if OP is a special machine register. */ - -int -spec_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != REG || GET_MODE (op) != mode) - return 0; - - switch (GET_MODE_CLASS (mode)) - { - case MODE_PARTIAL_INT: - return REGNO (op) >= R_BP && REGNO (op) <= R_CR; - case MODE_INT: - return REGNO (op) >= R_Q && REGNO (op) <= R_EXO; - default: - return 0; - } -} - -/* Returns 1 if OP is an accumulator register. */ - -int -accum_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (GET_CODE (op) == REG - && REGNO (op) >= R_ACU (0) && REGNO (op) <= R_ACU (3)); -} - -/* Returns 1 if OP is a normal data register. */ - -int -gpc_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; - - if (GET_CODE (op) == REG) - regno = REGNO (op); - else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) - { - regno = REGNO (SUBREG_REG (op)); - if (regno < FIRST_PSEUDO_REGISTER) - regno += SUBREG_WORD (op); - } - else - return 0; - - return (regno >= FIRST_PSEUDO_REGISTER || regno < R_BP - || (regno >= R_KR (0) && regno <= R_KR (31))); -} - -/* Returns 1 if OP is either an 8-bit constant integer or a general register. - If a register, it must be in the proper mode unless MODE is VOIDmode. */ - -int -srcb_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT - && (mode == QImode - || (INTVAL (op) & 0xffffff00) == 0)) - return 1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; - - return gpc_reg_operand (op, mode); -} - -int -cmplsrcb_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT - && (mode == QImode - || (INTVAL (op) & 0xffffff00) == 0xffffff00)) - return 1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; - - return gpc_reg_operand (op, mode); -} - -/* Return 1 if OP is either an immediate or a general register. This is used - for the input operand of mtsr/mtrsim. */ - -int -gpc_reg_or_immediate_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return gpc_reg_operand (op, mode) || immediate_operand (op, mode); -} - -/* Return 1 if OP can be used as the second operand of and AND insn. This - includes srcb_operand and a constant whose complement fits in 8 bits. */ - -int -and_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (srcb_operand (op, mode) - || (GET_CODE (op) == CONST_INT - && ((unsigned) ((~ INTVAL (op)) & GET_MODE_MASK (mode)) < 256))); -} - -/* Return 1 if OP can be used as the second operand of an ADD insn. - This is the same as above, except we use negative, rather than - complement. */ - -int -add_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (srcb_operand (op, mode) - || (GET_CODE (op) == CONST_INT - && ((unsigned) ((- INTVAL (op)) & GET_MODE_MASK (mode)) < 256))); -} - -/* Return 1 if OP is a valid address in a CALL_INSN. These are a SYMBOL_REF - to the current function, all SYMBOL_REFs if TARGET_SMALL_MEMORY, or - a sufficiently-small constant. */ - -int -call_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF: - return (TARGET_SMALL_MEMORY - || (! TARGET_LARGE_MEMORY - && ((GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FLAG (op)) - || ! strcmp (XSTR (op, 0), current_function_name)))); - - case CONST_INT: - return (unsigned HOST_WIDE_INT) INTVAL (op) < 0x40000; - - default: - return 0; - } -} - -/* Return 1 if OP can be used as the input operand for a move insn. */ - -int -in_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx orig_op = op; - - if (! general_operand (op, mode)) - return 0; - - while (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - switch (GET_CODE (op)) - { - case REG: - return 1; - - case MEM: - return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE); - - case CONST_INT: - if (GET_MODE_CLASS (mode) != MODE_INT - && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) - return 0; - - return 1; - - case CONST: - case SYMBOL_REF: - case LABEL_REF: - return (GET_MODE (op) == mode - || mode == SImode || mode == HImode || mode == QImode); - - case CONST_DOUBLE: - return ((GET_MODE_CLASS (mode) == MODE_FLOAT - && mode == GET_MODE (op)) - || (GET_MODE (op) == VOIDmode - && GET_MODE_CLASS (mode) == MODE_INT)); - - default: - return 0; - } -} - -/* Return 1 if OP can be used as the output operand for a move insn. */ - -int -out_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx orig_op = op; - - if (! general_operand (op, mode)) - return 0; - - while (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) == REG) - return (gpc_reg_operand (orig_op, mode) - || spec_reg_operand (orig_op, mode) - || (GET_MODE_CLASS (mode) == MODE_FLOAT - && accum_reg_operand (orig_op, mode))); - - else if (GET_CODE (op) == MEM) - return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE); - else - return 0; -} - -/* Return 1 if OP is an item in memory, given that we are in reload. */ - -int -reload_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno = true_regnum (op); - - return (! CONSTANT_P (op) - && (regno == -1 - || (GET_CODE (op) == REG - && REGNO (op) >= FIRST_PSEUDO_REGISTER))); -} - -/* Given an object for which reload_memory_operand is true, return the address - of the operand, taking into account anything that reload may do. */ - -rtx -a29k_get_reloaded_address (op) - rtx op; -{ - if (GET_CODE (op) == SUBREG) - { - if (SUBREG_WORD (op) != 0) - abort (); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) == REG) - op = reg_equiv_mem[REGNO (op)]; - - return find_replacement (&XEXP (op, 0)); -} - -/* Subfunction of the following function. Update the flags of any MEM - found in part of X. */ - -static void -a29k_set_memflags_1 (x, in_struct_p, scalar_p, volatile_p, unchanging_p) - rtx x; - int in_struct_p, scalar_p, volatile_p, unchanging_p; -{ - int i; - - switch (GET_CODE (x)) - { - case SEQUENCE: - case PARALLEL: - for (i = XVECLEN (x, 0) - 1; i >= 0; i--) - a29k_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p, - unchanging_p); - break; - - case INSN: - a29k_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p, - unchanging_p); - break; - - case SET: - a29k_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p, - unchanging_p); - a29k_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p, unchanging_p); - break; - - case MEM: - MEM_IN_STRUCT_P (x) = in_struct_p; - MEM_SCALAR_P (x) = scalar_p; - MEM_VOLATILE_P (x) = volatile_p; - RTX_UNCHANGING_P (x) = unchanging_p; - break; - } -} - -/* Given INSN, which is either an INSN or a SEQUENCE generated to - perform a memory operation, look for any MEMs in either a SET_DEST or - a SET_SRC and copy the in-struct, unchanging, and volatile flags from - REF into each of the MEMs found. If REF is not a MEM, don't do - anything. */ - -void -a29k_set_memflags (insn, ref) - rtx insn; - rtx ref; -{ - /* Note that it is always safe to get these flags, though they won't - be what we think if REF is not a MEM. */ - int in_struct_p = MEM_IN_STRUCT_P (ref); - int scalar_p = MEM_IN_SCALAR_P (ref); - int volatile_p = MEM_VOLATILE_P (ref); - int unchanging_p = RTX_UNCHANGING_P (ref); - - if (GET_CODE (ref) != MEM - || (! in_struct_p && ! volatile_p && ! unchanging_p)) - return; - - a29k_set_memflags_1 (insn, in_struct_p, scalar_p, volatile_p, unchanging_p); -} - -/* Return 1 if OP is a comparison operator that we have in floating-point. */ - -int -fp_comparison_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - return ((mode == VOIDmode || mode == GET_MODE (op)) - && (GET_CODE (op) == EQ || GET_CODE (op) == GT || - GET_CODE (op) == GE)); -} - -/* Return 1 if OP is a valid branch comparison. */ - -int -branch_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - return ((mode == VOIDmode || mode == GET_MODE (op)) - && (GET_CODE (op) == GE || GET_CODE (op) == LT)); -} - -/* Return 1 if OP is a load multiple operation. It is known to be a - PARALLEL and the first three sections will be tested. */ - -int -load_multiple_operation (op, mode) - rtx op; - enum machine_mode mode; -{ - int count = XVECLEN (op, 0) - 2; - 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 + 2); - - 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. */ - -int -store_multiple_operation (op, mode) - rtx op; - enum machine_mode mode; -{ - int num_special = TARGET_NO_STOREM_BUG ? 2 : 1; - int count = XVECLEN (op, 0) - num_special; - 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 + num_special); - - 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; -} - -/* Given a special register REG and MASK, a value being masked against a - quantity to which the special register is set, return 1 if the masking - operation is built-in to the setting of that special register. */ - -int -masks_bits_for_special (reg, mask) - rtx reg; - rtx mask; -{ - int needed_mask_value; - - if (GET_CODE (reg) != REG || GET_CODE (mask) != CONST_INT) - abort (); - - switch (REGNO (reg)) - { - case R_BP: - case R_INT: - needed_mask_value = 3; - break; - - case R_FC: - needed_mask_value = 31; - break; - - case R_CR: - case R_LRU: - needed_mask_value = 255; - break; - - case R_FPE: - needed_mask_value = 511; - break; - - case R_MMU: - needed_mask_value = 0x3ff; - break; - - case R_OPS: - case R_CPS: - case R_RBP: - case R_FPS: - needed_mask_value = 0xffff; - break; - - case R_VAB: - needed_mask_value = 0xffff0000; - break; - - case R_Q: - case R_CFG: - case R_CHA: - case R_CHD: - case R_CHC: - case R_TMC: - case R_TMR: - case R_PC0: - case R_PC1: - case R_PC2: - return 0; - - default: - abort (); - } - - return (INTVAL (mask) & ~ needed_mask_value) == 0; -} - -/* Return nonzero if this label is that of the return point, but there is - a non-null epilogue. */ - -int -epilogue_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return next_active_insn (op) == 0 && a29k_first_epilogue_insn != 0; -} - -/* Return the register class of a scratch register needed to copy IN into - or out of a register in CLASS in MODE. If it can be done directly, - NO_REGS is returned. */ - -enum reg_class -secondary_reload_class (class, mode, in) - enum reg_class class; - enum machine_mode mode; - rtx in; -{ - int regno = -1; - enum rtx_code code = GET_CODE (in); - - if (! CONSTANT_P (in)) - { - regno = true_regnum (in); - - /* A pseudo is the same as memory. */ - if (regno == -1 || regno >= FIRST_PSEUDO_REGISTER) - code = MEM; - } - - /* If we are transferring between memory and a multi-word mode, we need - CR. */ - - if (code == MEM && GET_MODE_SIZE (mode) > UNITS_PER_WORD) - return CR_REGS; - - /* If between memory and a mode smaller than a word without DW being - enabled, we need BP. */ - - if (code == MEM && ! TARGET_DW_ENABLE - && GET_MODE_SIZE (mode) < UNITS_PER_WORD) - return BP_REGS; - - /* Otherwise, we can place anything into GENERAL_REGS and can put - GENERAL_REGS into anything. */ - if (class == GENERAL_REGS - || (regno != -1 - && (regno < R_BP - || (regno >= R_KR (0) && regno <= R_KR (31))))) - return NO_REGS; - - /* We can place 16-bit constants into a special register. */ - if (code == CONST_INT - && (GET_MODE_BITSIZE (mode) <= 16 || (unsigned) INTVAL (in) <= 65535) - && (class == BP_REGS || class == Q_REGS || class == SPECIAL_REGS)) - return NO_REGS; - - /* Otherwise, we need GENERAL_REGS. */ - return GENERAL_REGS; -} - -/* START is the zero-based incoming argument register index used (0 is 160, - i.e., the first incoming argument register) and COUNT is the number used. - - Mark the corresponding incoming registers as neither fixed nor call used. - For each register used for incoming arguments, we have one less local - register that can be used. So also mark some high-numbered registers as - fixed. - - Return the first register number to use for the argument. */ - -int -incoming_reg (start, count) - int start; - int count; -{ - int i; - - /* We only use 16 argument registers, so truncate at the end of the - area. */ - if (start + count > 16) - count = 16 - start; - - if (! TARGET_NO_REUSE_ARGS) - /* Mark all the used registers as not fixed and saved over calls. */ - for (i = R_AR (start); i < R_AR (start + count); i++) - { - fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 0; - CLEAR_HARD_REG_BIT (fixed_reg_set, i); - CLEAR_HARD_REG_BIT (call_used_reg_set, i); - CLEAR_HARD_REG_BIT (call_fixed_reg_set, i); - } - - /* Shorten the maximum size of the frame. - Remember that R_AR(-1,-2) are place holders for the caller's lr0,lr1. - Make sure to keep the frame rounded to an even boundary. Rounding up - to an 8 byte boundary will use a slot. Otherwise a frame with 121 local - regs and 5 arguments will overrun the stack (121+1 + 5 + 2 > 128). */ - /* ??? An alternative would be to never allocate one reg. */ - for (i = (R_AR (0) - 2 - start - count) & ~1; i < R_AR (0) - 2 - start; i++) - { - fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1; - SET_HARD_REG_BIT (fixed_reg_set, i); - SET_HARD_REG_BIT (call_used_reg_set, i); - SET_HARD_REG_BIT (call_fixed_reg_set, i); - } - - return R_AR (start); -} - -/* Add CLOBBERs to CALL_INSN_FUNCTION_USAGE chain of INSN indicating - that LR2 up to, but not including, OP are clobbered. If OP is - zero, indicate all parameter registers are clobbered. */ - -void -a29k_clobbers_to (insn, op) - rtx insn; - rtx op; -{ - int i; - int high_regno; - - if (op == 0) - high_regno = R_LR (18); - else if (GET_CODE (op) != REG || REGNO (op) < R_LR (0) - || REGNO (op) > R_LR (18)) - abort (); - else - high_regno = REGNO (op); - - for (i = R_LR (2); i < high_regno; i++) - CALL_INSN_FUNCTION_USAGE (insn) - = gen_rtx (EXPR_LIST, VOIDmode, - gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, i)), - CALL_INSN_FUNCTION_USAGE (insn)); -} - -/* These routines are used in finding insns to fill delay slots in the - epilogue. */ - -/* Return 1 if the current function will adjust the register stack. */ - -int -needs_regstack_p () -{ - int i; - rtx insn; - - if (frame_pointer_needed) - return 1; - - /* If any local register is used, we need to adjust the regstack. */ - for (i = R_LR (127); i >= R_LR (0); i --) - if (regs_ever_live[i]) - return 1; - - /* We need a register stack if we make any calls. */ - for (insn = get_insns (); insn; insn = next_insn (insn)) - if (GET_CODE (insn) == CALL_INSN - || (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SEQUENCE - && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN)) - return 1; - - /* Otherwise, we don't. */ - return 0; -} - -/* Return 1 if X uses a local register. */ - -int -uses_local_reg_p (x) - rtx x; -{ - char *fmt; - int i, j; - - switch (GET_CODE (x)) - { - case REG: - return REGNO (x) >= R_LR (0) && REGNO (x) <= R_FP; - - case CONST_INT: - case CONST: - case PC: - case CC0: - case LABEL_REF: - case SYMBOL_REF: - 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') - { - if (uses_local_reg_p (XEXP (x, i))) - return 1; - } - else if (fmt[i] == 'E') - { - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if (uses_local_reg_p (XVECEXP (x, i, j))) - return 1; - } - } - - return 0; -} - -/* Returns 1 if this function is known to have a null epilogue. */ - -int -null_epilogue () -{ - return (reload_completed && ! needs_regstack_p () - && get_frame_size () == 0 - && current_function_pretend_args_size == 0); -} - -/* Write out the assembler form of an operand. Recognize the following - special options: - - %N means write the low-order 8 bits of the negative of the constant - %Q means write a QImode operand (truncate constants to 8 bits) - %M means write the low-order 16 bits of the constant - %m means write the low-order 16 bits shifted left 16 bits - %C means write the low-order 8 bits of the complement of the constant - %b means write `f' is this is a reversed condition, `t' otherwise - %B means write `t' is this is a reversed condition, `f' otherwise - %J means write the 29k opcode part for a comparison operation - %e means write the label with an extra `X' is this is the epilogue - otherwise the normal label name - %E means write nothing if this insn has a delay slot, - a nop unless this is the epilogue label, in which case - write the first epilogue insn - %F means write just the normal operand if the insn has a delay slot; - otherwise, this is a recursive call so output the - symbol + 4 and write the first prologue insn in the - delay slot. - %L means write the register number plus one ("low order" register) - or the low-order part of a multi-word constant - %O means write the register number plus two - %P means write the register number plus three ("low order" of TImode) - %S means write the number of words in the mode of the operand, - minus one (for CR) - %V means write the number of elements in a PARALLEL minus 1 - %# means write nothing if we have a delay slot, "\n\tnop" otherwise - %* means write the register name for TPC. */ - -void -print_operand (file, x, code) - FILE *file; - rtx x; - char code; -{ - char buf[100]; - - /* These macros test for integers and extract the low-order bits. */ -#define INT_P(X) \ -((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \ - && GET_MODE (X) == VOIDmode) - -#define INT_LOWPART(X) \ - (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X)) - - switch (code) - { - case 'Q': - if (GET_CODE (x) == REG) - break; - else if (! INT_P (x)) - output_operand_lossage ("invalid %%Q value"); - fprintf (file, "%d", INT_LOWPART (x) & 0xff); - return; - - case 'C': - if (! INT_P (x)) - output_operand_lossage ("invalid %%C value"); - fprintf (file, "%d", (~ INT_LOWPART (x)) & 0xff); - return; - - case 'N': - if (! INT_P (x)) - output_operand_lossage ("invalid %%N value"); - fprintf (file, "%d", (- INT_LOWPART (x)) & 0xff); - return; - - case 'M': - if (! INT_P (x)) - output_operand_lossage ("invalid %%M value"); - fprintf (file, "%d", INT_LOWPART (x) & 0xffff); - return; - - case 'm': - if (! INT_P (x)) - output_operand_lossage ("invalid %%m value"); - fprintf (file, "%d", (INT_LOWPART (x) & 0xffff) << 16); - return; - - case 'b': - if (GET_CODE (x) == GE) - fprintf (file, "f"); - else - fprintf (file, "t"); - return; - - case 'B': - if (GET_CODE (x) == GE) - fprintf (file, "t"); - else - fprintf (file, "f"); - return; - - case 'J': - /* It so happens that the RTX names for the conditions are the same as - the 29k's insns except for "ne", which requires "neq". */ - fprintf (file, GET_RTX_NAME (GET_CODE (x))); - if (GET_CODE (x) == NE) - fprintf (file, "q"); - return; - - case 'e': - if (optimize && flag_delayed_branch - && a29k_last_prologue_insn == 0 && epilogue_operand (x, VOIDmode) - && dbr_sequence_length () == 0) - { - /* We need to output the label number of the last label in the - function, which is not necessarily X since there might be - a USE insn in between. First go forward to the last insn, then - back up to a label. */ - while (NEXT_INSN (x) != 0) - x = NEXT_INSN (x); - - while (GET_CODE (x) != CODE_LABEL) - x = PREV_INSN (x); - - ASM_GENERATE_INTERNAL_LABEL (buf, "LX", CODE_LABEL_NUMBER (x)); - assemble_name (file, buf); - } - else - output_asm_label (x); - return; - - case 'E': - if (dbr_sequence_length ()) - ; - else if (a29k_last_prologue_insn) - { - fprintf (file, "\n\t%s", a29k_last_prologue_insn); - a29k_last_prologue_insn = 0; - } - else if (optimize && flag_delayed_branch - && epilogue_operand (x, VOIDmode)) - { - fprintf (file, "\n\t%s", a29k_first_epilogue_insn); - a29k_first_epilogue_insn_used = 1; - } - else - fprintf (file, "\n\tnop"); - return; - - case 'F': - output_addr_const (file, x); - if (dbr_sequence_length () == 0) - { - /* If this doesn't have its delay slot filled, see if we need to - put the last insn of the prolog in it. If not, see if this is - a recursive call. If so, we can put the first insn of its - prolog in the delay slot. Otherwise, write a nop. */ - if (a29k_last_prologue_insn) - { - fprintf (file, "\n\t%s", a29k_last_prologue_insn); - a29k_last_prologue_insn = 0; - } - else if (GET_CODE (x) == SYMBOL_REF - && ! strcmp (XSTR (x, 0), current_function_name)) - fprintf (file, "+4\n\t%s,%d", - a29k_regstack_size >= 64 ? "const gr121" : "sub gr1,gr1", - a29k_regstack_size * 4); - else - fprintf (file, "\n\tnop"); - } - return; - - case 'L': - if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode) - { - union real_extract u; - - bcopy ((char *) &CONST_DOUBLE_LOW (x), (char *) &u, sizeof u); - fprintf (file, "$double1(%.20e)", u.d); - } - else if (GET_CODE (x) == REG) - fprintf (file, "%s", reg_names[REGNO (x) + 1]); - else - output_operand_lossage ("invalid %%L value"); - return; - - case 'O': - if (GET_CODE (x) != REG) - output_operand_lossage ("invalid %%O value"); - fprintf (file, "%s", reg_names[REGNO (x) + 2]); - return; - - case 'P': - if (GET_CODE (x) != REG) - output_operand_lossage ("invalid %%P value"); - fprintf (file, "%s", reg_names[REGNO (x) + 3]); - return; - - case 'S': - fprintf (file, "%d", (GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD)-1); - return; - - case 'V': - if (GET_CODE (x) != PARALLEL) - output_operand_lossage ("invalid %%V value"); - fprintf (file, "%d", XVECLEN (x, 0) - 2); - return; - - case '#': - if (dbr_sequence_length () == 0) - { - if (a29k_last_prologue_insn) - { - fprintf (file, "\n\t%s", a29k_last_prologue_insn); - a29k_last_prologue_insn = 0; - } - else - fprintf (file, "\n\tnop"); - } - return; - - case '*': - fprintf (file, "%s", reg_names [R_TPC]); - return; - } - - if (GET_CODE (x) == REG) - fprintf (file, "%s", reg_names [REGNO (x)]); - - else if (GET_CODE (x) == MEM) - output_address (XEXP (x, 0)); - - else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == SUBREG - && GET_CODE (SUBREG_REG (XEXP (x, 0))) == CONST_DOUBLE) - { - union real_extract u; - - if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode) - fprintf (file, "$float"); - else - fprintf (file, "$double%d", SUBREG_WORD (XEXP (x, 0))); - bcopy ((char *) &CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), - (char *) &u, sizeof u); - fprintf (file, "(%.20e)", u.d); - } - - else if (GET_CODE (x) == CONST_DOUBLE - && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) - { - union real_extract u; - - bcopy ((char *) &CONST_DOUBLE_LOW (x), (char *) &u, sizeof u); - fprintf (file, "$%s(%.20e)", - GET_MODE (x) == SFmode ? "float" : "double0", u.d); - } - - else - output_addr_const (file, x); -} - -/* This page contains routines to output function prolog and epilog code. */ - -/* Compute the size of the register stack, and determine if there are any - call instructions. */ - -static void -compute_regstack_size () -{ - int i; - rtx insn; - - /* See if we make any calls. We need to set lr1 if so. */ - a29k_makes_calls = 0; - for (insn = get_insns (); insn; insn = next_insn (insn)) - if (GET_CODE (insn) == CALL_INSN - || (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SEQUENCE - && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN)) - { - a29k_makes_calls = 1; - break; - } - - /* Find the highest local register used. */ - for (i = R_LR (127); i >= R_LR (0); i--) - if (regs_ever_live[i]) - break; - - a29k_regstack_size = i - (R_LR (0) - 1); - - /* If calling routines, ensure we count lr0 & lr1. */ - if (a29k_makes_calls && a29k_regstack_size < 2) - a29k_regstack_size = 2; - - /* Count frame pointer and align to 8 byte boundary (even number of - registers). */ - a29k_regstack_size += frame_pointer_needed; - if (a29k_regstack_size & 1) a29k_regstack_size++; -} - -/* Sets register names for incoming arguments and frame pointer. - This can't be computed until after register allocation. */ - -void -a29k_compute_reg_names () -{ - int i; - - compute_regstack_size (); - - /* Set the names and numbers of the frame pointer and incoming argument - registers. */ - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - a29k_debug_reg_map[i] = i; - - reg_names[FRAME_POINTER_REGNUM] = reg_names[R_LR (a29k_regstack_size - 1)]; - a29k_debug_reg_map[FRAME_POINTER_REGNUM] = R_LR (a29k_regstack_size - 1); - - for (i = 0; i < 16; i++) - { - reg_names[R_AR (i)] = reg_names[R_LR (a29k_regstack_size + i + 2)]; - a29k_debug_reg_map[R_AR (i)] = R_LR (a29k_regstack_size + i + 2); - } - - /* If using kernel register map, swap numbers for kernel and user - registers. */ - if (TARGET_KERNEL_REGISTERS) - for (i = 0; i < 32; i++) - { - int tem = a29k_debug_reg_map[i]; - a29k_debug_reg_map[i] = a29k_debug_reg_map[R_KR (i)]; - a29k_debug_reg_map[R_KR (i)] = tem; - } -} - -/* Output function prolog code to file FILE. Memory stack size is SIZE. */ - -void -output_prolog (file, size) - FILE *file; - int size; -{ - int i; - int arg_count = 0; - rtx insn; - unsigned int tag_word; - - /* See how many incoming arguments we have in registers. */ - for (i = R_AR (0); i < R_AR (16); i++) - if (! fixed_regs[i]) - arg_count++; - - /* The argument count includes the caller's lr0 and lr1. */ - arg_count += 2; - - /* Compute memory stack size. Add in number of bytes that the we should - push and pretend the caller did and the size of outgoing arguments. - Then round to a doubleword boundary. */ - size += (current_function_pretend_args_size - + current_function_outgoing_args_size); - size = (size + 7) & ~7; - - /* Write header words. See if one or two word form. */ - tag_word = (frame_pointer_needed ? 0x400000 : 0) + (arg_count << 16); - - if (size / 8 > 0xff) - fprintf (file, "\t.word %d, 0x%0x\n", (size / 8) << 2, - 0x800000 + tag_word); - else - fprintf (file, "\t.word 0x%0x\n", tag_word + ((size / 8) << 3)); - - /* Define the function name. */ - assemble_name (file, a29k_function_name); - fprintf (file, ":\n"); - - /* Push the register stack by the proper amount. There are two possible - ways to do this. */ - if (a29k_regstack_size >= 256/4) - fprintf (file, "\tconst %s,%d\n\tsub gr1,gr1,%s\n", - reg_names[R_TAV], a29k_regstack_size * 4, reg_names[R_TAV]); - else if (a29k_regstack_size) - fprintf (file, "\tsub gr1,gr1,%d\n", a29k_regstack_size * 4); - - /* Test that the registers are available. */ - if (a29k_regstack_size) - fprintf (file, "\tasgeu V_%sSPILL,gr1,%s\n", - TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RAB]); - - /* Set up frame pointer, if one is needed. */ - if (frame_pointer_needed) - fprintf (file, "\tsll %s,%s,0\n", reg_names[FRAME_POINTER_REGNUM], - reg_names[R_MSP]); - - /* Make room for any frame space. There are three ways to do this. */ - if (size >= 256) - { - fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size); - if (size >= 65536) - fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size); - if (TARGET_STACK_CHECK) - fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]); - fprintf (file, "\tsub %s,%s,%s\n", - reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]); - } - else if (size) - { - if (TARGET_STACK_CHECK) - fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]); - fprintf (file, "\tsub %s,%s,%d\n", - reg_names[R_MSP], reg_names[R_MSP], size); - } - - /* If this routine will make calls, set lr1. If we see an insn that - can use a delay slot before a call or jump, save this insn for that - slot (this condition is equivalent to seeing if we have an insn that - needs delay slots before an insn that has a filled delay slot). */ - a29k_last_prologue_insn = 0; - if (a29k_makes_calls) - { - i = (a29k_regstack_size + arg_count) * 4; - if (i >= 256) - fprintf (file, "\tconst %s,%d\n\tadd lr1,gr1,%s\n", - reg_names[R_TAV], i, reg_names[R_TAV]); - else - { - if (optimize && flag_delayed_branch) - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - if (GET_CODE (insn) == CODE_LABEL - || (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SEQUENCE)) - break; - - if (GET_CODE (insn) == NOTE - || (GET_CODE (insn) == INSN - && (GET_CODE (PATTERN (insn)) == USE - || GET_CODE (PATTERN (insn)) == CLOBBER))) - continue; - - if (num_delay_slots (insn) > 0) - { - a29k_last_prologue_insn = (char *) oballoc (100); - sprintf (a29k_last_prologue_insn, "add lr1,gr1,%d", i); - break; - } - } - - if (a29k_last_prologue_insn == 0) - fprintf (file, "\tadd lr1,gr1,%d\n", i); - } - } - - /* Compute the first insn of the epilogue. */ - a29k_first_epilogue_insn_used = 0; - - if (size == 0 && a29k_regstack_size == 0 && ! frame_pointer_needed) - a29k_first_epilogue_insn = 0; - else - a29k_first_epilogue_insn = (char *) oballoc (100); - - if (frame_pointer_needed) - sprintf (a29k_first_epilogue_insn, "sll %s,%s,0", - reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]); - else if (a29k_regstack_size) - { - if (a29k_regstack_size >= 256 / 4) - sprintf (a29k_first_epilogue_insn, "const %s,%d", - reg_names[R_TAV], a29k_regstack_size * 4); - else - sprintf (a29k_first_epilogue_insn, "add gr1,gr1,%d", - a29k_regstack_size * 4); - } - else if (size) - { - if (size >= 256) - sprintf (a29k_first_epilogue_insn, "const %s,%d", - reg_names[R_TAV], size); - else - sprintf (a29k_first_epilogue_insn, "add %s,%s,%d", - reg_names[R_MSP], reg_names[R_MSP], size); - } -} - -/* Call this after writing what might be the first instruction of the - epilogue. If that first insn was used in a delay slot, an intermediate - label is written. */ - -static void -check_epilogue_internal_label (file) - FILE *file; -{ - rtx insn; - - if (! a29k_first_epilogue_insn_used) - return; - - for (insn = get_last_insn (); - GET_CODE (insn) != CODE_LABEL; - insn = PREV_INSN (insn)) - ; - - ASM_OUTPUT_INTERNAL_LABEL (file, "LX", CODE_LABEL_NUMBER (insn)); - a29k_first_epilogue_insn_used = 0; -} - -/* Output the epilog of the last procedure to file FILE. SIZE is the memory - stack size. The register stack size is in the variable - A29K_REGSTACK_SIZE. */ - -void -output_epilog (file, size) - FILE *file; - int size; -{ - rtx insn; - int locals_unavailable = 0; /* True until after first insn - after gr1 update. */ - - /* If we hit a BARRIER before a real insn or CODE_LABEL, we don't - need to do anything because we are never jumped to. */ - insn = get_last_insn (); - if (GET_CODE (insn) == NOTE) - insn = prev_nonnote_insn (insn); - - if (insn && GET_CODE (insn) == BARRIER) - return; - - /* If a frame pointer was needed we must restore the memory stack pointer - before adjusting the register stack. */ - if (frame_pointer_needed) - { - fprintf (file, "\tsll %s,%s,0\n", - reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]); - check_epilogue_internal_label (file); - } - - /* Restore the register stack. There are two ways to do this. */ - if (a29k_regstack_size) - { - if (a29k_regstack_size >= 256/4) - { - fprintf (file, "\tconst %s,%d\n", - reg_names[R_TAV], a29k_regstack_size * 4); - check_epilogue_internal_label (file); - fprintf (file, "\tadd gr1,gr1,%s\n", reg_names[R_TAV]); - } - else - { - fprintf (file, "\tadd gr1,gr1,%d\n", a29k_regstack_size * 4); - check_epilogue_internal_label (file); - } - locals_unavailable = 1; - } - - /* Restore the memory stack pointer if there is no frame pointer. - Adjust the size to include any pretend arguments and pushed - arguments and round to doubleword boundary. */ - size += (current_function_pretend_args_size - + current_function_outgoing_args_size); - size = (size + 7) & ~7; - - if (size && ! frame_pointer_needed) - { - if (size >= 256) - { - fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size); - check_epilogue_internal_label (file); - locals_unavailable = 0; - if (size >= 65536) - fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size); - fprintf (file, "\tadd %s,%s,%s\n", - reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]); - } - else - { - fprintf (file, "\tadd %s,%s,%d\n", - reg_names[R_MSP], reg_names[R_MSP], size); - check_epilogue_internal_label (file); - locals_unavailable = 0; - } - } - - if (locals_unavailable) - { - /* If we have an insn for this delay slot, write it. */ - if (current_function_epilogue_delay_list) - final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), - file, 1, -2, 1); - else - fprintf (file, "\tnop\n"); - } - - fprintf (file, "\tjmpi lr0\n"); - if (a29k_regstack_size) - fprintf (file, "\tasleu V_%sFILL,lr1,%s\n", - TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RFB]); - else if (current_function_epilogue_delay_list) - final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), - file, 1, -2, 1); - else - fprintf (file, "\tnop\n"); -} diff --git a/gcc/config/a29k/a29k.h b/gcc/config/a29k/a29k.h deleted file mode 100755 index acff143..0000000 --- a/gcc/config/a29k/a29k.h +++ /dev/null @@ -1,1673 +0,0 @@ -/* Definitions of target machine for GNU compiler, for AMD Am29000 CPU. - Copyright (C) 1988, 90-97, 1998 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@nyu.edu) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -/* Names to predefine in the preprocessor for this target machine. */ - -#define CPP_PREDEFINES "-D_AM29K -D_AM29000 -D_EPI -Acpu(a29k) -Amachine(a29k)" - -/* Print subsidiary information on the compiler version in use. */ -#define TARGET_VERSION - -/* Pass -w to assembler. */ -#define ASM_SPEC "-w" - -/* Run-time compilation parameters selecting different hardware subsets. */ - -extern int target_flags; - -/* Macro to define tables used to set the flags. - This is a list in braces of pairs in braces, - each pair being { "NAME", VALUE } - where VALUE is the bits to set or minus the bits to clear. - An empty string NAME is used to identify the default VALUE. */ - -/* This means that the DW bit will be enabled, to allow direct loads - of bytes. */ - -#define TARGET_DW_ENABLE (target_flags & 1) - -/* This means that the external hardware does supports byte writes. */ - -#define TARGET_BYTE_WRITES (target_flags & 2) - -/* This means that a "small memory model" has been selected where all - function addresses are known to be within 256K. This allows CALL to be - used. */ - -#define TARGET_SMALL_MEMORY (target_flags & 4) - -/* This means that we must always used on indirect call, even when - calling a function in the same file, since the file might be > 256KB. */ - -#define TARGET_LARGE_MEMORY (target_flags & 8) - -/* This means that we are compiling for a 29050. */ - -#define TARGET_29050 (target_flags & 16) - -/* This means that we are compiling for the kernel which means that we use - gr64-gr95 instead of gr96-126. */ - -#define TARGET_KERNEL_REGISTERS (target_flags & 32) - -/* This means that a call to "__msp_check" should be inserted after each stack - adjustment to check for stack overflow. */ - -#define TARGET_STACK_CHECK (target_flags & 64) - -/* This handles 29k processors which cannot handle the separation - of a mtsrim insns and a storem insn (most 29000 chips to date, but - not the 29050. */ - -#define TARGET_NO_STOREM_BUG (target_flags & 128) - -/* This forces the compiler not to use incoming argument registers except - for copying out arguments. It helps detect problems when a function is - called with fewer arguments than it is declared with. */ - -#define TARGET_NO_REUSE_ARGS (target_flags & 256) - -/* This means that neither builtin nor emulated float operations are - available, and that GCC should generate libcalls instead. */ - -#define TARGET_SOFT_FLOAT (target_flags & 512) - -/* This means that we should not emit the multm or mutmu instructions - that some embedded systems' trap handlers don't support. */ - -#define TARGET_MULTM ((target_flags & 1024) == 0) - -#define TARGET_SWITCHES \ - { {"dw", 1}, \ - {"ndw", -1}, \ - {"bw", 2}, \ - {"nbw", - (1|2)}, \ - {"small", 4}, \ - {"normal", - (4|8)}, \ - {"large", 8}, \ - {"29050", 16+128}, \ - {"29000", -16}, \ - {"kernel-registers", 32}, \ - {"user-registers", -32}, \ - {"stack-check", 64}, \ - {"no-stack-check", - 74}, \ - {"storem-bug", -128}, \ - {"no-storem-bug", 128}, \ - {"reuse-arg-regs", -256}, \ - {"no-reuse-arg-regs", 256}, \ - {"soft-float", 512}, \ - {"no-multm", 1024}, \ - {"", TARGET_DEFAULT}} - -/* CYGNUS LOCAL: reuse-arg-regs bug, see PR 8144 */ -#define TARGET_DEFAULT (3 + 256) - -/* Show we can debug even without a frame pointer. */ -#define CAN_DEBUG_WITHOUT_FP - -/* target machine storage layout */ - -/* Define the types for size_t, ptrdiff_t, and wchar_t. These are the - same as those used by EPI. The type for wchar_t does not make much - sense, but is what is used. */ - -#define SIZE_TYPE "unsigned int" -#define PTRDIFF_TYPE "int" -#define WCHAR_TYPE "char" -#define WCHAR_TYPE_SIZE BITS_PER_UNIT - -/* 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) < 4) \ - (MODE) = SImode; - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. - This is arbitrary on the 29k since it has no actual bit-field insns. - It is better to define this as TRUE because BYTES_BIG_ENDIAN is TRUE - and we want to be able to convert BP position to bit position with - just a shift. */ -#define BITS_BIG_ENDIAN 1 - -/* Define this if most significant byte of a word is the lowest numbered. - This is true on 29k. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this if most significant word of a multiword number is lowest - numbered. - - For 29k we can decide arbitrarily since there are no machine instructions - for them. Might as well be consistent with bytes. */ -#define WORDS_BIG_ENDIAN 1 - -/* number of bits in an addressable storage unit */ -#define BITS_PER_UNIT 8 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; - if using 16-bit ints on a 68000, this would still be 32. - But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 32 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 4 - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 32 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 64 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 32 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 32 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* A bitfield declared as `int' forces `int' alignment for the struct. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 32 - -/* Make strings word-aligned so strcpy from constants will be faster. */ -#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ - (TREE_CODE (EXP) == STRING_CST \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -/* Make arrays of chars word-aligned for the same reasons. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -/* Set this non-zero if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 0 - -/* Set this non-zero if unaligned move instructions are extremely slow. - - On the 29k, they trap. */ -#define SLOW_UNALIGNED_ACCESS 1 - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. - - 29k has 256 registers, of which 62 are not defined. gr0 and gr1 are - not produced in generated RTL so we can start at gr96, and call it - register zero. - - So 0-31 are gr96-gr127, lr0-lr127 are 32-159. To represent the input - arguments, whose register numbers we won't know until we are done, - use register 160-175. They cannot be modified. Similarly, 176 is used - for the frame pointer. It is assigned the last local register number - once the number of registers used is known. - - We use 177, 178, 179, and 180 for the special registers BP, FC, CR, and Q, - respectively. Registers 181 through 199 are used for the other special - registers that may be used by the programmer, but are never used by the - compiler. - - Registers 200-203 are the four floating-point accumulator register in - the 29050. - - Registers 204-235 are the 32 global registers for kernel mode when - -mkernel-registers is not specified, and the 32 global user registers - when it is. - - When -mkernel-registers is specified, we still use the same register - map but change the names so 0-31 print as gr64-gr95. */ - -#define FIRST_PSEUDO_REGISTER 236 - -/* Because of the large number of registers on the 29k, we define macros - to refer to each group of registers and then define the number for some - registers used in the calling sequence. */ - -#define R_GR(N) ((N) - 96) /* gr96 is register number 0 */ -#define R_LR(N) ((N) + 32) /* lr0 is register number 32 */ -#define R_FP 176 /* frame pointer is register 176 */ -#define R_AR(N) ((N) + 160) /* first incoming arg reg is 160 */ -#define R_KR(N) ((N) + 204) /* kernel registers (gr64 to gr95) */ - -/* Define the numbers of the special registers. */ -#define R_BP 177 -#define R_FC 178 -#define R_CR 179 -#define R_Q 180 - -/* These special registers are not used by the compiler, but may be referenced - by the programmer via asm declarations. */ - -#define R_VAB 181 -#define R_OPS 182 -#define R_CPS 183 -#define R_CFG 184 -#define R_CHA 185 -#define R_CHD 186 -#define R_CHC 187 -#define R_RBP 188 -#define R_TMC 189 -#define R_TMR 190 -#define R_PC0 191 -#define R_PC1 192 -#define R_PC2 193 -#define R_MMU 194 -#define R_LRU 195 -#define R_FPE 196 -#define R_INT 197 -#define R_FPS 198 -#define R_EXO 199 - -/* Define the number for floating-point accumulator N. */ -#define R_ACU(N) ((N) + 200) - -/* Now define the registers used in the calling sequence. */ -#define R_TAV R_GR (121) -#define R_TPC R_GR (122) -#define R_LRP R_GR (123) -#define R_SLP R_GR (124) -#define R_MSP R_GR (125) -#define R_RAB R_GR (126) -#define R_RFB R_GR (127) - -/* 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, 0, 0, 0, \ - 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, \ - 0, 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, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 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 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. */ -#define CALL_USED_REGISTERS \ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ - 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, 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, 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, \ - 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 } - -/* List the order in which to allocate registers. Each register must be - listed once, even those in FIXED_REGISTERS. - - We allocate in the following order: - gr116-gr120 (not used for anything but temps) - gr96-gr111 (function return values, reverse order) - argument registers (160-175) - lr0-lr127 (locals, saved) - acc3-0 (acc0 special) - everything else */ - -#define REG_ALLOC_ORDER \ - {R_GR (116), R_GR (117), R_GR (118), R_GR (119), R_GR (120), \ - R_GR (111), R_GR (110), R_GR (109), R_GR (108), R_GR (107), \ - R_GR (106), R_GR (105), R_GR (104), R_GR (103), R_GR (102), \ - R_GR (101), R_GR (100), R_GR (99), R_GR (98), R_GR (97), R_GR (96), \ - R_AR (0), R_AR (1), R_AR (2), R_AR (3), R_AR (4), R_AR (5), \ - R_AR (6), R_AR (7), R_AR (8), R_AR (9), R_AR (10), R_AR (11), \ - R_AR (12), R_AR (13), R_AR (14), R_AR (15), \ - R_LR (0), R_LR (1), R_LR (2), R_LR (3), R_LR (4), R_LR (5), \ - R_LR (6), R_LR (7), R_LR (8), R_LR (9), R_LR (10), R_LR (11), \ - R_LR (12), R_LR (13), R_LR (14), R_LR (15), R_LR (16), R_LR (17), \ - R_LR (18), R_LR (19), R_LR (20), R_LR (21), R_LR (22), R_LR (23), \ - R_LR (24), R_LR (25), R_LR (26), R_LR (27), R_LR (28), R_LR (29), \ - R_LR (30), R_LR (31), R_LR (32), R_LR (33), R_LR (34), R_LR (35), \ - R_LR (36), R_LR (37), R_LR (38), R_LR (39), R_LR (40), R_LR (41), \ - R_LR (42), R_LR (43), R_LR (44), R_LR (45), R_LR (46), R_LR (47), \ - R_LR (48), R_LR (49), R_LR (50), R_LR (51), R_LR (52), R_LR (53), \ - R_LR (54), R_LR (55), R_LR (56), R_LR (57), R_LR (58), R_LR (59), \ - R_LR (60), R_LR (61), R_LR (62), R_LR (63), R_LR (64), R_LR (65), \ - R_LR (66), R_LR (67), R_LR (68), R_LR (69), R_LR (70), R_LR (71), \ - R_LR (72), R_LR (73), R_LR (74), R_LR (75), R_LR (76), R_LR (77), \ - R_LR (78), R_LR (79), R_LR (80), R_LR (81), R_LR (82), R_LR (83), \ - R_LR (84), R_LR (85), R_LR (86), R_LR (87), R_LR (88), R_LR (89), \ - R_LR (90), R_LR (91), R_LR (92), R_LR (93), R_LR (94), R_LR (95), \ - R_LR (96), R_LR (97), R_LR (98), R_LR (99), R_LR (100), R_LR (101), \ - R_LR (102), R_LR (103), R_LR (104), R_LR (105), R_LR (106), \ - R_LR (107), R_LR (108), R_LR (109), R_LR (110), R_LR (111), \ - R_LR (112), R_LR (113), R_LR (114), R_LR (115), R_LR (116), \ - R_LR (117), R_LR (118), R_LR (119), R_LR (120), R_LR (121), \ - R_LR (122), R_LR (123), R_LR (124), R_LR (124), R_LR (126), \ - R_LR (127), \ - R_ACU (3), R_ACU (2), R_ACU (1), R_ACU (0), \ - R_GR (112), R_GR (113), R_GR (114), R_GR (115), R_GR (121), \ - R_GR (122), R_GR (123), R_GR (124), R_GR (125), R_GR (126), \ - R_GR (127), \ - R_FP, R_BP, R_FC, R_CR, R_Q, \ - R_VAB, R_OPS, R_CPS, R_CFG, R_CHA, R_CHD, R_CHC, R_RBP, R_TMC, \ - R_TMR, R_PC0, R_PC1, R_PC2, R_MMU, R_LRU, R_FPE, R_INT, R_FPS, \ - R_EXO, \ - R_KR (0), R_KR (1), R_KR (2), R_KR (3), R_KR (4), R_KR (5), \ - R_KR (6), R_KR (7), R_KR (8), R_KR (9), R_KR (10), R_KR (11), \ - R_KR (12), R_KR (13), R_KR (14), R_KR (15), R_KR (16), R_KR (17), \ - R_KR (18), R_KR (19), R_KR (20), R_KR (21), R_KR (22), R_KR (23), \ - R_KR (24), R_KR (25), R_KR (26), R_KR (27), R_KR (28), R_KR (29), \ - R_KR (30), R_KR (31) } - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((REGNO) >= R_ACU (0) && (REGNO) <= R_ACU (3)? 1 \ - : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - On 29k, the cpu registers can hold any mode. But a double-precision - floating-point value should start at an even register. The special - registers cannot hold floating-point values, BP, CR, and FC cannot - hold integer or floating-point values, and the accumulators cannot - hold integer values. - - DImode and larger values should start at an even register just like - DFmode values, even though the instruction set doesn't require it, in order - to prevent reload from aborting due to a modes_equiv_for_class_p failure. - - (I'd like to use the "?:" syntax to make this more readable, but Sun's - compiler doesn't seem to accept it.) */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) \ -(((REGNO) >= R_ACU (0) && (REGNO) <= R_ACU (3) \ - && (GET_MODE_CLASS (MODE) == MODE_FLOAT \ - || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)) \ - || ((REGNO) >= R_BP && (REGNO) <= R_CR \ - && GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT) \ - || ((REGNO) >= R_Q && (REGNO) < R_ACU (0) \ - && GET_MODE_CLASS (MODE) != MODE_FLOAT \ - && GET_MODE_CLASS (MODE) != MODE_COMPLEX_FLOAT) \ - || (((REGNO) < R_BP || (REGNO) >= R_KR (0)) \ - && ((((REGNO) & 1) == 0) \ - || GET_MODE_UNIT_SIZE (MODE) <= UNITS_PER_WORD))) - -/* 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. - - On the 29k, normally we'd just have problems with DFmode because of the - even alignment. However, we also have to be a bit concerned about - the special register's restriction to non-floating and the floating-point - accumulator's restriction to only floating. This probably won't - cause any great inefficiencies in practice. */ - -#define MODES_TIEABLE_P(MODE1, MODE2) \ - ((MODE1) == (MODE2) \ - || (GET_MODE_CLASS (MODE1) == MODE_INT \ - && GET_MODE_CLASS (MODE2) == MODE_INT)) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* 29k 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 R_GR (125) - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM R_FP - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms - may be accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED 0 - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM R_FP - -/* Register in which static-chain is passed to a function. */ -#define STATIC_CHAIN_REGNUM R_SLP - -/* Register in which address to store a structure value - is passed to a function. */ -#define STRUCT_VALUE_REGNUM R_LRP - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. - - The 29k has nine registers classes: LR0_REGS, GENERAL_REGS, SPECIAL_REGS, - BP_REGS, FC_REGS, CR_REGS, Q_REGS, ACCUM_REGS, and ACCUM0_REGS. - LR0_REGS, BP_REGS, FC_REGS, CR_REGS, and Q_REGS contain just the single - register. The latter two classes are used to represent the floating-point - accumulator registers in the 29050. We also define the union class - FLOAT_REGS to represent any register that can be used to hold a - floating-point value. The union of SPECIAL_REGS and ACCUM_REGS isn't - useful as the former cannot contain floating-point and the latter can only - contain floating-point. */ - -enum reg_class { NO_REGS, LR0_REGS, GENERAL_REGS, BP_REGS, FC_REGS, CR_REGS, - Q_REGS, SPECIAL_REGS, ACCUM0_REGS, ACCUM_REGS, FLOAT_REGS, - ALL_REGS, LIM_REG_CLASSES }; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ - {"NO_REGS", "LR0_REGS", "GENERAL_REGS", "BP_REGS", "FC_REGS", "CR_REGS", \ - "Q_REGS", "SPECIAL_REGS", "ACCUM0_REGS", "ACCUM_REGS", "FLOAT_REGS", \ - "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS \ - { {0, 0, 0, 0, 0, 0, 0, 0}, \ - {0, 1, 0, 0, 0, 0, 0, 0}, \ - {~0, ~0, ~0, ~0, ~0, ~ 0xfffe0000, ~ 0xfff, 0xfff}, \ - {0, 0, 0, 0, 0, 0x20000, 0, 0}, \ - {0, 0, 0, 0, 0, 0x40000, 0, 0}, \ - {0, 0, 0, 0, 0, 0x80000, 0, 0}, \ - {0, 0, 0, 0, 0, 0x100000, 0, 0}, \ - {0, 0, 0, 0, 0, 0xfffe0000, 0xff, 0}, \ - {0, 0, 0, 0, 0, 0, 0x100, 0}, \ - {0, 0, 0, 0, 0, 0, 0xf00, 0}, \ - {~0, ~0, ~0, ~0, ~0, ~ 0xfffe0000, ~ 0xff, 0xfff}, \ - {~0, ~0, ~0, ~0, ~0, ~0, ~0, 0xfff} } - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) \ - ((REGNO) == R_BP ? BP_REGS \ - : (REGNO) == R_FC ? FC_REGS \ - : (REGNO) == R_CR ? CR_REGS \ - : (REGNO) == R_Q ? Q_REGS \ - : (REGNO) > R_BP && (REGNO) <= R_EXO ? SPECIAL_REGS \ - : (REGNO) == R_ACU (0) ? ACCUM0_REGS \ - : (REGNO) >= R_KR (0) ? GENERAL_REGS \ - : (REGNO) > R_ACU (0) ? ACCUM_REGS \ - : (REGNO) == R_LR (0) ? LR0_REGS \ - : GENERAL_REGS) - -/* The class value for index registers, and the one for base regs. */ -#define INDEX_REG_CLASS NO_REGS -#define BASE_REG_CLASS GENERAL_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) \ - ((C) == 'r' ? GENERAL_REGS \ - : (C) == 'l' ? LR0_REGS \ - : (C) == 'b' ? BP_REGS \ - : (C) == 'f' ? FC_REGS \ - : (C) == 'c' ? CR_REGS \ - : (C) == 'q' ? Q_REGS \ - : (C) == 'h' ? SPECIAL_REGS \ - : (C) == 'a' ? ACCUM_REGS \ - : (C) == 'A' ? ACCUM0_REGS \ - : (C) == 'f' ? FLOAT_REGS \ - : NO_REGS) - -/* Define this macro to change register usage conditional on target flags. - - On the 29k, we use this to change the register names for kernel mapping. */ - -#define CONDITIONAL_REGISTER_USAGE \ - { \ - char *p; \ - int i; \ - \ - if (TARGET_KERNEL_REGISTERS) \ - for (i = 0; i < 32; i++) \ - { \ - p = reg_names[i]; \ - reg_names[i] = reg_names[R_KR (i)]; \ - reg_names[R_KR (i)] = p; \ - } \ - } - -/* The letters I, J, K, L, M, N, O, 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. - - For 29k: - `I' is used for the range of constants most insns can contain. - `J' is for the few 16-bit insns. - `K' is a constant whose high-order 24 bits are all one - `L' is a HImode constant whose high-order 8 bits are all one - `M' is a 32-bit constant whose high-order 16 bits are all one (for CONSTN) - `N' is a 32-bit constant whose negative is 8 bits - `O' is the 32-bit constant 0x80000000, any constant with low-order - 16 bits zero for 29050. - `P' is a HImode constant whose negative is 8 bits */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (unsigned) (VALUE) < 0x100 \ - : (C) == 'J' ? (unsigned) (VALUE) < 0x10000 \ - : (C) == 'K' ? ((VALUE) & 0xffffff00) == 0xffffff00 \ - : (C) == 'L' ? ((VALUE) & 0xff00) == 0xff00 \ - : (C) == 'M' ? ((VALUE) & 0xffff0000) == 0xffff0000 \ - : (C) == 'N' ? ((VALUE) < 0 && (VALUE) > -256) \ - : (C) == 'O' ? ((VALUE) == 0x80000000 \ - || (TARGET_29050 && ((VALUE) & 0xffff) == 0)) \ - : (C) == 'P' ? (((VALUE) | 0xffff0000) < 0 \ - && ((VALUE) | 0xffff0000) > -256) \ - : 0) - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. - All floating-point constants are valid on 29k. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1 - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) 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) - -/* This function is used to get the address of an object. */ - -extern struct rtx_def *a29k_get_reloaded_address (); - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. - - On 29k, this is the size of MODE in words except that the floating-point - accumulators only require one word for anything they can hold. */ - -#define CLASS_MAX_NREGS(CLASS, MODE) \ - (((CLASS) == ACCUM_REGS || (CLASS) == ACCUM0_REGS) ? 1 \ - : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Define the cost of moving between registers of various classes. Everything - involving a general register is cheap, but moving between the other types - (even within a class) is two insns. */ - -#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ - ((CLASS1) == GENERAL_REGS || (CLASS2) == GENERAL_REGS ? 2 : 4) - -/* A C expressions returning the cost of moving data of MODE from a register to - or from memory. - - It takes extra insns on the 29k to form addresses, so we want to make - this higher. In addition, we need to keep it more expensive than the - most expensive register-register copy. */ - -#define MEMORY_MOVE_COST(MODE,CLASS,IN) 6 - -/* A C statement (sans semicolon) to update the integer variable COST - based on the relationship between INSN that is dependent on - DEP_INSN through the dependence LINK. The default is to make no - adjustment to COST. On the a29k, ignore the cost of anti- and - output-dependencies. */ -#define ADJUST_COST(INSN,LINK,DEP_INSN,COST) \ - if (REG_NOTE_KIND (LINK) != 0) \ - (COST) = 0; /* Anti or output dependence. */ - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -#define STACK_GROWS_DOWNWARD - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ - -#define STARTING_FRAME_OFFSET (- current_function_pretend_args_size) - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. - On 29k, don't define this because there are no push insns. */ -/* #define PUSH_ROUNDING(BYTES) */ - -/* Define this if the maximum size of all the outgoing args is to be - accumulated and pushed during the prologue. The amount can be - found in the variable current_function_outgoing_args_size. */ -#define ACCUMULATE_OUTGOING_ARGS - -/* Offset of first parameter from the argument pointer register value. */ - -#define FIRST_PARM_OFFSET(FNDECL) (- current_function_pretend_args_size) - -/* Define this if stack space is still allocated for a parameter passed - in a register. */ -/* #define REG_PARM_STACK_SPACE */ - -/* Value is the number of bytes of arguments automatically - popped when returning from a subroutine call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - SIZE is the number of bytes of arguments passed on the stack. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. - - On 29k the value is found in gr96. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), R_GR (96)) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ - -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, R_GR (96)) - -/* 1 if N is a possible register number for a function value - as seen by the caller. - On 29k, gr96-gr111 are used. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == R_GR (96)) - -/* 1 if N is a possible register number for function argument passing. - On 29k, these are lr2-lr17. */ - -#define FUNCTION_ARG_REGNO_P(N) ((N) <= R_LR (17) && (N) >= R_LR (2)) - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. - - On 29k, this is a single integer, which is a number of words - of arguments scanned so far. - Thus 16 or more means all following args should go on the stack. */ - -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ - -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) (CUM) = 0 - -/* Same, but called for incoming args. - - On the 29k, we use this to set all argument registers to fixed and - set the last 16 local regs, less two, (lr110-lr125) to available. Some - will later be changed to call-saved by FUNCTION_INCOMING_ARG. - lr126,lr127 are always fixed, they are place holders for the caller's - lr0,lr1. */ - -#define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,IGNORE) \ -{ int i; \ - for (i = R_AR (0) - 2; i < R_AR (16); i++) \ - { \ - fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1; \ - SET_HARD_REG_BIT (fixed_reg_set, i); \ - SET_HARD_REG_BIT (call_used_reg_set, i); \ - SET_HARD_REG_BIT (call_fixed_reg_set, i); \ - } \ - for (i = R_LR (110); i < R_LR (126); i++) \ - { \ - fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 0; \ - CLEAR_HARD_REG_BIT (fixed_reg_set, i); \ - CLEAR_HARD_REG_BIT (call_used_reg_set, i); \ - CLEAR_HARD_REG_BIT (call_fixed_reg_set, i); \ - } \ - (CUM) = 0; \ - } - -/* Define intermediate macro to compute the size (in registers) of an argument - for the 29k. */ - -#define A29K_ARG_SIZE(MODE, TYPE, NAMED) \ -(! (NAMED) ? 0 \ - : (MODE) != BLKmode \ - ? (GET_MODE_SIZE (MODE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD \ - : (int_size_in_bytes (TYPE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD) - -/* 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) \ - if (MUST_PASS_IN_STACK (MODE, TYPE)) \ - (CUM) = 16; \ - else \ - (CUM) += A29K_ARG_SIZE (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). - - On 29k the first 16 words of args are normally in registers - and the rest are pushed. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ -((CUM) < 16 && (NAMED) && ! MUST_PASS_IN_STACK (MODE, TYPE) \ - ? gen_rtx(REG, (MODE), R_LR (2) + (CUM)) : 0) - -/* Define where a function finds its arguments. - This is different from FUNCTION_ARG because of register windows. - - On the 29k, we hack this to call a function that sets the used registers - as non-fixed and not used by calls. */ - -#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ -((CUM) < 16 && (NAMED) && ! MUST_PASS_IN_STACK (MODE, TYPE) \ - ? gen_rtx (REG, MODE, \ - incoming_reg (CUM, A29K_ARG_SIZE (MODE, TYPE, NAMED))) \ - : 0) - -/* This indicates that an argument is to be passed with an invisible reference - (i.e., a pointer to the object is passed). - - On the 29k, we do this if it must be passed on the stack. */ - -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - (MUST_PASS_IN_STACK (MODE, TYPE)) - -/* Specify the padding direction of arguments. - - On the 29k, we must pad upwards in order to be able to pass args in - registers. */ - -#define FUNCTION_ARG_PADDING(MODE, TYPE) upward - -/* 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) \ -((CUM) < 16 && 16 < (CUM) + A29K_ARG_SIZE (MODE, TYPE, NAMED) && (NAMED) \ - ? 16 - (CUM) : 0) - -/* Perform any needed actions needed for a function that is receiving a - variable number of arguments. - - CUM is as above. - - MODE and TYPE are the mode and type of the current parameter. - - PRETEND_SIZE is a variable that should be set to the amount of stack - that must be pushed by the prolog to pretend that our caller pushed - it. - - Normally, this macro will push all remaining incoming registers on the - stack and set PRETEND_SIZE to the length of the registers pushed. */ - -#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \ -{ if ((CUM) < 16) \ - { \ - int first_reg_offset = (CUM); \ - \ - if (MUST_PASS_IN_STACK (MODE, TYPE)) \ - first_reg_offset += A29K_ARG_SIZE (TYPE_MODE (TYPE), TYPE, 1); \ - \ - if (first_reg_offset > 16) \ - first_reg_offset = 16; \ - \ - if (! (NO_RTL) && first_reg_offset != 16) \ - move_block_from_reg \ - (R_AR (0) + first_reg_offset, \ - gen_rtx (MEM, BLKmode, virtual_incoming_args_rtx), \ - 16 - first_reg_offset, (16 - first_reg_offset) * UNITS_PER_WORD); \ - PRETEND_SIZE = (16 - first_reg_offset) * UNITS_PER_WORD; \ - } \ -} - -/* 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 *a29k_compare_op0, *a29k_compare_op1; -extern int a29k_compare_fp_p; - -/* This macro produces the initial definition of a function name. - - For the 29k, we need the prolog to contain one or two words prior to - the declaration of the function name. So just store away the name and - write it as part of the prolog. This also computes the register names, - which can't be done until after register allocation, but must be done - before final_start_function is called. */ - -extern char *a29k_function_name; - -#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ - a29k_function_name = NAME; \ - a29k_compute_reg_names (); - -/* This macro generates the assembly code for function entry. - FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - 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. */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. */ - -#define EXIT_IGNORE_STACK 1 - -/* This macro generates the assembly code for function exit, - on machines that need it. If FUNCTION_EPILOGUE is not defined - then individual return instructions are generated for each - return statement. Args are same as for FUNCTION_PROLOGUE. - - The function epilogue should not depend on the current stack pointer! - It should use the frame pointer only. This is mandatory because - of alloca; we also take advantage of it to omit stack adjustments - before returning. */ - -#define FUNCTION_EPILOGUE(FILE, SIZE) output_epilog (FILE, SIZE) - -/* Define the number of delay slots needed for the function epilogue. - - On the 29k, we need a slot except when we have a register stack adjustment, - have a memory stack adjustment, and have no frame pointer. */ - -#define DELAY_SLOTS_FOR_EPILOGUE \ - (! (needs_regstack_p () \ - && (get_frame_size () + current_function_pretend_args_size \ - + current_function_outgoing_args_size) != 0 \ - && ! frame_pointer_needed)) - -/* Define whether INSN can be placed in delay slot N for the epilogue. - - On the 29k, we must be able to place it in a delay slot, it must - not use sp if the frame pointer cannot be eliminated, and it cannot - use local regs if we need to push the register stack. - If this is a SET with a memory as source, it might load from - a stack slot, unless the address is constant. */ - -#define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN,N) \ - (get_attr_in_delay_slot (INSN) == IN_DELAY_SLOT_YES \ - && ! (frame_pointer_needed \ - && reg_mentioned_p (stack_pointer_rtx, PATTERN (INSN))) \ - && ! (needs_regstack_p () && uses_local_reg_p (PATTERN (INSN))) \ - && (GET_CODE (PATTERN (INSN)) != SET \ - || GET_CODE (SET_SRC (PATTERN (INSN))) != MEM \ - || ! rtx_varies_p (XEXP (SET_SRC (PATTERN (INSN)), 0)))) - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. - - The trampoline should set the static chain pointer to value placed - into the trampoline and should branch to the specified routine. We - use gr121 (tav) as a temporary. */ - -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - fprintf (FILE, "\tconst %s,0\n", reg_names[R_TAV]); \ - fprintf (FILE, "\tconsth %s,0\n", reg_names[R_TAV]); \ - fprintf (FILE, "\tconst %s,0\n", reg_names[R_SLP]); \ - fprintf (FILE, "\tjmpi %s\n", reg_names[R_TAV]); \ - fprintf (FILE, "\tconsth %s,0\n", reg_names[R_SLP]); \ -} - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 20 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. - - We do this on the 29k by writing the bytes of the addresses into the - trampoline one byte at a time. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - INITIALIZE_TRAMPOLINE_VALUE (TRAMP, FNADDR, 0, 4); \ - INITIALIZE_TRAMPOLINE_VALUE (TRAMP, CXT, 8, 16); \ -} - -/* Define a sub-macro to initialize one value into the trampoline. - We specify the offsets of the CONST and CONSTH instructions, respectively - and copy the value a byte at a time into these instructions. */ - -#define INITIALIZE_TRAMPOLINE_VALUE(TRAMP, VALUE, CONST, CONSTH) \ -{ \ - rtx _addr, _temp; \ - rtx _val = force_reg (SImode, VALUE); \ - \ - _addr = memory_address (QImode, plus_constant (TRAMP, (CONST) + 3)); \ - emit_move_insn (gen_rtx (MEM, QImode, _addr), \ - gen_lowpart (QImode, _val)); \ - \ - _temp = expand_shift (RSHIFT_EXPR, SImode, _val, \ - build_int_2 (8, 0), 0, 1); \ - _addr = memory_address (QImode, plus_constant (TRAMP, (CONST) + 1)); \ - emit_move_insn (gen_rtx (MEM, QImode, _addr), \ - gen_lowpart (QImode, _temp)); \ - \ - _temp = expand_shift (RSHIFT_EXPR, SImode, _temp, \ - build_int_2 (8, 0), _temp, 1); \ - _addr = memory_address (QImode, plus_constant (TRAMP, (CONSTH) + 3)); \ - emit_move_insn (gen_rtx (MEM, QImode, _addr), \ - gen_lowpart (QImode, _temp)); \ - \ - _temp = expand_shift (RSHIFT_EXPR, SImode, _temp, \ - build_int_2 (8, 0), _temp, 1); \ - _addr = memory_address (QImode, plus_constant (TRAMP, (CONSTH) + 1)); \ - emit_move_insn (gen_rtx (MEM, QImode, _addr), \ - gen_lowpart (QImode, _temp)); \ -} - -/* Addressing modes, and classification of registers for them. */ - -/* #define HAVE_POST_INCREMENT 0 */ -/* #define HAVE_POST_DECREMENT 0 */ - -/* #define HAVE_PRE_DECREMENT 0 */ -/* #define HAVE_PRE_INCREMENT 0 */ - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_INDEX_P(REGNO) 0 -#define REGNO_OK_FOR_BASE_P(REGNO) 1 - -/* Given the value returned from get_frame_size, compute the actual size - of the frame we will allocate. We include the pretend and outgoing - arg sizes and round to a doubleword. */ - -#define ACTUAL_FRAME_SIZE(SIZE) \ - (((SIZE) + current_function_pretend_args_size \ - + current_function_outgoing_args_size + 7) & ~7) - -/* Define the initial offset between the frame and stack pointer. */ - -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ - (DEPTH) = ACTUAL_FRAME_SIZE (get_frame_size ()) - -/* Maximum number of registers that can appear in a valid memory address. */ -#define MAX_REGS_PER_ADDRESS 1 - -/* Recognize any constant value that is a valid address. */ - -#define CONSTANT_ADDRESS_P(X) \ -(GET_CODE (X) == CONST_INT && (unsigned) INTVAL (X) < 0x100) - -/* Include all constant integers and constant doubles */ -#define LEGITIMATE_CONSTANT_P(X) 1 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) 0 -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) 1 - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - On the 29k, a legitimate address is a register and so is a - constant of less than 256. */ - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ if (REG_P (X) && REG_OK_FOR_BASE_P (X)) \ - goto ADDR; \ - if (GET_CODE (X) == CONST_INT \ - && (unsigned) INTVAL (X) < 0x100) \ - goto ADDR; \ -} - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. - - For the 29k, we need not do anything. However, if we don't, - `memory_address' will try lots of things to get a valid address, most of - which will result in dead code and extra pseudos. So we make the address - valid here. - - This is easy: The only valid addresses are an offset from a register - and we know the address isn't valid. So just call either `force_operand' - or `force_reg' unless this is a (plus (reg ...) (const_int 0)). */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -{ if (GET_CODE (X) == PLUS && XEXP (X, 1) == const0_rtx) \ - X = XEXP (x, 0); \ - if (GET_CODE (X) == MULT || GET_CODE (X) == PLUS) \ - X = force_operand (X, 0); \ - else \ - X = force_reg (Pmode, X); \ - goto WIN; \ -} - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. - On the 29k this is never true. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) - -/* Compute the cost of an address. For the 29k, all valid addresses are - the same cost. */ - -#define ADDRESS_COST(X) 0 - -/* Define this if some processing needs to be done immediately before - emitting code for an insn. */ - -/* #define FINAL_PRESCAN_INSN(INSN,OPERANDS,NOPERANDS) */ - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE 1 */ - -/* Specify the tree operation to be used to convert reals to integers. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* This is the kind of divide that is easiest to do in the general case. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 0 - -/* This flag, if defined, says the same insns that convert to a signed fixnum - also convert validly to an unsigned one. - - We actually lie a bit here as overflow conditions are different. But - they aren't being checked anyway. */ - -#define FIXUNS_TRUNC_LIKE_FIX_TRUNC - -/* Max number of bytes we can move to of from memory - in one reasonably fast instruction. - - For the 29k, we will define movti, so put this at 4 words. */ -#define MOVE_MAX 16 - -/* Largest number of bytes of an object that can be placed in a register. - On the 29k we have plenty of registers, so use TImode. */ -#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TImode) - -/* Nonzero if access to memory by bytes is no faster than for words. - Also non-zero if doing byte operations (specifically shifts) in registers - is undesirable. - - On the 29k, large masks are expensive, so we want to use bytes to - manipulate fields. */ -#define SLOW_BYTE_ACCESS 0 - -/* Define if operations between registers always perform the operation - on the full register even if a narrower mode is specified. */ -#define WORD_REGISTER_OPERATIONS - -/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD - will either zero-extend or sign-extend. The value of this macro should - be the code that says which one of the two operations is implicitly - done, NIL if none. */ -#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND - -/* Define if the object format being used is COFF or a superset. */ -#define OBJECT_FORMAT_COFF - -/* This uses COFF, so it wants SDB format. */ -#define SDB_DEBUGGING_INFO - -/* Define this to be the delimiter between SDB sub-sections. The default - is ";". */ -#define SDB_DELIM "\n" - -/* Do not break .stabs pseudos into continuations. */ -#define DBX_CONTIN_LENGTH 0 - -/* Don't try to use the `x' type-cross-reference character in DBX data. - Also has the consequence of putting each struct, union or enum - into a separate .stabs, containing only cross-refs to the others. */ -#define DBX_NO_XREFS - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* We assume that the store-condition-codes instructions store 0 for false - and some other value for true. This is the value stored for true, which - is just the sign bit. */ - -#define STORE_FLAG_VALUE (-2147483647 - 1) - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -#define Pmode SImode - -/* Mode of a function address in a call instruction (for indexing purposes). - - Doesn't matter on 29k. */ -#define FUNCTION_MODE SImode - -/* Define this if addresses of constant functions - shouldn't be put through pseudo regs where they can be cse'd. - Desirable on machines where ordinary constants are expensive - but a CALL with constant address is cheap. */ -#define NO_FUNCTION_CSE - -/* Define this to be nonzero if shift instructions ignore all but the low-order - few bits. */ -#define SHIFT_COUNT_TRUNCATED 1 - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. - - We only care about the cost if it is valid in an insn. The only - constants that cause an insn to generate more than one machine - instruction are those involving floating-point or address. So - only these need be expensive. */ - -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - return 0; \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - return 6; \ - case CONST_DOUBLE: \ - return GET_MODE (RTX) == SFmode ? 6 : 8; - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. - - All MEMs cost the same if they are valid. This is used to ensure - that (mem (symbol_ref ...)) is placed into a CALL when valid. - - The multiply cost depends on whether this is a 29050 or not. */ - -#define RTX_COSTS(X,CODE,OUTER_CODE) \ - case MULT: \ - return TARGET_29050 ? COSTS_N_INSNS (2) : COSTS_N_INSNS (40); \ - case DIV: \ - case UDIV: \ - case MOD: \ - case UMOD: \ - return COSTS_N_INSNS (50); \ - case MEM: \ - return COSTS_N_INSNS (2); - -/* Control the assembler format that we output. */ - -/* Output at beginning of assembler file. */ - -#define ASM_FILE_START(FILE) \ -{ char *p, *after_dir = main_input_filename; \ - if (TARGET_29050) \ - fprintf (FILE, "\t.cputype 29050\n"); \ - for (p = main_input_filename; *p; p++) \ - if (*p == '/') \ - after_dir = p + 1; \ - fprintf (FILE, "\t.file "); \ - output_quoted_string (FILE, after_dir); \ - fprintf (FILE, "\n"); \ - fprintf (FILE, "\t.sect .lit,lit\n"); } - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF "" - -/* The next few macros don't have tabs on most machines, but - at least one 29K assembler wants them. */ - -/* Output before instructions. */ - -#define TEXT_SECTION_ASM_OP "\t.text" - -/* Output before read-only data. */ - -#define READONLY_DATA_SECTION_ASM_OP "\t.use .lit" - -/* Output before writable data. */ - -#define DATA_SECTION_ASM_OP "\t.data" - -/* Define an extra section for read-only data, a routine to enter it, and - indicate that it is for read-only data. */ - -#define EXTRA_SECTIONS readonly_data - -#define EXTRA_SECTION_FUNCTIONS \ -void \ -literal_section () \ -{ \ - if (in_section != readonly_data) \ - { \ - fprintf (asm_out_file, "%s\n", READONLY_DATA_SECTION_ASM_OP); \ - in_section = readonly_data; \ - } \ -} \ - -#define READONLY_DATA_SECTION literal_section - -/* If we are referencing a function that is static or is known to be - in this file, make the SYMBOL_REF special. We can use this to indicate - that we can branch to this function without emitting a no-op after the - call. */ - -#define ENCODE_SECTION_INFO(DECL) \ - if (TREE_CODE (DECL) == FUNCTION_DECL \ - && (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL))) \ - SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{"gr96", "gr97", "gr98", "gr99", "gr100", "gr101", "gr102", "gr103", "gr104", \ - "gr105", "gr106", "gr107", "gr108", "gr109", "gr110", "gr111", "gr112", \ - "gr113", "gr114", "gr115", "gr116", "gr117", "gr118", "gr119", "gr120", \ - "gr121", "gr122", "gr123", "gr124", "gr125", "gr126", "gr127", \ - "lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", "lr8", "lr9", \ - "lr10", "lr11", "lr12", "lr13", "lr14", "lr15", "lr16", "lr17", "lr18", \ - "lr19", "lr20", "lr21", "lr22", "lr23", "lr24", "lr25", "lr26", "lr27", \ - "lr28", "lr29", "lr30", "lr31", "lr32", "lr33", "lr34", "lr35", "lr36", \ - "lr37", "lr38", "lr39", "lr40", "lr41", "lr42", "lr43", "lr44", "lr45", \ - "lr46", "lr47", "lr48", "lr49", "lr50", "lr51", "lr52", "lr53", "lr54", \ - "lr55", "lr56", "lr57", "lr58", "lr59", "lr60", "lr61", "lr62", "lr63", \ - "lr64", "lr65", "lr66", "lr67", "lr68", "lr69", "lr70", "lr71", "lr72", \ - "lr73", "lr74", "lr75", "lr76", "lr77", "lr78", "lr79", "lr80", "lr81", \ - "lr82", "lr83", "lr84", "lr85", "lr86", "lr87", "lr88", "lr89", "lr90", \ - "lr91", "lr92", "lr93", "lr94", "lr95", "lr96", "lr97", "lr98", "lr99", \ - "lr100", "lr101", "lr102", "lr103", "lr104", "lr105", "lr106", "lr107", \ - "lr108", "lr109", "lr110", "lr111", "lr112", "lr113", "lr114", "lr115", \ - "lr116", "lr117", "lr118", "lr119", "lr120", "lr121", "lr122", "lr123", \ - "lr124", "lr125", "lr126", "lr127", \ - "AI0", "AI1", "AI2", "AI3", "AI4", "AI5", "AI6", "AI7", "AI8", "AI9", \ - "AI10", "AI11", "AI12", "AI13", "AI14", "AI15", "FP", \ - "bp", "fc", "cr", "q", \ - "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr", \ - "pc0", "pc1", "pc2", "mmu", "lru", "fpe", "int", "fps", "exo", \ - "0", "1", "2", "3", \ - "gr64", "gr65", "gr66", "gr67", "gr68", "gr69", "gr70", "gr71", \ - "gr72", "gr73", "gr74", "gr75", "gr76", "gr77", "gr78", "gr79", \ - "gr80", "gr81", "gr82", "gr83", "gr84", "gr85", "gr86", "gr87", \ - "gr88", "gr89", "gr90", "gr91", "gr92", "gr93", "gr94", "gr95" } - -/* How to renumber registers for dbx and gdb. */ - -extern int a29k_debug_reg_map[]; -#define DBX_REGISTER_NUMBER(REGNO) a29k_debug_reg_map[REGNO] - -/* This how to write an assembler directive to FILE to switch to - section NAME for DECL. */ - -#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ - fprintf (FILE, "\t.sect %s, bss\n\t.use %s\n", NAME, NAME) - -/* This is how to output the definition of a user-level label named NAME, - such as the label on a static function or variable NAME. */ - -#define ASM_OUTPUT_LABEL(FILE,NAME) \ - do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) - -/* This is how to output a command to make the user-level label named NAME - defined for reference from other files. */ - -#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ - do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) - -/* The prefix to add to user-visible assembler symbols. */ - -#undef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "_" - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ - -#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - fprintf (FILE, "%s%d:\n", PREFIX, NUM) - -/* This is how to output a label for a jump table. Arguments are the same as - for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is - passed. */ - -#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \ -{ ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, 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. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*%s%d", PREFIX, NUM) - -/* This is how to output an assembler line defining a `double' constant. */ - -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ - fprintf (FILE, "\t.double %.20e\n", (VALUE)) - -/* This is how to output an assembler line defining a `float' constant. */ - -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ - fprintf (FILE, "\t.float %.20e\n", (VALUE)) - -/* This is how to output an assembler line defining an `int' constant. */ - -#define ASM_OUTPUT_INT(FILE,VALUE) \ -( fprintf (FILE, "\t.word "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* Likewise for `char' and `short' constants. */ - -#define ASM_OUTPUT_SHORT(FILE,VALUE) \ -( fprintf (FILE, "\t.hword "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ -( fprintf (FILE, "\t.byte "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tsub %s,%s,4\n\tstore 0,0,%s,%s\n", \ - reg_names[R_MSP], reg_names[R_MSP], reg_names[REGNO], \ - reg_names[R_MSP]); - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tload 0,0,%s,%s\n\tadd %s,%s,4\n", \ - reg_names[REGNO], reg_names[R_MSP], reg_names[R_MSP], \ - reg_names[R_MSP]); - -/* This is how to output an assembler line for a numeric constant byte. */ - -#define ASM_OUTPUT_BYTE(FILE,VALUE) \ - fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) - -/* This is how to output an element of a case-vector that is absolute. */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.word L%d\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. - Don't define this if it is not supported. */ - -/* #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) */ - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - if ((LOG) != 0) \ - fprintf (FILE, "\t.align %d\n", 1 << (LOG)) - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t.block %d\n", (SIZE)) - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs ("\t.comm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d\n", (SIZE))) - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE,ROUNDED) \ -( fputs ("\t.lcomm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d\n", (SIZE))) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) - -/* Define the parentheses used to group arithmetic operations - in assembler code. */ - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* Define results of standard character escape sequences. */ -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. */ - -#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE) - -/* Determine which codes are valid without a following integer. These must - not be alphabetic. - - We support `#' which is null if a delay slot exists, otherwise - "\n\tnop" and `*' which prints the register name for TPC (gr122). */ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '#' || (CODE) == '*') - -/* Print a memory address as an operand to reference that memory location. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ -{ register rtx addr = ADDR; \ - if (!REG_P (addr) \ - && ! (GET_CODE (addr) == CONST_INT \ - && INTVAL (addr) >= 0 && INTVAL (addr) < 256)) \ - abort (); \ - output_operand (addr, 0); \ -} -/* Define the codes that are matched by predicates in a29k.c. */ - -#define PREDICATE_CODES \ - {"cint_8_operand", {CONST_INT}}, \ - {"cint_16_operand", {CONST_INT}}, \ - {"long_const_operand", {CONST_INT, CONST, CONST_DOUBLE, \ - LABEL_REF, SYMBOL_REF}}, \ - {"shift_constant_operand", {CONST_INT, ASHIFT}}, \ - {"const_0_operand", {CONST_INT, ASHIFT}}, \ - {"const_8_operand", {CONST_INT, ASHIFT}}, \ - {"const_16_operand", {CONST_INT, ASHIFT}}, \ - {"const_24_operand", {CONST_INT, ASHIFT}}, \ - {"float_const_operand", {CONST_DOUBLE}}, \ - {"gpc_reg_operand", {SUBREG, REG}}, \ - {"gpc_reg_or_float_constant_operand", {SUBREG, REG, CONST_DOUBLE}}, \ - {"gpc_reg_or_integer_constant_operand", {SUBREG, REG, \ - CONST_INT, CONST_DOUBLE}}, \ - {"gpc_reg_or_immediate_operand", {SUBREG, REG, CONST_INT, \ - CONST_DOUBLE, CONST, \ - SYMBOL_REF, LABEL_REF}}, \ - {"spec_reg_operand", {REG}}, \ - {"accum_reg_operand", {REG}}, \ - {"srcb_operand", {SUBREG, REG, CONST_INT}}, \ - {"cmplsrcb_operand", {SUBREG, REG, CONST_INT}}, \ - {"reg_or_immediate_operand", {SUBREG, REG, CONST_INT, CONST, \ - CONST_DOUBLE, CONST, SYMBOL_REF, LABEL_REF}}, \ - {"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}}, \ - {"and_operand", {SUBREG, REG, CONST_INT}}, \ - {"add_operand", {SUBREG, REG, CONST_INT}}, \ - {"call_operand", {SYMBOL_REF, CONST_INT}}, \ - {"in_operand", {SUBREG, MEM, REG, CONST_INT, CONST, SYMBOL_REF, \ - LABEL_REF, CONST_DOUBLE}}, \ - {"out_operand", {SUBREG, REG, MEM}}, \ - {"reload_memory_operand", {SUBREG, REG, MEM}}, \ - {"fp_comparison_operator", {EQ, GT, GE}}, \ - {"branch_operator", {GE, LT}}, \ - {"load_multiple_operation", {PARALLEL}}, \ - {"store_multiple_operation", {PARALLEL}}, \ - {"epilogue_operand", {CODE_LABEL}}, diff --git a/gcc/config/a29k/a29k.md b/gcc/config/a29k/a29k.md deleted file mode 100755 index cc4f422..0000000 --- a/gcc/config/a29k/a29k.md +++ /dev/null @@ -1,2874 +0,0 @@ -;;- Machine description for AMD Am29000 for GNU C compiler -;; Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc. -;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; The insns in this file are presented in the same order as the AMD 29000 -;; User's Manual (i.e., alphabetical by machine op-code). -;; -;; DEFINE_EXPAND's are located near the first occurrence of the major insn -;; that they generate. - -;; The only attribute we have is the type. We only care about calls, branches, -;; loads, stores, floating-point operations, and multi-word insns. -;; Everything else is miscellaneous. - -(define_attr "type" - "call,branch,load,store,fadd,fmul,fam,fdiv,fsqrt,dmul,dam,ddiv,dsqrt,multi,misc" - (const_string "misc")) - -;; ASM insns cannot go into a delay slot, so call them "multi". -(define_asm_attributes [(set_attr "type" "multi")]) - -(define_attr "in_delay_slot" "yes,no" - (if_then_else (eq_attr "type" "call,branch,multi") (const_string "no") - (const_string "yes"))) - -;; Branch and call insns require a single delay slot. Annulling is not -;; supported. -(define_delay (eq_attr "type" "call,branch") - [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) - -;; Define the function unit usages. We first define memory as a unit. -(define_function_unit "memory" 1 0 (eq_attr "type" "load") 6 5 - [(eq_attr "type" "load")]) -(define_function_unit "memory" 1 0 (eq_attr "type" "load") 6 6 - [(eq_attr "type" "store")]) -(define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) - -;; Now define the function units for the floating-point support. Most -;; units are pipelined and can accept an input every cycle. -;; -;; Note that we have an inaccuracy here. If a fmac insn is issued, followed -;; 2 cycles later by a fadd, there will be a conflict for the floating -;; adder that we can't represent. Also, all insns will conflict for the -;; floating-point rounder. It isn't clear how to represent this. - -(define_function_unit "multiplier" 1 0 (eq_attr "type" "fmul") 3 0) -(define_function_unit "multiplier" 1 0 (eq_attr "type" "dmul") 6 4) -(define_function_unit "multiplier" 1 0 (eq_attr "type" "fam") 6 0) -(define_function_unit "multiplier" 1 0 (eq_attr "type" "dam") 9 4) - -(define_function_unit "adder" 1 0 (eq_attr "type" "fadd,fam,dam") 3 0) - -(define_function_unit "divider" 1 0 (eq_attr "type" "fdiv") 11 10) -(define_function_unit "divider" 1 0 (eq_attr "type" "fsqrt") 28 27) -(define_function_unit "divider" 1 0 (eq_attr "type" "ddiv") 18 17) -(define_function_unit "divider" 1 0 (eq_attr "type" "dsqrt") 57 56) - -;; ADD -(define_insn "addsi3" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") - (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r") - (match_operand:SI 2 "add_operand" "rI,N")))] - "" - "@ - add %0,%1,%2 - sub %0,%1,%n2") - -(define_insn "adddi3" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r") - (match_operand:DI 2 "gpc_reg_operand" "r")))] - "" - "add %L0,%L1,%L2\;addc %0,%1,%2" - [(set_attr "type" "multi")]) - -;; AND/ANDN -(define_insn "andsi3" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") - (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r") - (match_operand:SI 2 "and_operand" "rI,K")))] - "" - "@ - and %0,%1,%2 - andn %0,%1,%C2") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") - (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")) - (match_operand:SI 2 "cmplsrcb_operand" "r,K")))] - "" - "@ - andn %0,%2,%1 - nor %0,%1,%C2") - -;; CALLI -;; -;; Each call pattern is duplicated so that we can add CLOBBERs to the -;; resulting insn. -;; -;; We indicate that LR0 is clobbered in the CALL_INSN itself. Otherwise, -;; reorg will think it is just clobbered by the called function. - -(define_expand "call" - [(use (match_operand:SI 0 "" "")) - (use (match_operand 1 "" "")) - (use (match_operand 2 "" ""))] - "" - " -{ rtx insn = emit_call_insn (gen_call_internal (operands[0], operands[1])); - a29k_clobbers_to (insn, operands[2]); - - DONE; -}") - -(define_expand "call_internal" - [(parallel [(call (match_operand:SI 0 "" "") - (match_operand 1 "" "")) - (clobber (scratch:SI))])] - "" - " -{ - if (GET_CODE (operands[0]) != MEM) - abort (); - - /* We tell here whether this is a recursive call, since this insn may - later be inlined into another function. */ - if (! TARGET_SMALL_MEMORY - && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) - operands[0] = gen_rtx (MEM, SImode, - force_reg (Pmode, XEXP (operands[0], 0))); -}") - -(define_expand "call_value" - [(use (match_operand:SI 0 "gpc_reg_operand" "")) - (use (match_operand:SI 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" ""))] - "" - " -{ rtx insn = emit_call_insn (gen_call_value_internal (operands[0], operands[1], - operands[2])); - - a29k_clobbers_to (insn, operands[3]); - DONE; -}") - -(define_expand "call_value_internal" - [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") - (call (match_operand:SI 1 "" "") - (match_operand 2 "" ""))) - (clobber (scratch:SI))])] - "" - " -{ - if (GET_CODE (operands[1]) != MEM) - abort (); - - /* We tell here whether this is a recursive call, since this insn may - later be inlined into another function. */ - if (! TARGET_SMALL_MEMORY - && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) - operands[1] = gen_rtx (MEM, SImode, - force_reg (Pmode, XEXP (operands[1], 0))); - -}") - -(define_insn "" - [(call (match_operand:SI 0 "memory_operand" "m") - (match_operand 1 "" "")) - (clobber (match_scratch:SI 2 "=&l"))] - "GET_CODE (XEXP (operands[0], 0)) != CONST_INT" - "calli lr0,%0%#" - [(set_attr "type" "call")]) - -(define_insn "" - [(call (mem:SI (match_operand:SI 0 "call_operand" "i")) - (match_operand:SI 1 "general_operand" "g")) - (clobber (match_scratch:SI 2 "=&l"))] - "" - "call lr0,%F0" - [(set_attr "type" "call")]) - -(define_insn "" - [(set (match_operand 0 "gpc_reg_operand" "=r") - (call (match_operand:SI 1 "memory_operand" "m") - (match_operand 2 "" ""))) - (clobber (match_scratch:SI 3 "=&l"))] - "GET_CODE (XEXP (operands[1], 0)) != CONST_INT" - "calli lr0,%1%#" - [(set_attr "type" "call")]) - -(define_insn "" - [(set (match_operand 0 "gpc_reg_operand" "=r") - (call (mem:SI (match_operand:SI 1 "call_operand" "i")) - (match_operand:SI 2 "general_operand" "g"))) - (clobber (match_scratch:SI 3 "=&l"))] - "" - "call lr0,%F1" - [(set_attr "type" "call")]) - -(define_expand "probe" - [(call (mem:SI (symbol_ref:SI "_msp_check")) - (const_int 1))] - "TARGET_STACK_CHECK" - "") - -;; This is used for internal routine calls via TPC. Currently used only -;; in probe, above. -(define_insn "" - [(call (mem:SI (match_operand:SI 0 "immediate_operand" "s")) - (const_int 1))] - "" - "call %*,%0" - [(set_attr "type" "call")]) - -;; CONST, CONSTH, CONSTN -;; -;; Many of these are generated from move insns. -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (and:SI (match_operand:SI 1 "immediate_operand" "i") - (const_int 65535)))] - "" - "const %0,%1") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") - (const_int 16) - (match_operand:SI 1 "const_0_operand" "")) - (ashiftrt:SI (match_operand:SI 2 "immediate_operand" "i") - (const_int 16)))] - "" - "consth %0,%2") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") - (const_int 16) - (match_operand:SI 1 "const_0_operand" "")) - (match_operand:SI 2 "cint_16_operand" "J"))] - "" - "consth %0,%m2") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ior:SI (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0")) - (match_operand:SI 2 "const_int_operand" "n")))] - "(INTVAL (operands[2]) & 0xffff) == 0" - "consth %0,%2") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ior:SI (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0")) - (and:SI (match_operand:SI 2 "immediate_operand" "i") - (const_int -65536))))] - "" - "consth %0,%2") - -;; CONVERT -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (fix:SI (match_operand:SF 1 "register_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,0,3,0,1") - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (fix:SI (match_operand:DF 1 "register_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,0,3,0,2") - -(define_insn "fixuns_truncsfsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (unsigned_fix:SI (match_operand:SF 1 "register_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,1,3,0,1") - -(define_insn "fixuns_truncdfsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (unsigned_fix:SI (match_operand:DF 1 "register_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,1,3,0,2") - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=r") - (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,0,4,1,2") - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=r") - (float_extend:DF (match_operand:SF 1 "register_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,0,4,2,1") - -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=r") - (float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,0,4,1,0") - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "register_operand" "=r") - (float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,0,4,2,0") - -(define_insn "floatunssisf2" - [(set (match_operand:SF 0 "register_operand" "=r") - (unsigned_float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,1,4,1,0") - -(define_insn "floatunssidf2" - [(set (match_operand:DF 0 "register_operand" "=r") - (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "convert %0,%1,1,4,2,0") - -;; CPxxx, DEQ, DGT, DGE, FEQ, FGT, FGE -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (match_operator 3 "comparison_operator" - [(match_operand:SI 1 "gpc_reg_operand" "r") - (match_operand:SI 2 "srcb_operand" "rI")]))] - "" - "cp%J3 %0,%1,%2") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (match_operator 3 "fp_comparison_operator" - [(match_operand:SF 1 "register_operand" "r") - (match_operand:SF 2 "register_operand" "r")]))] - "! TARGET_SOFT_FLOAT" - "f%J3 %0,%1,%2" - [(set_attr "type" "fadd")]) - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (match_operator 3 "fp_comparison_operator" - [(match_operand:DF 1 "register_operand" "r") - (match_operand:DF 2 "register_operand" "r")]))] - "! TARGET_SOFT_FLOAT" - "d%J3 %0,%1,%2" - [(set_attr "type" "fadd")]) - -;; DADD -(define_expand "adddf3" - [(set (match_operand:DF 0 "register_operand" "") - (plus:DF (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "register_operand" "")))] - "! TARGET_SOFT_FLOAT" - "") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r") - (plus:DF (match_operand:DF 1 "register_operand" "%r") - (match_operand:DF 2 "register_operand" "r")))] - "! TARGET_29050 " - "dadd %0,%1,%2" - [(set_attr "type" "fadd")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,a") - (plus:DF (match_operand:DF 1 "register_operand" "%r,r") - (match_operand:DF 2 "register_operand" "r,0")))] - "TARGET_29050" - "@ - dadd %0,%1,%2 - dmac 8,%0,%1,%1" - [(set_attr "type" "fadd,dam")]) - -;; DDIV -(define_insn "divdf3" - [(set (match_operand:DF 0 "register_operand" "=r") - (div:DF (match_operand:DF 1 "register_operand" "=r") - (match_operand:DF 2 "register_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "ddiv %0,%1,%2" - [(set_attr "type" "ddiv")]) - -;; DIVIDE -;; -;; We must set Q to the sign extension of the dividend first. For MOD, we -;; must get the remainder from Q. -;; -;; For divmod: operand 1 is divided by operand 2; quotient goes to operand -;; 0 and remainder to operand 3. -(define_expand "divmodsi4" - [(set (match_dup 4) - (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "") - (const_int 31))) - (parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") - (div:SI (match_dup 1) - (match_operand:SI 2 "gpc_reg_operand" ""))) - (set (match_operand:SI 3 "gpc_reg_operand" "") - (mod:SI (match_dup 1) - (match_dup 2))) - (use (match_dup 4))])] - "" - " -{ - operands[4] = gen_reg_rtx (SImode); -}") - -(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 "gpc_reg_operand" "r"))) - (set (match_operand:SI 3 "register_operand" "=q") - (mod:SI (match_dup 1) - (match_dup 2))) - (use (match_operand:SI 4 "register_operand" "3"))] - "" - "divide %0,%1,%2") - -;; DIVIDU -;; -;; Similar to DIVIDE. -(define_expand "udivmodsi4" - [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") - (udiv:SI (match_operand:SI 1 "gpc_reg_operand" "") - (match_operand:SI 2 "gpc_reg_operand" ""))) - (set (match_operand:SI 3 "gpc_reg_operand" "") - (umod:SI (match_dup 1) - (match_dup 2))) - (use (const_int 0))])] - "" - "") - -(define_insn "" - [(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:SI 3 "register_operand" "=q") - (umod:SI (match_dup 1) - (match_dup 2))) - (use (match_operand:SI 4 "const_int_operand" "3"))] - "" - "dividu %0,%1,%2") - -;; DMAC/DMSM -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=a,*r") - (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "%r,A") - (match_operand:DF 2 "register_operand" "r,r")) - (match_operand:DF 3 "register_operand" "0,*r")))] - "TARGET_29050" - "@ - dmac 0,%0,%1,%2 - dmsm %0,%2,%3" - [(set_attr "type" "dam")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=a") - (plus:DF (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "r")) - (match_operand:DF 2 "register_operand" "r")) - (match_operand:DF 3 "register_operand" "0")))] - "TARGET_29050" - "dmac 1,%0,%2,%1" - [(set_attr "type" "dam")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=a") - (minus:DF (mult:DF (match_operand:DF 1 "register_operand" "%r") - (match_operand:DF 2 "register_operand" "r")) - (match_operand:DF 3 "register_operand" "0")))] - "TARGET_29050" - "dmac 2,%0,%1,%2" - [(set_attr "type" "dam")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=a") - (minus:DF (mult:DF (match_operand:DF 1 "register_operand" "r") - (neg:DF (match_operand:DF 2 "register_operand" "r"))) - (match_operand:DF 3 "register_operand" "0")))] - "TARGET_29050" - "dmac 3,%0,%1,%2" - [(set_attr "type" "dam")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=a") - (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "r")) - (match_operand:DF 2 "register_operand" "r")))] - "TARGET_29050" - "dmac 5,%0,%2,%1" - [(set_attr "type" "dam")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=a") - (minus:DF (neg:DF (match_operand:DF 1 "register_operand" "r")) - (match_operand:DF 2 "register_operand" "0")))] - "TARGET_29050" - "dmac 11,%0,%1,%1" - [(set_attr "type" "dam")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=a") - (neg:DF (plus:DF (match_operand:DF 1 "register_operand" "%r") - (match_operand:DF 2 "register_operand" "0"))))] - "TARGET_29050" - "dmac 11,%0,%1,%1" - [(set_attr "type" "dam")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,r,a") - (neg:DF (match_operand:DF 1 "register_operand" "0,r,r"))) - (clobber (match_scratch:SI 2 "=&r,&r,X"))] - "TARGET_29050" - "@ - cpeq %2,gr1,gr1\;xor %0,%1,%2 - cpeq %2,gr1,gr1\;xor %0,%1,%2\;sll %L0,%L1,0 - dmac 13,%0,%1,%1" - [(set_attr "type" "multi,multi,dam")]) - -;; DMUL -(define_expand "muldf3" - [(set (match_operand:DF 0 "register_operand" "") - (mult:DF (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "register_operand" "")))] - "! TARGET_SOFT_FLOAT" - "") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r") - (mult:DF (match_operand:DF 1 "register_operand" "%r") - (match_operand:DF 2 "register_operand" "r")))] - "! TARGET_29050" - "dmul %0,%1,%2" - [(set_attr "type" "dmul")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,a") - (mult:DF (match_operand:DF 1 "register_operand" "%r,r") - (match_operand:DF 2 "register_operand" "r,r")))] - "TARGET_29050" - "@ - dmul %0,%1,%2 - dmac 4,%0,%1,%2" - [(set_attr "type" "dmul,dam")]) - -;; DSUB -(define_expand "subdf3" - [(set (match_operand:DF 0 "register_operand" "=r") - (minus:DF (match_operand:DF 1 "register_operand" "r") - (match_operand:DF 2 "register_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r") - (minus:DF (match_operand:DF 1 "register_operand" "r") - (match_operand:DF 2 "register_operand" "r")))] - "! TARGET_29050" - "dsub %0,%1,%2" - [(set_attr "type" "fadd")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r,a,a") - (minus:DF (match_operand:DF 1 "register_operand" "r,0,r") - (match_operand:DF 2 "register_operand" "r,r,0")))] - "TARGET_29050" - "@ - dsub %0,%1,%2 - dmac 9,%0,%2,%2 - dmac 10,%0,%1,%1" - [(set_attr "type" "fadd,dam,dam")]) - -;; EXBYTE -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ior:SI (and:SI (match_operand:SI 1 "srcb_operand" "rI") - (const_int -256)) - (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") - (const_int 8) - (ashift:PSI - (match_operand:PSI 3 "register_operand" "b") - (const_int 3)))))] - "" - "exbyte %0,%2,%1") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r") - (const_int 8) - (ashift:PSI - (match_operand:PSI 2 "register_operand" "b") - (const_int 3))))] - "" - "exbyte %0,%1,0") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") - (const_int 8) - (match_operand:PSI 1 "const_24_operand" "")) - (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") - (const_int 8) - (ashift:PSI - (match_operand:PSI 3 "register_operand" "b") - (const_int 3))))] - "" - "exbyte %0,%2,%0") - -(define_expand "extzv" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "") - (match_operand:SI 2 "general_operand" "") - (match_operand:SI 3 "general_operand" "")))] - "" - " -{ - int size, pos; - - if (GET_CODE (operands[2]) != CONST_INT - || GET_CODE (operands[3]) != CONST_INT) - FAIL; - - size = INTVAL (operands[2]); - pos = INTVAL (operands[3]); - - /* Can't do this unless a byte extraction. If extracting the high - or low byte, don't do this because a shift or AND is shorter. - Don't do 16-bit extracts, since the only two are the high and low - ends, and it is faster to do them with CONSTH and SRL. */ - - if (size != 8 || (pos != 8 && pos != 16)) - FAIL; - - operands[3] = gen_rtx (ASHIFT, PSImode, - force_reg (PSImode, GEN_INT (pos / 8)), - GEN_INT (3)); - -}") - -;; EXHW -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ior:SI (and:SI (match_operand:SI 1 "srcb_operand" "rI") - (const_int -65536)) - (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") - (const_int 16) - (ashift:PSI - (match_operand:PSI 3 "register_operand" "b") - (const_int 3)))))] - "" - "exhw %0,%2,%1") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r") - (const_int 16) - (ashift:PSI - (match_operand:PSI 2 "register_operand" "b") - (const_int 3))))] - "" - "exhw %0,%1,0") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") - (const_int 16) - (match_operand:PSI 1 "const_16_operand" "")) - (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r") - (const_int 16) - (ashift:PSI - (match_operand:PSI 3 "register_operand" "b") - (const_int 3))))] - "" - "exhw %0,%2,%0") - -;; EXHWS -;; -;; This is probably unused. The high-order 16-bits are obtained with an SRA -;; insn. The low-order 16 bits are a sign-extend, which is a pair of -;; shifts. Setting BP followed by the insn is equivalent, so we don't -;; bother going to any trouble to generate this insn. - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (sign_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r") - (const_int 16) - (ashift:PSI - (match_operand:PSI 2 "register_operand" "b") - (const_int 3))))] - "" - "exhws %0,%1") - -;; EXTRACT -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r") - (match_operand:PSI 2 "register_operand" "f")))] - "" - "extract %0,%1,%1") - -(define_expand "rotlsi3" - [(set (match_dup 3) - (match_operand:SI 2 "gpc_reg_or_immediate_operand" "")) - (set (match_operand:SI 0 "gpc_reg_operand" "") - (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "") - (match_dup 3)))] - "" - " -{ operands[2] = gen_lowpart (PSImode, operands[2]); - operands[3] = gen_reg_rtx (PSImode); -}") - -;; It would be nice to be able to have a define_split corresponding to the -;; above, but there is no way to tell combine we need a PSImode temporary. -;; If we put a (clobber (scratch:PSI)) there, combine would merge the above -;; two insns. This is bad because it then thinks only one insn is needed. - -;; FADD -(define_expand "addsf3" - [(set (match_operand:SF 0 "register_operand" "") - (plus:SF (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "register_operand" "")))] - "! TARGET_SOFT_FLOAT" - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r") - (plus:SF (match_operand:SF 1 "register_operand" "%r") - (match_operand:SF 2 "register_operand" "r")))] - "! TARGET_29050" - "fadd %0,%1,%2" - [(set_attr "type" "fadd")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r,a") - (plus:SF (match_operand:SF 1 "register_operand" "%r,r") - (match_operand:SF 2 "register_operand" "r,0")))] - "TARGET_29050" - "@ - fadd %0,%1,%2 - fmac 8,%0,%1,%1" - [(set_attr "type" "fadd,fam")]) - -;; FDIV -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=r") - (div:SF (match_operand:SF 1 "register_operand" "=r") - (match_operand:SF 2 "register_operand" "r")))] - "! TARGET_SOFT_FLOAT" - "fdiv %0,%1,%2" - [(set_attr "type" "fdiv")]) - -;; FDMUL -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=r") - (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "%r")) - (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))] - "! TARGET_SOFT_FLOAT" - "fdmul %0,%1,%2") - -;; FMAC/FMSM -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=a,*r") - (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "%r,A") - (match_operand:SF 2 "register_operand" "r,r")) - (match_operand:SF 3 "register_operand" "0,*r")))] - "TARGET_29050" - "@ - fmac 0,%0,%1,%2 - fmsm %0,%2,%3" - [(set_attr "type" "fam")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=a") - (plus:SF (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "r")) - (match_operand:SF 2 "register_operand" "r")) - (match_operand:SF 3 "register_operand" "0")))] - "TARGET_29050" - "fmac 1,%0,%2,%1" - [(set_attr "type" "fam")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=a") - (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "%r") - (match_operand:SF 2 "register_operand" "r")) - (match_operand:SF 3 "register_operand" "0")))] - "TARGET_29050" - "fmac 2,%0,%1,%2" - [(set_attr "type" "fam")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=a") - (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "r")) - (match_operand:SF 2 "register_operand" "r")) - (match_operand:SF 3 "register_operand" "0")))] - "TARGET_29050" - "fmac 3,%0,%2,%1" - [(set_attr "type" "fam")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=a") - (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "r")) - (match_operand:SF 2 "register_operand" "r")))] - "TARGET_29050" - "fmac 5,%0,%2,%1" - [(set_attr "type" "fam")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=a") - (minus:SF (neg:SF (match_operand:SF 1 "register_operand" "%r")) - (match_operand:SF 2 "register_operand" "0")))] - "TARGET_29050" - "fmac 11,%0,%1,%1" - [(set_attr "type" "fam")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=a") - (neg:SF (plus:SF (match_operand:SF 1 "register_operand" "%r") - (match_operand:SF 2 "register_operand" "0"))))] - "TARGET_29050" - "fmac 11,%0,%1,%1" - [(set_attr "type" "fam")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r,a") - (neg:SF (match_operand:SF 1 "register_operand" "r,r"))) - (clobber (match_scratch:SI 2 "=&r,X"))] - "TARGET_29050" - "@ - cpeq %2,gr1,gr1\;xor %0,%1,%2 - fmac 13,%0,%1,%1" - [(set_attr "type" "multi,fam")]) - -;; FMUL -(define_expand "mulsf3" - [(set (match_operand:SF 0 "register_operand" "") - (mult:SF (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "register_operand" "")))] - "! TARGET_SOFT_FLOAT" - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r") - (mult:SF (match_operand:SF 1 "register_operand" "%r") - (match_operand:SF 2 "register_operand" "r")))] - "! TARGET_29050" - "fmul %0,%1,%2" - [(set_attr "type" "fmul")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r,a") - (mult:SF (match_operand:SF 1 "register_operand" "%r,r") - (match_operand:SF 2 "register_operand" "r,r")))] - "TARGET_29050" - "@ - fmul %0,%1,%2 - fmac 4,%0,%1,%2" - [(set_attr "type" "fmul,fam")]) - -;; FSUB -(define_expand "subsf3" - [(set (match_operand:SF 0 "register_operand" "") - (minus:SF (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "register_operand" "")))] - "! TARGET_SOFT_FLOAT" - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r") - (minus:SF (match_operand:SF 1 "register_operand" "r") - (match_operand:SF 2 "register_operand" "r")))] - "! TARGET_29050" - "fsub %0,%1,%2" - [(set_attr "type" "fadd")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=r,a,a") - (minus:SF (match_operand:SF 1 "register_operand" "r,0,r") - (match_operand:SF 2 "register_operand" "r,r,0")))] - "TARGET_29050" - "@ - fsub %0,%1,%2 - fmac 9,%0,%2,%2 - fmac 10,%0,%1,%1" - [(set_attr "type" "fadd,fam,fam")]) - -;; INBYTE -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") - (const_int 8) - (ashift:PSI - (match_operand:PSI 2 "register_operand" "b") - (const_int 3))) - (match_operand:SI 1 "srcb_operand" "rI"))] - "" - "inbyte %0,%0,%1") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ior:SI (and:SI - (not:SI - (ashift:SI (const_int 255) - (ashift:PSI - (match_operand:PSI 3 "register_operand" "b") - (const_int 3)))) - (match_operand:SI 1 "gpc_reg_operand" "r")) - (ashift:SI (zero_extend:SI - (match_operand:QI 2 "srcb_operand" "rI")) - (ashift:PSI (match_dup 3) (const_int 3)))))] - "" - "inbyte %0,%1,%2") - -;; INHW -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") - (const_int 16) - (ashift:PSI - (match_operand:PSI 2 "register_operand" "b") - (const_int 3))) - (match_operand:SI 1 "srcb_operand" "rI"))] - "" - "inhw %0,%0,%1") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ior:SI (and:SI - (not:SI - (ashift:SI (const_int 65535) - (ashift:PSI - (match_operand:PSI 3 "register_operand" "b") - (const_int 3)))) - (match_operand:SI 1 "gpc_reg_operand" "r")) - (ashift:SI (zero_extend:SI - (match_operand:HI 2 "srcb_operand" "rI")) - (ashift:PSI (match_dup 3) (const_int 3)))))] - "" - "inhw %0,%1,%2") - -(define_expand "insv" - [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "") - (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")) - (match_operand:SI 3 "srcb_operand" ""))] - "" - " -{ - int size, pos; - - if (GET_CODE (operands[1]) != CONST_INT - || GET_CODE (operands[2]) != CONST_INT) - FAIL; - - size = INTVAL (operands[1]); - pos = INTVAL (operands[2]); - if ((size != 8 && size != 16) || pos % size != 0) - FAIL; - - operands[2] = gen_rtx (ASHIFT, PSImode, - force_reg (PSImode, GEN_INT (pos / 8)), - GEN_INT (3)); -}") - -;; LOAD (also used by move insn). -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "r") - (const_int -4)))) - (set (match_operand:PSI 2 "register_operand" "=b") - (truncate:PSI (match_dup 1)))] - "! TARGET_DW_ENABLE" - "load 0,16,%0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] - "TARGET_DW_ENABLE" - "load 0,1,%0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:HI 0 "gpc_reg_operand" "=r") - (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))] - "TARGET_DW_ENABLE" - "load 0,1,%0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] - "TARGET_DW_ENABLE" - "load 0,2,%0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (sign_extend:SI (match_operand:QI 1 "memory_operand" "m"))) - (clobber (match_scratch:PSI 2 "=&b"))] - "TARGET_DW_ENABLE" - "load 0,17,%0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:HI 0 "gpc_reg_operand" "=r") - (sign_extend:HI (match_operand:QI 1 "memory_operand" "m"))) - (clobber (match_scratch:PSI 2 "=&b"))] - "TARGET_DW_ENABLE" - "load 0,17,%0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) - (clobber (match_scratch:PSI 2 "=&b"))] - "TARGET_DW_ENABLE" - "load 0,18,%0,%1" - [(set_attr "type" "load")]) - -;; LOADM -(define_expand "load_multiple" - [(set (match_dup 4) - (match_operand:PSI 2 "const_int_operand" "")) - (match_par_dup 3 [(set (match_operand:SI 0 "" "") - (match_operand:SI 1 "" ""))])] - "" - " -{ - int regno; - int count; - rtx from; - int i; - - /* Support only loading a constant number of hard registers from memory. */ - if (GET_CODE (operands[2]) != CONST_INT - || operands[2] == const1_rtx - || GET_CODE (operands[1]) != MEM - || GET_CODE (operands[0]) != REG - || REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) - FAIL; - - count = INTVAL (operands[2]); - regno = REGNO (operands[0]); - - /* CR gets set to the number of registers minus one. */ - operands[2] = GEN_INT(count - 1); - - operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2)); - from = memory_address (SImode, XEXP (operands[1], 0)); - XVECEXP (operands[3], 0, 0) = gen_rtx (SET, VOIDmode, - gen_rtx (REG, SImode, regno), - gen_rtx (MEM, SImode, from)); - operands[4] = gen_reg_rtx (PSImode); - - XVECEXP (operands[3], 0, 1) = gen_rtx (USE, VOIDmode, operands[4]); - XVECEXP (operands[3], 0, 2) = gen_rtx (CLOBBER, VOIDmode, operands[4]); - - for (i = 1; i < count; i++) - XVECEXP (operands[3], 0, i + 2) - = gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, regno + i), - gen_rtx (MEM, SImode, plus_constant (from, i * 4))); -}") - -;; Indicate that CR is used and is then clobbered. -(define_insn "" - [(set (match_operand 0 "gpc_reg_operand" "=r") - (match_operand 1 "memory_operand" "m")) - (use (match_operand:PSI 2 "register_operand" "+c")) - (clobber (match_dup 2))] - "GET_MODE (operands[0]) == GET_MODE (operands[1]) - && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD" - "loadm 0,0,%0,%1" - [(set_attr "type" "load")]) - -(define_insn "" - [(match_parallel 0 "load_multiple_operation" - [(set (match_operand:SI 1 "gpc_reg_operand" "=r") - (match_operand:SI 2 "memory_operand" "m")) - (use (match_operand:PSI 3 "register_operand" "+c")) - (clobber (match_dup 3))])] - "" - "loadm 0,0,%1,%2" - [(set_attr "type" "load")]) - -;; MTSR (used also by move insn) -(define_insn "" - [(set (match_operand:SI 0 "spec_reg_operand" "=*h,*h") - (and:SI (match_operand:SI 1 "gpc_reg_or_immediate_operand" "r,i") - (match_operand:SI 2 "const_int_operand" "n,n")))] - "masks_bits_for_special (operands[0], operands[2])" - "@ - mtsr %0,%1 - mtsrim %0,%1") - -(define_insn "" - [(set (match_operand:PSI 0 "register_operand" "=h,h") - (truncate:PSI - (match_operand:SI 1 "gpc_reg_or_immediate_operand" "r,i")))] - "" - "@ - mtsr %0,%1 - mtsrim %0,%1") - -;; MULTIPLY, MULTM, MULTMU -(define_insn "mulsi3" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (mult:SI (match_operand:SI 1 "gpc_reg_operand" "%r") - (match_operand:SI 2 "gpc_reg_operand" "r"))) - (clobber (match_scratch:SI 3 "=&q"))] - "" - "multiply %0,%1,%2") - -(define_insn "mulsidi3" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r")) - (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r")))) - (clobber (match_scratch:SI 3 "=&q"))] - "TARGET_MULTM" - "multiply %L0,%1,%2\;multm %0,%1,%2" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")) - (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "")))) - (clobber (reg:SI 180))] - "reload_completed" - [(parallel [(set (match_dup 3) - (mult:SI (match_dup 1) (match_dup 2))) - (clobber (reg:SI 180))]) - (parallel [(set (match_dup 4) - (truncate:SI - (lshiftrt:DI - (mult:DI (sign_extend:DI (match_dup 1)) - (sign_extend:DI (match_dup 2))) - (const_int 32)))) - (clobber (reg:SI 180))])] - " -{ operands[3] = operand_subword (operands[0], 1, 1, DImode); - operands[4] = operand_subword (operands[0], 0, 1, DImode); } ") - -(define_insn "umulsidi3" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (mult:DI (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r")) - (zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r")))) - (clobber (match_scratch:SI 3 "=&q"))] - "TARGET_MULTM" - "multiplu %L0,%1,%2\;multmu %0,%1,%2" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (mult:DI (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")) - (zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" "")))) - (clobber (reg:SI 180))] - "reload_completed" - [(parallel [(set (match_dup 3) - (mult:SI (match_dup 1) (match_dup 2))) - (clobber (reg:SI 180))]) - (parallel [(set (match_dup 4) - (truncate:SI - (lshiftrt:DI - (mult:DI (zero_extend:DI (match_dup 1)) - (zero_extend:DI (match_dup 2))) - (const_int 32)))) - (clobber (reg:SI 180))])] - " -{ operands[3] = operand_subword (operands[0], 1, 1, DImode); - operands[4] = operand_subword (operands[0], 0, 1, DImode); } ") - -(define_insn "smulsi3_highpart" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (truncate:SI - (lshiftrt:DI - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r")) - (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))) - (const_int 32)))) - (clobber (match_scratch:SI 3 "=&q"))] - "TARGET_MULTM" - "multm %0,%1,%2") - -(define_insn "umulsi3_highpart" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (truncate:SI - (lshiftrt:DI - (mult:DI (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r")) - (zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))) - (const_int 32)))) - (clobber (match_scratch:SI 3 "=&q"))] - "TARGET_MULTM" - "multmu %0,%1,%2") - -;; NAND -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r")) - (not:SI (match_operand:SI 2 "gpc_reg_operand" "r"))))] - "" - "nand %0,%1,%2") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")) - (match_operand:SI 2 "const_int_operand" "K")))] - ; Match TARGET_29050 in "orn" pattern for slightly better reload. - "! TARGET_29050 && ((unsigned) ~ INTVAL (operands[2])) < 256" - "nand %0,%1,%C2") - -;; NOR -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r")) - (not:SI (match_operand:SI 2 "gpc_reg_operand" "r"))))] - "" - "nor %0,%1,%2") - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")))] - "" - "nor %0,%1,0") - -;; OR/ORN -(define_expand "iorsi3" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (ior:SI (match_operand:SI 1 "gpc_reg_operand" "") - (match_operand:SI 2 "srcb_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ior:SI (match_operand:SI 1 "gpc_reg_operand" "%r") - (match_operand:SI 2 "srcb_operand" "rI")))] - "! TARGET_29050" - "or %0,%1,%2") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") - (ior:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r") - (match_operand:SI 2 "and_operand" "rI,K")))] - "TARGET_29050" - "@ - or %0,%1,%2 - orn %0,%1,%C2") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") - (ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")) - (match_operand:SI 2 "cmplsrcb_operand" "r,K")))] - "TARGET_29050" - "@ - orn %0,%2,%1 - nand %0,%1,%C2") - - -;; SLL (also used by move insn) -(define_insn "nop" - [(const_int 0)] - "" - "aseq 0x40,gr1,gr1") - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r") - (match_operand:QI 2 "srcb_operand" "rn")))] - "" - "sll %0,%1,%Q2") - -;; SQRT -(define_insn "sqrtsf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "=r") - (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "r")))] - "TARGET_29050" - "sqrt %0,%1,1" - [(set_attr "type" "fsqrt")]) - -(define_insn "sqrtdf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "=r") - (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "r")))] - "TARGET_29050" - "sqrt %0,%1,2" - [(set_attr "type" "dsqrt")]) - -;; SRA -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r") - (match_operand:QI 2 "srcb_operand" "rn")))] - "" - "sra %0,%1,%Q2") - -;; SRL -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r") - (match_operand:QI 2 "srcb_operand" "rn")))] - "" - "srl %0,%1,%Q2") - -;; STORE -;; -;; These somewhat bogus patterns exist to set OPT = 001/010 for partial-word -;; stores on systems with DW not set. -(define_insn "" - [(set (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "r") - (const_int -4))) - (match_operand:SI 1 "gpc_reg_operand" "r"))] - "! TARGET_DW_ENABLE" - "store 0,1,%1,%0" - [(set_attr "type" "store")]) - -(define_insn "" - [(set (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "r") - (const_int -3))) - (match_operand:SI 1 "gpc_reg_operand" "r"))] - "! TARGET_DW_ENABLE" - "store 0,2,%1,%0" - [(set_attr "type" "store")]) - -;; STOREM -(define_expand "store_multiple" - [(use (match_operand 0 "" "")) - (use (match_operand 1 "" "")) - (use (match_operand 2 "" ""))] - "" - " -{ rtx pat; - - if (TARGET_NO_STOREM_BUG) - pat = gen_store_multiple_no_bug (operands[0], operands[1], operands[2]); - else - pat = gen_store_multiple_bug (operands[0], operands[1], operands[2]); - - if (pat) - emit_insn (pat); - else - FAIL; - - DONE; -}") - -(define_expand "store_multiple_no_bug" - [(set (match_dup 4) - (match_operand:PSI 2 "const_int_operand" "")) - (match_par_dup 3 [(set (match_operand:SI 0 "" "") - (match_operand:SI 1 "" ""))])] - "" - " -{ - int regno; - int count; - rtx from; - int i; - - /* Support only storing a constant number of hard registers to memory. */ - if (GET_CODE (operands[2]) != CONST_INT - || operands[2] == const1_rtx - || GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != REG - || REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) - FAIL; - - count = INTVAL (operands[2]); - regno = REGNO (operands[1]); - - /* CR gets set to the number of registers minus one. */ - operands[2] = GEN_INT(count - 1); - - operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2)); - from = memory_address (SImode, XEXP (operands[0], 0)); - XVECEXP (operands[3], 0, 0) = gen_rtx (SET, VOIDmode, - gen_rtx (MEM, SImode, from), - gen_rtx (REG, SImode, regno)); - operands[4] = gen_reg_rtx (PSImode); - XVECEXP (operands[3], 0, 1) = gen_rtx (USE, VOIDmode, operands[4]); - XVECEXP (operands[3], 0, 2) = gen_rtx (CLOBBER, VOIDmode, operands[4]); - - for (i = 1; i < count; i++) - XVECEXP (operands[3], 0, i + 2) - = gen_rtx (SET, VOIDmode, - gen_rtx (MEM, SImode, plus_constant (from, i * 4)), - gen_rtx (REG, SImode, regno + i)); -}") - -(define_expand "store_multiple_bug" - [(match_par_dup 3 [(set (match_operand:SI 0 "" "") - (match_operand:SI 1 "" "")) - (use (match_operand:SI 2 "" ""))])] - "" - " -{ - int regno; - int count; - rtx from; - int i; - - /* Support only storing a constant number of hard registers to memory. */ - if (GET_CODE (operands[2]) != CONST_INT - || operands[2] == const1_rtx - || GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != REG - || REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) - FAIL; - - count = INTVAL (operands[2]); - regno = REGNO (operands[1]); - - operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 1)); - from = memory_address (SImode, XEXP (operands[0], 0)); - XVECEXP (operands[3], 0, 0) = gen_rtx (SET, VOIDmode, - gen_rtx (MEM, SImode, from), - gen_rtx (REG, SImode, regno)); - XVECEXP (operands[3], 0, 1) - = gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, PSImode)); - - for (i = 1; i < count; i++) - XVECEXP (operands[3], 0, i + 1) - = gen_rtx (SET, VOIDmode, - gen_rtx (MEM, SImode, plus_constant (from, i * 4)), - gen_rtx (REG, SImode, regno + i)); -}") - -(define_insn "" - [(set (match_operand 0 "memory_operand" "=m") - (match_operand 1 "gpc_reg_operand" "r")) - (clobber (match_scratch:PSI 2 "=&c"))] - "!TARGET_NO_STOREM_BUG - && GET_MODE (operands[0]) == GET_MODE (operands[1]) - && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD" - "mtsrim cr,%S1\;storem 0,0,%1,%0" - [(set_attr "type" "multi")]) - -(define_insn "" - [(match_parallel 0 "store_multiple_operation" - [(set (match_operand:SI 1 "memory_operand" "=m") - (match_operand:SI 2 "gpc_reg_operand" "r")) - (clobber (match_scratch:PSI 3 "=&c"))])] - "!TARGET_NO_STOREM_BUG" - "mtsrim cr,%V0\;storem 0,0,%2,%1" - [(set_attr "type" "multi")]) - -(define_insn "" - [(set (match_operand 0 "memory_operand" "=m") - (match_operand 1 "gpc_reg_operand" "r")) - (use (match_operand:PSI 2 "register_operand" "+c")) - (clobber (match_dup 2))] - "TARGET_NO_STOREM_BUG - && GET_MODE (operands[0]) == GET_MODE (operands[1]) - && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD" - "storem 0,0,%1,%0" - [(set_attr "type" "store")]) - -(define_insn "" - [(match_parallel 0 "store_multiple_operation" - [(set (match_operand:SI 1 "memory_operand" "=m") - (match_operand:SI 2 "gpc_reg_operand" "r")) - (use (match_operand:PSI 3 "register_operand" "+c")) - (clobber (match_dup 3))])] - "TARGET_NO_STOREM_BUG" - "storem 0,0,%2,%1" - [(set_attr "type" "store")]) - -;; SUB -;; -;; Either operand can be a register or an 8-bit constant, but both cannot be -;; constants (can't usually occur anyway). -(define_expand "subsi3" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (minus:SI (match_operand:SI 1 "srcb_operand" "") - (match_operand:SI 2 "srcb_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == CONST_INT - && GET_CODE (operands[1]) == CONST_INT) - operands[1] = force_reg (SImode, operands[1]); -}") - -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") - (minus:SI (match_operand:SI 1 "srcb_operand" "r,I") - (match_operand:SI 2 "srcb_operand" "rI,r")))] - "register_operand (operands[1], SImode) - || register_operand (operands[2], SImode)" - "@ - sub %0,%1,%2 - subr %0,%2,%1") - -(define_insn "subdi3" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (minus:DI (match_operand:DI 1 "gpc_reg_operand" "r") - (match_operand:DI 2 "gpc_reg_operand" "r")))] - "" - "sub %L0,%L1,%L2\;subc %0,%1,%2" - [(set_attr "type" "multi")]) - -;; SUBR (also used above in SUB) -(define_insn "negdi2" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))] - "" - "subr %L0,%L1,0\;subrc %0,%1,0" - [(set_attr "type" "multi")]) - -(define_insn "negsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r")))] - "" - "subr %0,%1,0") - -;; XNOR -(define_insn "" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (not:SI (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r") - (match_operand:SI 2 "gpc_reg_operand" "r"))))] - "" - "xnor %0,%1,%2") - -;; XOR - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") - (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r") - (match_operand:SI 2 "and_operand" "rI,K")))] - "" - "@ - xor %0,%1,%2 - xnor %0,%1,%C2") - -;; Can use XOR to negate floating-point values, but we are better off not doing -;; it that way on the 29050 so it can combine with the fmac insns. -(define_expand "negsf2" - [(parallel [(set (match_operand:SF 0 "register_operand" "") - (neg:SF (match_operand:SF 1 "register_operand" ""))) - (clobber (match_scratch:SI 2 ""))])] - "! TARGET_SOFT_FLOAT" - " -{ - rtx result; - rtx target; - - if (! TARGET_29050) - { - target = operand_subword_force (operands[0], 0, SFmode); - result = expand_binop (SImode, xor_optab, - operand_subword_force (operands[1], 0, SFmode), - GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); - if (result == 0) - abort (); - - if (result != target) - emit_move_insn (result, target); - - /* Make a place for REG_EQUAL. */ - emit_move_insn (operands[0], operands[0]); - DONE; - } -}") - -(define_expand "negdf2" - [(parallel [(set (match_operand:DF 0 "register_operand" "") - (neg:DF (match_operand:DF 1 "register_operand" ""))) - (clobber (match_scratch:SI 2 ""))])] - "! TARGET_SOFT_FLOAT" - " -{ - rtx result; - rtx target; - rtx insns; - - if (! TARGET_29050) - { - start_sequence (); - target = operand_subword (operands[0], 0, 1, DFmode); - result = expand_binop (SImode, xor_optab, - operand_subword_force (operands[1], 0, DFmode), - GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); - if (result == 0) - abort (); - - if (result != target) - emit_move_insn (result, target); - - emit_move_insn (operand_subword (operands[0], 1, 1, DFmode), - operand_subword_force (operands[1], 1, DFmode)); - - insns = get_insns (); - end_sequence (); - - emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); - DONE; - } -}") - -;; Sign extend and truncation operations. -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "gpc_reg_operand" "=r") - (zero_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r")))] - "" - "and %0,%1,255") - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r")))] - "" - "and %0,%1,255") - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0")))] - "" - "consth %0,0") - -(define_expand "extendqihi2" - [(set (match_dup 2) - (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "") - (const_int 24))) - (set (match_operand:HI 0 "gpc_reg_operand" "") - (ashiftrt:SI (match_dup 2) - (const_int 24)))] - "" - " -{ operands[0] = gen_lowpart (SImode, operands[0]); - operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_reg_rtx (SImode); }") - -(define_expand "extendqisi2" - [(set (match_dup 2) - (ashift:SI (match_operand:QI 1 "gpc_reg_operand" "") - (const_int 24))) - (set (match_operand:SI 0 "gpc_reg_operand" "") - (ashiftrt:SI (match_dup 2) - (const_int 24)))] - "" - " -{ operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_reg_rtx (SImode); }") - -(define_expand "extendhisi2" - [(set (match_dup 2) - (ashift:SI (match_operand:HI 1 "gpc_reg_operand" "") - (const_int 16))) - (set (match_operand:SI 0 "gpc_reg_operand" "") - (ashiftrt:SI (match_dup 2) - (const_int 16)))] - "" - " -{ operands[1] = gen_lowpart (SImode, operands[1]); - operands[2] = gen_reg_rtx (SImode); }") - -;; Define the methods used to move data around. -;; -;; movsi: -;; -;; If storing into memory, force source into register. -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && ! gpc_reg_operand (operands[1], SImode)) - operands[1] = copy_to_mode_reg (SImode, operands[1]); - else if (spec_reg_operand (operands[0], SImode) - && ! (register_operand (operands[1], SImode) - || cint_16_operand (operands[1], SImode))) - operands[1] = force_reg (SImode, operands[1]); -}") - -(define_expand "movpsi" - [(set (match_operand:PSI 0 "general_operand" "") - (match_operand:PSI 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! gpc_reg_operand (operands[1], PSImode)) - operands[1] = copy_to_mode_reg (PSImode, operands[1]); - else if (spec_reg_operand (operands[0], PSImode) - && ! (register_operand (operands[1], PSImode) - || cint_16_operand (operands[1], PSImode))) - operands[1] = force_reg (PSImode, operands[1]); -}") - -(define_split - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (match_operand:SI 1 "long_const_operand" ""))] - "" - [(set (match_dup 0) - (and:SI (match_dup 1) - (const_int 65535))) - (set (match_dup 0) - (ior:SI (zero_extend:SI (match_dup 2)) - (and:SI (match_dup 1) - (const_int -65536))))] - " operands[2] = gen_lowpart (HImode, operands[0]); ") - -;; Subroutines to load/store halfwords. Operands 0 and 1 are the output and -;; input, respectively, except that the address is passed for a MEM instead -;; of the MEM itself and the short item is passed in QImode. -;; -;; Operand 2 is a scratch general register and operand 3 is a scratch register -;; used for BP. When called before reload, pseudos are passed for both -;; operands. During reload, R_TAV is used for the general register, and -;; a reload register of class BR_REGS (R_VP) for BP. -;; -;; We have two versions of the store operations, for when halfword writes are -;; supported and when they are not. -(define_expand "loadhi" - [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "") - (const_int -4)))) - (set (match_operand:PSI 3 "register_operand" "") - (truncate:PSI (match_dup 1)))]) - (set (match_operand:SI 0 "gpc_reg_operand" "") - (zero_extract:SI (match_dup 2) - (const_int 16) - (ashift:PSI (match_dup 3) (const_int 3))))] - "" - "") - -(define_expand "storehinhww" - [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "") - (const_int -4)))) - (set (match_operand:PSI 3 "register_operand" "") - (truncate:PSI (match_dup 0)))]) - (set (zero_extract:SI (match_dup 2) - (const_int 16) - (ashift:PSI (match_dup 3) (const_int 3))) - (match_operand:SI 1 "gpc_reg_operand" "")) - (set (mem:SI (match_dup 0)) - (match_dup 2))] - "" - "") - -(define_expand "storehihww" - [(set (match_operand:PSI 3 "register_operand" "") - (truncate:PSI (match_operand:SI 0 "gpc_reg_operand" ""))) - (set (match_operand:SI 2 "gpc_reg_operand" "") - (ior:SI (and:SI (not:SI (ashift:SI (const_int 65535) - (ashift:PSI (match_dup 3) - (const_int 3)))) - (match_operand:SI 1 "gpc_reg_operand" "")) - (ashift:SI (zero_extend:SI (match_dup 4)) - (ashift:PSI (match_dup 3) (const_int 3))))) - (set (mem:SI (and:SI (match_dup 0) - (const_int -3))) - (match_dup 2))] - "" - " -{ operands[4] = gen_lowpart (HImode, operands[1]); }") - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ if (GET_CODE (operands[0]) == MEM) - { - if (! gpc_reg_operand (operands[1], HImode)) - operands[1] = copy_to_mode_reg (HImode, operands[1]); - if (! TARGET_DW_ENABLE) - { - rtx general = gen_reg_rtx (SImode); - rtx bp = gen_reg_rtx (PSImode); - rtx (*fcn) () - = TARGET_BYTE_WRITES ? gen_storehihww : gen_storehinhww; - rtx seq = (*fcn) (XEXP (operands[0], 0), - gen_lowpart (SImode, operands[1]), - general, bp); - - a29k_set_memflags (seq, operands[0]); - emit_insn (seq); - DONE; - } - } - else if (GET_CODE (operands[1]) == MEM) - { - if (! TARGET_DW_ENABLE) - { - rtx general = gen_reg_rtx (SImode); - rtx bp = gen_reg_rtx (PSImode); - rtx seq = gen_loadhi (gen_lowpart (SImode, operands[0]), - XEXP (operands[1], 0), general, bp); - - a29k_set_memflags (seq, operands[1]); - emit_insn (seq); - DONE; - } - } -}") - -(define_expand "reload_inhi" - [(parallel [(match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "reload_memory_operand" "m") - (match_operand:PSI 2 "register_operand" "=b")])] - "! TARGET_DW_ENABLE" - " -{ rtx seq = gen_loadhi (gen_lowpart (SImode, operands[0]), - a29k_get_reloaded_address (operands[1]), - gen_rtx (REG, SImode, R_TAV), - operands[2]); - - a29k_set_memflags (seq, operands[1]); - emit_insn (seq); - DONE; -}") - -(define_expand "reload_outhi" - [(parallel [(match_operand:SI 0 "reload_memory_operand" "=m") - (match_operand:SI 1 "register_operand" "m") - (match_operand:PSI 2 "register_operand" "=b")])] - "! TARGET_DW_ENABLE" - " -{ rtx (*fcn) () = TARGET_BYTE_WRITES ? gen_storehihww : gen_storehinhww; - rtx seq = (*fcn) (a29k_get_reloaded_address (operands[0]), - gen_lowpart (SImode, operands[1]), - gen_rtx (REG, SImode, R_TAV), operands[2]); - - a29k_set_memflags (seq, operands[0]); - emit_insn (seq); - DONE; -}") - -;; Subroutines to load/store bytes. Operands 0 and 1 are the output and -;; input, respectively, except that the address is passed for a MEM instead -;; of the MEM itself and the short item is passed in QImode. -;; -;; Operand 2 is a scratch general register and operand 3 is a scratch register -;; used for BP. When called before reload, pseudos are passed for both -;; operands. During reload, R_TAV is used for the general register, and -;; a reload register of class BR_REGS (R_VP) for BP. -;; -;; We have two versions of the store operations, for when byte writes are -;; supported and when they are not. -(define_expand "loadqi" - [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "") - (const_int -4)))) - (set (match_operand:PSI 3 "register_operand" "") - (truncate:PSI (match_dup 1)))]) - (set (match_operand:SI 0 "gpc_reg_operand" "") - (zero_extract:SI (match_dup 2) - (const_int 8) - (ashift:PSI (match_dup 3) (const_int 3))))] - "" - "") - -(define_expand "storeqinhww" - [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "") - (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "") - (const_int -4)))) - (set (match_operand:PSI 3 "register_operand" "") - (truncate:PSI (match_dup 0)))]) - (set (zero_extract:SI (match_dup 2) - (const_int 8) - (ashift:PSI (match_dup 3) - (const_int 3))) - (match_operand:SI 1 "gpc_reg_operand" "")) - (set (mem:SI (match_dup 0)) - (match_dup 2))] - "" - "") - -(define_expand "storeqihww" - [(set (match_operand:PSI 3 "register_operand" "") - (truncate:PSI (match_operand:SI 0 "gpc_reg_operand" ""))) - (set (match_operand:SI 2 "gpc_reg_operand" "") - (ior:SI (and:SI (not:SI (ashift:SI (const_int 255) - (ashift:PSI (match_dup 3) - (const_int 3)))) - (match_operand:SI 1 "gpc_reg_operand" "")) - (ashift:SI (zero_extend:SI (match_dup 4)) - (ashift:PSI (match_dup 3) - (const_int 3))))) - (set (mem:SI (and:SI (match_dup 0) - (const_int -4))) - (match_dup 2))] - "" - " -{ operands[4] = gen_lowpart (QImode, operands[1]); }") - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ if (GET_CODE (operands[0]) == MEM) - { - if (! gpc_reg_operand (operands[1], QImode)) - operands[1] = copy_to_mode_reg (QImode, operands[1]); - if (! TARGET_DW_ENABLE) - { - rtx general = gen_reg_rtx (SImode); - rtx bp = gen_reg_rtx (PSImode); - rtx (*fcn) () - = TARGET_BYTE_WRITES ? gen_storeqihww : gen_storeqinhww; - rtx seq = (*fcn) (XEXP (operands[0], 0), - gen_lowpart (SImode, operands[1]), - general, bp); - - a29k_set_memflags (seq, operands[0]); - emit_insn (seq); - DONE; - } - } - else if (GET_CODE (operands[1]) == MEM) - { - if (! TARGET_DW_ENABLE) - { - rtx general = gen_reg_rtx (SImode); - rtx bp = gen_reg_rtx (PSImode); - rtx seq = gen_loadqi (gen_lowpart (SImode, operands[0]), - XEXP (operands[1], 0), general, bp); - - a29k_set_memflags (seq, operands[1]); - emit_insn (seq); - DONE; - } - } -}") - -(define_expand "reload_inqi" - [(parallel [(match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "reload_memory_operand" "m") - (match_operand:PSI 2 "register_operand" "=b")])] - "! TARGET_DW_ENABLE" - " -{ rtx seq = gen_loadqi (gen_lowpart (SImode, operands[0]), - a29k_get_reloaded_address (operands[1]), - gen_rtx (REG, SImode, R_TAV), - operands[2]); - - a29k_set_memflags (seq, operands[1]); - emit_insn (seq); - DONE; -}") - -(define_expand "reload_outqi" - [(parallel [(match_operand:SI 0 "reload_memory_operand" "=m") - (match_operand:SI 1 "register_operand" "m") - (match_operand:PSI 2 "register_operand" "=b")])] - "! TARGET_DW_ENABLE" - " -{ rtx (*fcn) () = TARGET_BYTE_WRITES ? gen_storeqihww : gen_storeqinhww; - rtx seq = (*fcn) (a29k_get_reloaded_address (operands[0]), - gen_lowpart (SImode, operands[1]), - gen_rtx (REG, SImode, R_TAV), operands[2]); - - a29k_set_memflags (seq, operands[0]); - emit_insn (seq); - DONE; -}") - -;; Now the actual insns used to move data around. We include here the -;; DEFINE_SPLITs that may be needed. In some cases these will be -;; split again. For floating-point, if we can look inside the constant, -;; always split it. This can eliminate unnecessary insns. -(define_insn "" - [(set (match_operand:SF 0 "out_operand" "=r,r,r,r,m") - (match_operand:SF 1 "in_operand" "r,E,F,m,r"))] - "(gpc_reg_operand (operands[0], SFmode) - || gpc_reg_operand (operands[1], SFmode)) - && ! TARGET_29050" - "@ - sll %0,%1,0 - # - const %0,%1\;consth %0,%1 - load 0,0,%0,%1 - store 0,0,%1,%0" - [(set_attr "type" "misc,multi,multi,load,store")]) - -(define_insn "" - [(set (match_operand:SF 0 "out_operand" "=r,r,r,r,m,*a,r") - (match_operand:SF 1 "in_operand" "r,E,F,m,r,r,*a"))] - "(gpc_reg_operand (operands[0], SFmode) - || gpc_reg_operand (operands[1], SFmode)) - && TARGET_29050" - "@ - sll %0,%1,0 - # - const %0,%1\;consth %0,%1 - load 0,0,%0,%1 - store 0,0,%1,%0 - mtacc %1,1,%0 - mfacc %0,1,%1" - [(set_attr "type" "misc,multi,multi,load,store,fadd,fadd")]) - -;; Turn this into SImode. It will then be split up that way. -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "float_const_operand" ""))] - "HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT" - [(set (match_dup 0) - (match_dup 1))] - " -{ operands[0] = operand_subword (operands[0], 0, 0, SFmode); - operands[1] = operand_subword (operands[1], 0, 0, SFmode); - - if (operands[0] == 0 || operands[1] == 0) - FAIL; -}") - -(define_insn "" - [(set (match_operand:DF 0 "out_operand" "=?r,?r,r,m") - (match_operand:DF 1 "in_operand" "rE,F,m,r")) - (clobber (match_scratch:PSI 2 "=X,X,&c,&c"))] - "(gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode)) - && ! TARGET_29050" - "@ - # - const %0,%1\;consth %0,%1\;const %L0,%L1\;consth %L0,%L1 - mtsrim cr,1\;loadm 0,0,%0,%1 - mtsrim cr,1\;storem 0,0,%1,%0" - [(set_attr "type" "multi")]) - -(define_insn "" - [(set (match_operand:DF 0 "out_operand" "=?r,?r,r,m,?*a,?r") - (match_operand:DF 1 "in_operand" "rE,F,m,r,r,*a")) - (clobber (match_scratch:PSI 2 "=X,X,&c,&c,X,X"))] - "(gpc_reg_operand (operands[0], DFmode) - || gpc_reg_operand (operands[1], DFmode)) - && TARGET_29050" - "@ - # - const %0,%1\;consth %0,%1\;const %L0,%L1\;consth %L0,%L1 - mtsrim cr,1\;loadm 0,0,%0,%1 - mtsrim cr,1\;storem 0,0,%1,%0 - mtacc %1,2,%0 - mfacc %0,2,%1" - [(set_attr "type" "multi,multi,multi,multi,fadd,fadd")]) - -;; Split register-register copies and constant loads into two SImode loads, -;; one for each word. In the constant case, they will get further split. -;; Don't so this until register allocation, though, since it will -;; interfere with register allocation. Normally copy the lowest-addressed -;; word first; the exception is if we are copying register to register and -;; the lowest register of the first operand is the highest register of the -;; second operand. -(define_split - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (match_operand:DF 1 "gpc_reg_or_float_constant_operand" "")) - (clobber (match_scratch:PSI 2 ""))] - "reload_completed" - [(set (match_dup 3) (match_dup 4)) - (set (match_dup 5) (match_dup 6))] - " -{ if (GET_CODE (operands[1]) == REG - && REGNO (operands[0]) == REGNO (operands[1]) + 1) - { - operands[3] = operand_subword (operands[0], 1, 1, DFmode); - operands[4] = operand_subword (operands[1], 1, 1, DFmode); - operands[5] = operand_subword (operands[0], 0, 1, DFmode); - operands[6] = operand_subword (operands[1], 0, 1, DFmode); - } - else - { - operands[3] = operand_subword (operands[0], 0, 1, DFmode); - operands[4] = operand_subword (operands[1], 0, 1, DFmode); - operands[5] = operand_subword (operands[0], 1, 1, DFmode); - operands[6] = operand_subword (operands[1], 1, 1, DFmode); - } - - if (operands[3] == 0 || operands[4] == 0 - || operands[5] == 0 || operands[6] == 0) - FAIL; -}") - -;; Split memory loads and stores into the MTSR and LOADM/STOREM. -(define_split - [(set (match_operand:DF 0 "out_operand" "") - (match_operand:DF 1 "in_operand" "")) - (clobber (reg:PSI 179))] - "TARGET_NO_STOREM_BUG - && (memory_operand (operands[0], DFmode) - || memory_operand (operands[1], DFmode))" - [(set (reg:PSI 179) (const_int 1)) - (parallel [(set (match_dup 0) (match_dup 1)) - (use (reg:PSI 179)) - (clobber (reg:PSI 179))])] - "") - -;; DI move is similar to DF move. -(define_insn "" - [(set (match_operand:DI 0 "out_operand" "=?r,r,m") - (match_operand:DI 1 "in_operand" "rn,m,r")) - (clobber (match_scratch:PSI 2 "=X,&c,&c"))] - "(gpc_reg_operand (operands[0], DImode) - || gpc_reg_operand (operands[1], DImode))" - "@ - # - mtsrim cr,1\;loadm 0,0,%0,%1 - mtsrim cr,1\;storem 0,0,%1,%0" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (match_operand:DI 1 "gpc_reg_or_integer_constant_operand" "")) - (clobber (match_scratch:PSI 2 ""))] - "reload_completed" - [(set (match_dup 3) (match_dup 4)) - (set (match_dup 5) (match_dup 6))] - " -{ if (GET_CODE (operands[1]) == REG - && REGNO (operands[0]) == REGNO (operands[1]) + 1) - { - operands[3] = operand_subword (operands[0], 1, 1, DImode); - operands[4] = operand_subword (operands[1], 1, 1, DImode); - operands[5] = operand_subword (operands[0], 0, 1, DImode); - operands[6] = operand_subword (operands[1], 0, 1, DImode); - } - else - { - operands[3] = operand_subword (operands[0], 0, 1, DImode); - operands[4] = operand_subword (operands[1], 0, 1, DImode); - operands[5] = operand_subword (operands[0], 1, 1, DImode); - operands[6] = operand_subword (operands[1], 1, 1, DImode); - } -}") - -(define_split - [(set (match_operand:DI 0 "out_operand" "") - (match_operand:DI 1 "in_operand" "")) - (clobber (reg:PSI 179))] - "TARGET_NO_STOREM_BUG - && (memory_operand (operands[0], DImode) - || memory_operand (operands[1], DImode))" - [(set (reg:PSI 179) (const_int 1)) - (parallel [(set (match_dup 0) (match_dup 1)) - (use (reg:PSI 179)) - (clobber (reg:PSI 179))])] - "") - -;; TImode moves are very similar to DImode moves, except that we can't -;; have constants. -(define_insn "" - [(set (match_operand:TI 0 "out_operand" "=?r,r,m") - (match_operand:TI 1 "in_operand" "r,m,r")) - (clobber (match_scratch:PSI 2 "=X,&c,&c"))] - "(gpc_reg_operand (operands[0], TImode) - || gpc_reg_operand (operands[1], TImode))" - "@ - # - mtsrim cr,3\;loadm 0,0,%0,%1 - mtsrim cr,3\;storem 0,0,%1,%0" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:TI 0 "gpc_reg_operand" "") - (match_operand:TI 1 "gpc_reg_operand" "")) - (clobber (match_scratch:PSI 2 ""))] - "reload_completed" - [(set (match_dup 3) (match_dup 4)) - (set (match_dup 5) (match_dup 6)) - (set (match_dup 7) (match_dup 8)) - (set (match_dup 9) (match_dup 10))] - " -{ - if (REGNO (operands[0]) >= REGNO (operands[1]) + 1 - && REGNO (operands[0]) <= REGNO (operands[1]) + 3) - { - operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3); - operands[4] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3); - operands[5] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2); - operands[6] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); - operands[7] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - operands[8] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - operands[9] = gen_rtx (REG, SImode, REGNO (operands[0])); - operands[10] = gen_rtx (REG, SImode, REGNO (operands[1])); - } - else - { - operands[3] = gen_rtx (REG, SImode, REGNO (operands[0])); - operands[4] = gen_rtx (REG, SImode, REGNO (operands[1])); - operands[5] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - operands[6] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - operands[7] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2); - operands[8] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); - operands[9] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3); - operands[10] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3); - } -}") - -(define_split - [(set (match_operand:TI 0 "out_operand" "") - (match_operand:TI 1 "in_operand" "")) - (clobber (reg:PSI 179))] - "TARGET_NO_STOREM_BUG - && (memory_operand (operands[0], TImode) - || memory_operand (operands[1], TImode))" - [(set (reg:PSI 179) (const_int 3)) - (parallel [(set (match_dup 0) (match_dup 1)) - (use (reg:PSI 179)) - (clobber (reg:PSI 179))])] - "") - -(define_insn "" - [(set (match_operand:SI 0 "out_operand" "=r,r,r,r,r,r,r,m,*h,*h") - (match_operand:SI 1 "in_operand" "r,J,M,O,i,m,*h,r,r,J"))] - "(gpc_reg_operand (operands[0], SImode) - || gpc_reg_operand (operands[1], SImode) - || (spec_reg_operand (operands[0], SImode) - && cint_16_operand (operands[1], SImode))) - && ! TARGET_29050" - "@ - sll %0,%1,0 - const %0,%1 - constn %0,%M1 - cpeq %0,gr1,gr1 - # - load 0,0,%0,%1 - mfsr %0,%1 - store 0,0,%1,%0 - mtsr %0,%1 - mtsrim %0,%1" - [(set_attr "type" "misc,misc,misc,misc,multi,load,misc,store,misc,misc")]) - -(define_insn "" - [(set (match_operand:SI 0 "out_operand" "=r,r,r,r,r,r,r,m,*h,*h") - (match_operand:SI 1 "in_operand" "r,J,M,O,i,m,*h,r,r,J"))] - "(gpc_reg_operand (operands[0], SImode) - || gpc_reg_operand (operands[1], SImode) - || (spec_reg_operand (operands[0], SImode) - && cint_16_operand (operands[1], SImode))) - && TARGET_29050" - "@ - sll %0,%1,0 - const %0,%1 - constn %0,%M1 - consthz %0,%1 - # - load 0,0,%0,%1 - mfsr %0,%1 - store 0,0,%1,%0 - mtsr %0,%1 - mtsrim %0,%1" - [(set_attr "type" "misc,misc,misc,misc,multi,load,misc,store,misc,misc")]) - -(define_insn "" - [(set (match_operand:PSI 0 "out_operand" "=*r,*r,*r,*r,m,h,h") - (match_operand:PSI 1 "in_operand" "r,i,m,h,r,r,J"))] - "(gpc_reg_operand (operands[0], PSImode) - || gpc_reg_operand (operands[1], PSImode) - || (spec_reg_operand (operands[0], PSImode) - && cint_16_operand (operands[1], PSImode)))" - "@ - sll %0,%1,0 - const %0,%1 - load 0,0,%0,%1 - mfsr %0,%1 - store 0,0,%1,%0 - mtsr %0,%1 - mtsrim %0,%1" - [(set_attr "type" "misc,multi,load,misc,store,misc,misc")]) - -(define_insn "" - [(set (match_operand:HI 0 "out_operand" "=r,r,r,m,r,*h,*h") - (match_operand:HI 1 "in_operand" "r,i,m,r,*h,r,i"))] - "gpc_reg_operand (operands[0], HImode) - || gpc_reg_operand (operands[1], HImode) - || (spec_reg_operand (operands[0], HImode) - && cint_16_operand (operands[1], HImode))" - "@ - sll %0,%1,0 - const %0,%1 - load 0,2,%0,%1 - store 0,2,%1,%0 - mfsr %0,%1 - mtsr %0,%1 - mtsrim %0,%1" - [(set_attr "type" "misc,misc,load,store,misc,misc,misc")]) - -(define_insn "" - [(set (match_operand:QI 0 "out_operand" "=r,r,r,m,r,*h,*h") - (match_operand:QI 1 "in_operand" "r,i,m,r,*h,r,i"))] - "gpc_reg_operand (operands[0], QImode) - || gpc_reg_operand (operands[1], QImode) - || (spec_reg_operand (operands[0], HImode) - && cint_16_operand (operands[1], HImode))" - "@ - sll %0,%1,0 - const %0,%1 - load 0,1,%0,%1 - store 0,1,%1,%0 - mfsr %0,%1 - mtsr %0,%1 - mtsrim %0,%1" - [(set_attr "type" "misc,misc,load,store,misc,misc,misc")]) - -;; Define move insns for DI, TI, SF, and DF. -;; -;; In no case do we support mem->mem directly. -;; -;; For DI move of constant to register, split apart at this time since these -;; can require anywhere from 2 to 4 insns and determining which is complex. -;; -;; In other cases, handle similarly to SImode moves. -;; -;; However, indicate that DI, TI, and DF moves may clobber CR (reg 179). -(define_expand "movdi" - [(parallel [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" "")) - (clobber (scratch:PSI))])] - "" - " -{ - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (DImode, operands[1]); -}") - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (SFmode, operands[1]); -}") - -(define_expand "movdf" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" "")) - (clobber (scratch:PSI))])] - "" - " -{ if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (DFmode, operands[1]); -}") - -(define_expand "movti" - [(parallel [(set (match_operand:TI 0 "general_operand" "") - (match_operand:TI 1 "general_operand" "")) - (clobber (scratch:PSI))])] - "" - " -{ - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (TImode, operands[1]); - - /* We can't handle constants in general because there is no rtl to represent - 128 bit constants. Splitting happens to work for CONST_INTs so we split - them for good code. Other constants will get forced to memory. */ - - if (GET_CODE (operands[1]) == CONST_INT) - { - rtx part0, part1, part2, part3; - - part0 = operand_subword (operands[0], 0, 1, TImode); - part1 = operand_subword (operands[0], 1, 1, TImode); - part2 = operand_subword (operands[0], 2, 1, TImode); - part3 = operand_subword (operands[0], 3, 1, TImode); - - emit_move_insn (part0, const0_rtx); - emit_move_insn (part1, const0_rtx); - emit_move_insn (part2, const0_rtx); - emit_move_insn (part3, const0_rtx); - - DONE; - } - else if (CONSTANT_P (operands[1])) - { - operands[1] = force_const_mem (TImode, operands[1]); - if (! memory_address_p (TImode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], TImode, - XEXP (operands[1], 0)); - } -}") - -;; Here are the variants of the above for use during reload. - -(define_expand "reload_indf" - [(parallel [(set (match_operand:DF 0 "register_operand" "=r") - (match_operand:DF 1 "reload_memory_operand" "m")) - (clobber (match_operand:PSI 2 "register_operand" "=&c"))])] - "" - "") - -(define_expand "reload_outdf" - [(parallel [(set (match_operand:DF 0 "reload_memory_operand" "=m") - (match_operand:DF 1 "register_operand" "r")) - (clobber (match_operand:PSI 2 "register_operand" "=&c"))])] - "" - "") - -(define_expand "reload_indi" - [(parallel [(set (match_operand:DI 0 "register_operand" "=r") - (match_operand:DI 1 "reload_memory_operand" "m")) - (clobber (match_operand:PSI 2 "register_operand" "=&c"))])] - "" - "") - -(define_expand "reload_outdi" - [(parallel [(set (match_operand:DI 0 "reload_memory_operand" "=m") - (match_operand:DI 1 "register_operand" "r")) - (clobber (match_operand:PSI 2 "register_operand" "=&c"))])] - "" - "") - -(define_expand "reload_inti" - [(parallel [(set (match_operand:TI 0 "register_operand" "=r") - (match_operand:TI 1 "reload_memory_operand" "m")) - (clobber (match_operand:PSI 2 "register_operand" "=&c"))])] - "" - "") - -(define_expand "reload_outti" - [(parallel [(set (match_operand:TI 0 "reload_memory_operand" "=m") - (match_operand:TI 1 "register_operand" "r")) - (clobber (match_operand:PSI 2 "register_operand" "=&c"))])] - "" - "") - -;; For compare operations, we simply store the comparison operands and -;; do nothing else. The following branch or scc insn will output whatever -;; is needed. -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "gpc_reg_operand" "") - (match_operand:SI 1 "srcb_operand" "")))] - "" - " -{ - a29k_compare_op0 = operands[0]; - a29k_compare_op1 = operands[1]; - a29k_compare_fp_p = 0; - DONE; -}") - -(define_expand "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "gpc_reg_operand" "") - (match_operand:SF 1 "gpc_reg_operand" "")))] - "! TARGET_SOFT_FLOAT" - " -{ - a29k_compare_op0 = operands[0]; - a29k_compare_op1 = operands[1]; - a29k_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_SOFT_FLOAT" - " -{ - a29k_compare_op0 = operands[0]; - a29k_compare_op1 = operands[1]; - a29k_compare_fp_p = 1; - DONE; -}") - -;; We can generate bit-tests better if we use NE instead of EQ, but we -;; don't have an NE for floating-point. So we have to have two patterns -;; for EQ and two for NE. - -(define_expand "beq" - [(set (match_dup 1) (ne:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (a29k_compare_op0)) == MODE_FLOAT) - { - emit_insn (gen_beq_fp (operands[0])); - DONE; - } - - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -(define_expand "beq_fp" - [(set (match_dup 1) (eq:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -(define_expand "bne" - [(set (match_dup 1) (ne:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (GET_MODE_CLASS (GET_MODE (a29k_compare_op0)) == MODE_FLOAT) - { - emit_insn (gen_bne_fp (operands[0])); - DONE; - } - - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -(define_expand "bne_fp" - [(set (match_dup 1) (eq:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -;; We don't have a floating-point "lt" insn, so we have to use "gt" in that -;; case with the operands swapped. The operands must both be registers in -;; the floating-point case, so we know that swapping them is OK. -(define_expand "blt" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - if (a29k_compare_fp_p) - operands[2] = gen_rtx (GT, SImode, a29k_compare_op1, a29k_compare_op0); - else - operands[2] = gen_rtx (LT, SImode, a29k_compare_op0, a29k_compare_op1); -}") - -;; Similarly for "le". -(define_expand "ble" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - if (a29k_compare_fp_p) - operands[2] = gen_rtx (GE, SImode, a29k_compare_op1, a29k_compare_op0); - else - operands[2] = gen_rtx (LE, SImode, a29k_compare_op0, a29k_compare_op1); -}") - -(define_expand "bltu" - [(set (match_dup 1) (ltu:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -(define_expand "bleu" - [(set (match_dup 1) (leu:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -(define_expand "bgt" - [(set (match_dup 1) (gt:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -(define_expand "bge" - [(set (match_dup 1) (ge:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -(define_expand "bgtu" - [(set (match_dup 1) (gtu:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -(define_expand "bgeu" - [(set (match_dup 1) (geu:SI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (SImode); - operands[2] = a29k_compare_op0; - operands[3] = a29k_compare_op1; -}") - -(define_expand "seq" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (eq:SI (match_dup 1) (match_dup 2)))] - "" - " -{ - operands[1] = a29k_compare_op0; - operands[2] = a29k_compare_op1; -}") - -;; This is the most complicated case, because we don't have a floating-point -;; "ne" insn. If integer, handle normally. If floating-point, write the -;; compare and then write an insn to reverse the test. -(define_expand "sne_fp" - [(set (match_dup 3) - (eq:SI (match_operand 1 "gpc_reg_operand" "") - (match_operand 2 "gpc_reg_operand" ""))) - (set (match_operand:SI 0 "gpc_reg_operand" "") - (ge:SI (match_dup 3) (const_int 0)))] - "! TARGET_SOFT_FLOAT" - " -{ operands[3] = gen_reg_rtx (SImode); -}"); - -(define_expand "sne" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (ne:SI (match_dup 1) (match_dup 2)))] - "" - " -{ - operands[1] = a29k_compare_op0; - operands[2] = a29k_compare_op1; - - if (a29k_compare_fp_p) - { - emit_insn (gen_sne_fp (operands[0], operands[1], operands[2])); - DONE; - } -}") - -;; We don't have a floating-point "lt" insn, so use "gt" and swap the -;; operands, the same as we do "blt". -(define_expand "slt" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (a29k_compare_fp_p) - operands[1] = gen_rtx (GT, SImode, a29k_compare_op1, a29k_compare_op0); - else - operands[1] = gen_rtx (LT, SImode, a29k_compare_op0, a29k_compare_op1); -}") - -;; Similarly for "le" -(define_expand "sle" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (match_dup 1))] - "" - " -{ - if (a29k_compare_fp_p) - operands[1] = gen_rtx (GE, SImode, a29k_compare_op1, a29k_compare_op0); - else - operands[1] = gen_rtx (LE, SImode, a29k_compare_op0, a29k_compare_op1); -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (ltu:SI (match_dup 1) (match_dup 2)))] - "" - " -{ - operands[1] = a29k_compare_op0; - operands[2] = a29k_compare_op1; -}") - -(define_expand "sleu" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (leu:SI (match_dup 1) (match_dup 2)))] - "" - " -{ - operands[1] = a29k_compare_op0; - operands[2] = a29k_compare_op1; -}") - -(define_expand "sgt" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (gt:SI (match_dup 1) (match_dup 2)))] - "" - " -{ - operands[1] = a29k_compare_op0; - operands[2] = a29k_compare_op1; -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (ge:SI (match_dup 1) (match_dup 2)))] - "" - " -{ - operands[1] = a29k_compare_op0; - operands[2] = a29k_compare_op1; -}") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (gtu:SI (match_dup 1) (match_dup 2)))] - "" - " -{ - operands[1] = a29k_compare_op0; - operands[2] = a29k_compare_op1; -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (geu:SI (match_dup 1) (match_dup 2)))] - "" - " -{ - operands[1] = a29k_compare_op0; - operands[2] = a29k_compare_op1; -}") - -;; Now define the actual jump insns. -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "branch_operator" - [(match_operand:SI 1 "gpc_reg_operand" "r") - (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "jmp%b0 %1,%l2%#" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "branch_operator" - [(match_operand:SI 1 "gpc_reg_operand" "r") - (const_int 0)]) - (return) - (pc)))] - "null_epilogue ()" - "jmp%b0i %1,lr0%#" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "branch_operator" - [(match_operand:SI 1 "gpc_reg_operand" "r") - (const_int 0)]) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "jmp%B0 %1,%l2%#" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "branch_operator" - [(match_operand:SI 1 "gpc_reg_operand" "r") - (const_int 0)]) - (pc) - (return)))] - "null_epilogue ()" - "jmp%B0i %1,lr0%#" - [(set_attr "type" "branch")]) - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "jmp %e0%E0" - [(set_attr "type" "branch")]) - -(define_insn "return" - [(return)] - "null_epilogue ()" - "jmpi lr0%#" - [(set_attr "type" "branch")]) - -(define_insn "indirect_jump" - [(set (pc) - (match_operand:SI 0 "gpc_reg_operand" "r"))] - "" - "jmpi %0%#" - [(set_attr "type" "branch")]) - -(define_insn "tablejump" - [(set (pc) - (match_operand:SI 0 "gpc_reg_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "" - "jmpi %0%#" - [(set_attr "type" "branch")]) - -;; JMPFDEC -(define_insn "" - [(set (pc) - (if_then_else (ge (match_operand:SI 0 "gpc_reg_operand" "r") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))] - "" - "jmpfdec %0,%l1%#" - [(set_attr "type" "branch")]) diff --git a/gcc/config/a29k/t-a29k b/gcc/config/a29k/t-a29k deleted file mode 100755 index 7468422..0000000 --- a/gcc/config/a29k/t-a29k +++ /dev/null @@ -1,5 +0,0 @@ -LIBGCC1 = -CROSS_LIBGCC1 = - -# We need crt0.o. -LIBGCC1_TEST = diff --git a/gcc/config/a29k/t-a29kbare b/gcc/config/a29k/t-a29kbare deleted file mode 100755 index 21ba24f..0000000 --- a/gcc/config/a29k/t-a29kbare +++ /dev/null @@ -1,19 +0,0 @@ -LIBGCC1 = -CROSS_LIBGCC1 = - -# We need crt0.o. -LIBGCC1_TEST = - -# These are really part of libgcc1, but this will cause them to be -# built correctly, so... - -LIB2FUNCS_EXTRA = fp-bit.c 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/gcc/config/a29k/t-vx29k b/gcc/config/a29k/t-vx29k deleted file mode 100755 index 293674e..0000000 --- a/gcc/config/a29k/t-vx29k +++ /dev/null @@ -1,17 +0,0 @@ -LIBGCC1 = -CROSS_LIBGCC1 = - -# We need crt0.o. -LIBGCC1_TEST = - -# We don't want to put exit in libgcc.a for VxWorks, because VxWorks -# does not have _exit. -TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit -LIB2FUNCS_EXTRA = fp-bit.c 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/gcc/config/a29k/udi.h b/gcc/config/a29k/udi.h deleted file mode 100755 index 400ffbb..0000000 --- a/gcc/config/a29k/udi.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Definitions of target machine for GNU compiler, for AMD Am29000 CPU - running over UDI using COFF. - Copyright (C) 1994, 1996 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Support the ctors and dtors sections for g++. */ - -#define CTORS_SECTION_ASM_OP "\t.use .ctors" -#define DTORS_SECTION_ASM_OP "\t.use .dtors" - -/* A list of other sections which the compiler might be "in" at any - given time. */ - -#undef EXTRA_SECTIONS -#define EXTRA_SECTIONS readonly_data, in_ctors, in_dtors - -/* A list of extra section function definitions. */ - -#undef EXTRA_SECTION_FUNCTIONS -#define EXTRA_SECTION_FUNCTIONS \ - READONLY_DATA_FUNCTION \ - CTORS_SECTION_FUNCTION \ - DTORS_SECTION_FUNCTION - -#define READONLY_DATA_FUNCTION \ -void \ -literal_section () \ -{ \ - if (in_section != readonly_data) \ - { \ - fprintf (asm_out_file, "%s\n", READONLY_DATA_SECTION_ASM_OP); \ - in_section = readonly_data; \ - } \ -} \ - -#define CTORS_SECTION_FUNCTION \ -void \ -ctors_section () \ -{ \ - if (in_section != in_ctors) \ - { \ - fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ - in_section = in_ctors; \ - } \ -} - -#define DTORS_SECTION_FUNCTION \ -void \ -dtors_section () \ -{ \ - if (in_section != in_dtors) \ - { \ - fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ - in_section = in_dtors; \ - } \ -} - -#define INT_ASM_OP ".word" - -/* A C statement (sans semicolon) to output an element in the table of - global constructors. */ -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - ctors_section (); \ - fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - dtors_section (); \ - fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) diff --git a/gcc/config/a29k/unix.h b/gcc/config/a29k/unix.h deleted file mode 100755 index f05f258..0000000 --- a/gcc/config/a29k/unix.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Definitions of target machine for GNU compiler, for AMD Am29000 CPU, Unix. - Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -/* We define unix instead of EPI and define unix-style machine names. */ - -/* Set our default target to be the 29050; that is the more interesting chip - for Unix systems. */ - -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (1+2+16+128) - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dam29k -Da29k -Dam29000 -Asystem(unix) -Acpu(a29k) -Amachine(a29k)" - -#undef CPP_SPEC -#define CPP_SPEC "%{!m29000:-Dam29050 -D__am29050__}" - -/* Use a default linker configuration file. */ -#undef LINK_SPEC -#define LINK_SPEC "-T default.gld%s" - -/* Define the magic numbers that we recognize as COFF. */ - -#define MY_ISCOFF(magic) ((magic) == SIPFBOMAGIC || (magic) == SIPRBOMAGIC) - -/* For some systems, it is best if double-word objects are aligned on a - doubleword boundary. We want to maintain compatibility with MetaWare in - a29k.h, but do not feel constrained to do so here. */ - -#undef BIGGEST_ALIGNMENT -#define BIGGEST_ALIGNMENT 64 - -/* Add shared data as a kludge for now. */ - -#undef ASM_FILE_START -#define ASM_FILE_START(FILE) \ -{ char *p, *after_dir = main_input_filename; \ - if (TARGET_29050) \ - fprintf (FILE, "\t.cputype 29050\n"); \ - for (p = main_input_filename; *p; p++) \ - if (*p == '/') \ - after_dir = p + 1; \ - fprintf (FILE, "\t.file "); \ - output_quoted_string (FILE, after_dir); \ - fprintf (FILE, "\n"); \ - if (flag_shared_data) \ - fprintf (FILE, "\t.sect .shdata,data\n"); \ - fprintf (FILE, "\t.sect .lit,lit\n"); } - -/* Output before shared data. */ - -#define SHARED_SECTION_ASM_OP "\t.use .shdata" - -/* If we want shared data, we have to turn off commons. */ - -#define OVERRIDE_OPTIONS if (flag_shared_data) flag_no_common = 1; - -/* Default to -fno-pcc-struct-return, since we don't have to worry about - compatibility. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -#if 0 /* This would be needed except that the 29k doesn't have strict - alignment requirements. */ - -#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ - (((TYPE) != 0) \ - ? ((TYPE_ALIGN(TYPE) <= PARM_BOUNDARY) \ - ? PARM_BOUNDARY \ - : TYPE_ALIGN(TYPE)) \ - : ((GET_MODE_ALIGNMENT(MODE) <= PARM_BOUNDARY) \ - ? PARM_BOUNDARY \ - : GET_MODE_ALIGNMENT(MODE))) -#endif diff --git a/gcc/config/a29k/vx29k.h b/gcc/config/a29k/vx29k.h deleted file mode 100755 index 8739b1b..0000000 --- a/gcc/config/a29k/vx29k.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Definitions of target machine for GNU compiler. Vxworks 29k version. - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* This file just exists to give specs for the 29k running on VxWorks. */ - -/* Names to predefine in the preprocessor for this target machine. */ - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-D_AM29K -D_AM29000 -Acpu(a29k) -Amachine(a29k) -D__vxworks -D__vxworks_5" - -/* Vxworks header files require that the macro CPU be set. - We could define it in CPP_PREDEFINES, but the value is (or will be) - dependent upon GCC options. */ - -#undef CPP_SPEC -#define CPP_SPEC "-DCPU=AM29200" - -/* VxWorks does all the library stuff itself. */ - -#undef LIB_SPEC -#define LIB_SPEC "" - -/* VxWorks provides the functionality of crt0.o and friends itself. */ - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "crtbegin.o%s" - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend.o%s" diff --git a/gcc/config/a29k/x-unix b/gcc/config/a29k/x-unix deleted file mode 100755 index ed85ea3..0000000 --- a/gcc/config/a29k/x-unix +++ /dev/null @@ -1,2 +0,0 @@ -# Needed for missing functions in Sym1. -CLIB=-liberty -lld diff --git a/gcc/config/a29k/xm-a29k.h b/gcc/config/a29k/xm-a29k.h deleted file mode 100755 index 774e34b..0000000 --- a/gcc/config/a29k/xm-a29k.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Configuration for GNU C-compiler for AMD Am29000 processor. - Copyright (C) 1987, 1988, 1993 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 8 -#define HOST_BITS_PER_SHORT 16 -#define HOST_BITS_PER_INT 32 -#define HOST_BITS_PER_LONG 32 -#define HOST_BITS_PER_LONGLONG 64 - -#define HOST_WORDS_BIG_ENDIAN - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 diff --git a/gcc/config/a29k/xm-unix.h b/gcc/config/a29k/xm-unix.h deleted file mode 100755 index 206d8fd..0000000 --- a/gcc/config/a29k/xm-unix.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Configuration for GNU C-compiler for AMD Am29000 processor. - Copyright (C) 1987, 1988, 1993 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 8 -#define HOST_BITS_PER_SHORT 16 -#define HOST_BITS_PER_INT 32 -#define HOST_BITS_PER_LONG 32 -#define HOST_BITS_PER_LONGLONG 64 - -#define HOST_WORDS_BIG_ENDIAN - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* Ultra is V7, which is closest to USG. */ -#define USG diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c deleted file mode 100755 index 970f1d6..0000000 --- a/gcc/config/alpha/alpha.c +++ /dev/null @@ -1,5101 +0,0 @@ -/* Subroutines used for code generation on the DEC Alpha. - Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -#include "config.h" -#include "system.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "recog.h" -#include "reload.h" -#include "tree.h" -#include "expr.h" -#include "obstack.h" -#include "except.h" -#include "function.h" -#include "toplev.h" - -/* External data. */ -extern char *version_string; -extern int rtx_equal_function_value_matters; - -/* Specify which cpu to schedule for. */ - -enum processor_type alpha_cpu; -static char* const alpha_cpu_name[] = -{ - "ev4", "ev5", "ev6" -}; - -/* Specify how accurate floating-point traps need to be. */ - -enum alpha_trap_precision alpha_tp; - -/* Specify the floating-point rounding mode. */ - -enum alpha_fp_rounding_mode alpha_fprm; - -/* Specify which things cause traps. */ - -enum alpha_fp_trap_mode alpha_fptm; - -/* Strings decoded into the above options. */ - -char *alpha_cpu_string; /* -mcpu= */ -char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */ -char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */ -char *alpha_fptm_string; /* -mfp-trap-mode=[n|u|su|sui] */ -char *alpha_mlat_string; /* -mmemory-latency= */ - -/* Save information from a "cmpxx" operation until the branch or scc is - emitted. */ - -rtx alpha_compare_op0, alpha_compare_op1; -int alpha_compare_fp_p; - -/* Define the information needed to modify the epilogue for EH. */ - -rtx alpha_eh_epilogue_sp_ofs; - -/* Non-zero if inside of a function, because the Alpha asm can't - handle .files inside of functions. */ - -static int inside_function = FALSE; - -/* If non-null, this rtx holds the return address for the function. */ - -static rtx alpha_return_addr_rtx; - -/* The number of cycles of latency we should assume on memory reads. */ - -int alpha_memory_latency = 3; - -/* Whether the function needs the GP. */ - -static int alpha_function_needs_gp; - -/* The alias set for prologue/epilogue register save/restore. */ - -static int alpha_sr_alias_set; - -/* Declarations of static functions. */ -static void alpha_set_memflags_1 - PROTO((rtx, int, int, int)); -static rtx alpha_emit_set_const_1 - PROTO((rtx, enum machine_mode, HOST_WIDE_INT, int)); -static void alpha_expand_unaligned_load_words - PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs)); -static void alpha_expand_unaligned_store_words - PROTO((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs)); -static void alpha_sa_mask - PROTO((unsigned long *imaskP, unsigned long *fmaskP)); -static int alpha_does_function_need_gp - PROTO((void)); - - -/* Get the number of args of a function in one of two ways. */ -#ifdef OPEN_VMS -#define NUM_ARGS current_function_args_info.num_args -#else -#define NUM_ARGS current_function_args_info -#endif - -#define REG_PV 27 -#define REG_RA 26 - -/* Parse target option strings. */ - -void -override_options () -{ - alpha_cpu - = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6 - : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4); - - if (alpha_cpu_string) - { - if (! strcmp (alpha_cpu_string, "ev4") - || ! strcmp (alpha_cpu_string, "21064")) - { - alpha_cpu = PROCESSOR_EV4; - target_flags &= ~ (MASK_BWX | MASK_CIX | MASK_MAX); - } - else if (! strcmp (alpha_cpu_string, "ev5") - || ! strcmp (alpha_cpu_string, "21164")) - { - alpha_cpu = PROCESSOR_EV5; - target_flags &= ~ (MASK_BWX | MASK_CIX | MASK_MAX); - } - else if (! strcmp (alpha_cpu_string, "ev56") - || ! strcmp (alpha_cpu_string, "21164a")) - { - alpha_cpu = PROCESSOR_EV5; - target_flags |= MASK_BWX; - target_flags &= ~ (MASK_CIX | MASK_MAX); - } - else if (! strcmp (alpha_cpu_string, "pca56") - || ! strcmp (alpha_cpu_string, "21164PC") - || ! strcmp (alpha_cpu_string, "21164pc")) - { - alpha_cpu = PROCESSOR_EV5; - target_flags |= MASK_BWX | MASK_MAX; - target_flags &= ~ MASK_CIX; - } - else if (! strcmp (alpha_cpu_string, "ev6") - || ! strcmp (alpha_cpu_string, "21264")) - { - alpha_cpu = PROCESSOR_EV6; - target_flags |= MASK_BWX | MASK_CIX | MASK_MAX; - } - else - error ("bad value `%s' for -mcpu switch", alpha_cpu_string); - } - - alpha_tp = ALPHA_TP_PROG; - alpha_fprm = ALPHA_FPRM_NORM; - alpha_fptm = ALPHA_FPTM_N; - - if (TARGET_IEEE) - { - alpha_tp = ALPHA_TP_INSN; - alpha_fptm = ALPHA_FPTM_SU; - } - - if (TARGET_IEEE_WITH_INEXACT) - { - alpha_tp = ALPHA_TP_INSN; - alpha_fptm = ALPHA_FPTM_SUI; - } - - if (alpha_tp_string) - { - if (! strcmp (alpha_tp_string, "p")) - alpha_tp = ALPHA_TP_PROG; - else if (! strcmp (alpha_tp_string, "f")) - alpha_tp = ALPHA_TP_FUNC; - else if (! strcmp (alpha_tp_string, "i")) - alpha_tp = ALPHA_TP_INSN; - else - error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string); - } - - if (alpha_fprm_string) - { - if (! strcmp (alpha_fprm_string, "n")) - alpha_fprm = ALPHA_FPRM_NORM; - else if (! strcmp (alpha_fprm_string, "m")) - alpha_fprm = ALPHA_FPRM_MINF; - else if (! strcmp (alpha_fprm_string, "c")) - alpha_fprm = ALPHA_FPRM_CHOP; - else if (! strcmp (alpha_fprm_string,"d")) - alpha_fprm = ALPHA_FPRM_DYN; - else - error ("bad value `%s' for -mfp-rounding-mode switch", - alpha_fprm_string); - } - - if (alpha_fptm_string) - { - if (strcmp (alpha_fptm_string, "n") == 0) - alpha_fptm = ALPHA_FPTM_N; - else if (strcmp (alpha_fptm_string, "u") == 0) - alpha_fptm = ALPHA_FPTM_U; - else if (strcmp (alpha_fptm_string, "su") == 0) - alpha_fptm = ALPHA_FPTM_SU; - else if (strcmp (alpha_fptm_string, "sui") == 0) - alpha_fptm = ALPHA_FPTM_SUI; - else - error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string); - } - - /* Do some sanity checks on the above option. */ - - if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI) - && alpha_tp != ALPHA_TP_INSN) - { - warning ("fp software completion requires -mtrap-precision=i"); - alpha_tp = ALPHA_TP_INSN; - } - - if (TARGET_FLOAT_VAX) - { - if (alpha_fprm == ALPHA_FPRM_MINF || alpha_fprm == ALPHA_FPRM_DYN) - { - warning ("rounding mode not supported for VAX floats"); - alpha_fprm = ALPHA_FPRM_NORM; - } - if (alpha_fptm == ALPHA_FPTM_SUI) - { - warning ("trap mode not supported for VAX floats"); - alpha_fptm = ALPHA_FPTM_SU; - } - } - - { - char *end; - int lat; - - if (!alpha_mlat_string) - alpha_mlat_string = "L1"; - - if (ISDIGIT ((unsigned char)alpha_mlat_string[0]) - && (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0')) - ; - else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l') - && ISDIGIT ((unsigned char)alpha_mlat_string[1]) - && alpha_mlat_string[2] == '\0') - { - static int const cache_latency[][4] = - { - { 3, 30, -1 }, /* ev4 -- Bcache is a guess */ - { 2, 12, 38 }, /* ev5 -- Bcache from PC164 LMbench numbers */ - { 3, 13, -1 }, /* ev6 -- Ho hum, doesn't exist yet */ - }; - - lat = alpha_mlat_string[1] - '0'; - if (lat < 0 || lat > 3 || cache_latency[alpha_cpu][lat-1] == -1) - { - warning ("L%d cache latency unknown for %s", - lat, alpha_cpu_name[alpha_cpu]); - lat = 3; - } - else - lat = cache_latency[alpha_cpu][lat-1]; - } - else if (! strcmp (alpha_mlat_string, "main")) - { - /* Most current memories have about 370ns latency. This is - a reasonable guess for a fast cpu. */ - lat = 150; - } - else - { - warning ("bad value `%s' for -mmemory-latency", alpha_mlat_string); - lat = 3; - } - - alpha_memory_latency = lat; - } - - /* Default the definition of "small data" to 8 bytes. */ - if (!g_switch_set) - g_switch_value = 8; - - /* Acquire a unique set number for our register saves and restores. */ - alpha_sr_alias_set = new_alias_set (); -} - -/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */ - -int -zap_mask (value) - HOST_WIDE_INT value; -{ - int i; - - for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; - i++, value >>= 8) - if ((value & 0xff) != 0 && (value & 0xff) != 0xff) - return 0; - - return 1; -} - -/* Returns 1 if OP is either the constant zero or a register. If a - register, it must be in the proper mode unless MODE is VOIDmode. */ - -int -reg_or_0_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - return op == const0_rtx || register_operand (op, mode); -} - -/* Return 1 if OP is a constant in the range of 0-63 (for a shift) or - any register. */ - -int -reg_or_6bit_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - return ((GET_CODE (op) == CONST_INT - && (unsigned HOST_WIDE_INT) INTVAL (op) < 64) - || register_operand (op, mode)); -} - - -/* Return 1 if OP is an 8-bit constant or any register. */ - -int -reg_or_8bit_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - return ((GET_CODE (op) == CONST_INT - && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100) - || register_operand (op, mode)); -} - -/* Return 1 if OP is an 8-bit constant. */ - -int -cint8_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return ((GET_CODE (op) == CONST_INT - && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)); -} - -/* Return 1 if the operand is a valid second operand to an add insn. */ - -int -add_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - /* Constraints I, J, O and P are covered by K. */ - return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K') - || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')); - - return register_operand (op, mode); -} - -/* Return 1 if the operand is a valid second operand to a sign-extending - add insn. */ - -int -sext_add_operand (op, mode) - register 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), 'O')); - - return register_operand (op, mode); -} - -/* Return 1 if OP is the constant 4 or 8. */ - -int -const48_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) == 4 || INTVAL (op) == 8)); -} - -/* Return 1 if OP is a valid first operand to an AND insn. */ - -int -and_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode) - return (zap_mask (CONST_DOUBLE_LOW (op)) - && zap_mask (CONST_DOUBLE_HIGH (op))); - - if (GET_CODE (op) == CONST_INT) - return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100 - || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100 - || zap_mask (INTVAL (op))); - - return register_operand (op, mode); -} - -/* Return 1 if OP is a valid first operand to an IOR or XOR insn. */ - -int -or_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100 - || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100); - - return register_operand (op, mode); -} - -/* Return 1 if OP is a constant that is the width, in bits, of an integral - mode smaller than DImode. */ - -int -mode_width_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) == 8 || INTVAL (op) == 16 - || INTVAL (op) == 32 || INTVAL (op) == 64)); -} - -/* Return 1 if OP is a constant that is the width of an integral machine mode - smaller than an integer. */ - -int -mode_mask_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ -#if HOST_BITS_PER_WIDE_INT == 32 - if (GET_CODE (op) == CONST_DOUBLE) - return (CONST_DOUBLE_LOW (op) == -1 - && (CONST_DOUBLE_HIGH (op) == -1 - || CONST_DOUBLE_HIGH (op) == 0)); -#else - if (GET_CODE (op) == CONST_DOUBLE) - return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0); -#endif - - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) == 0xff - || INTVAL (op) == 0xffff - || INTVAL (op) == (HOST_WIDE_INT)0xffffffff -#if HOST_BITS_PER_WIDE_INT == 64 - || INTVAL (op) == -1 -#endif - )); -} - -/* Return 1 if OP is a multiple of 8 less than 64. */ - -int -mul8_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == CONST_INT - && (unsigned HOST_WIDE_INT) INTVAL (op) < 64 - && (INTVAL (op) & 7) == 0); -} - -/* Return 1 if OP is the constant zero in floating-point. */ - -int -fp0_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - return (GET_MODE (op) == mode - && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode)); -} - -/* Return 1 if OP is the floating-point constant zero or a register. */ - -int -reg_or_fp0_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - return fp0_operand (op, mode) || register_operand (op, mode); -} - -/* Return 1 if OP is a hard floating-point register. */ - -int -hard_fp_register_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - return ((GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == FLOAT_REGS) - || (GET_CODE (op) == SUBREG - && hard_fp_register_operand (SUBREG_REG (op), mode))); -} - -/* Return 1 if OP is a register or a constant integer. */ - - -int -reg_or_cint_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - return (GET_CODE (op) == CONST_INT - || register_operand (op, mode)); -} - -/* Return 1 if OP is something that can be reloaded into a register; - if it is a MEM, it need not be valid. */ - -int -some_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) - return 0; - - switch (GET_CODE (op)) - { - case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF: - case SYMBOL_REF: case CONST: - return 1; - - case SUBREG: - return some_operand (SUBREG_REG (op), VOIDmode); - - default: - break; - } - - return 0; -} - -/* Return 1 if OP is a valid operand for the source of a move insn. */ - -int -input_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) - return 0; - - if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode) - return 0; - - switch (GET_CODE (op)) - { - case LABEL_REF: - case SYMBOL_REF: - case CONST: - /* This handles both the Windows/NT and OSF cases. */ - return mode == ptr_mode || mode == DImode; - - case REG: - return 1; - - case SUBREG: - if (register_operand (op, mode)) - return 1; - /* ... fall through ... */ - case MEM: - return ((TARGET_BWX || (mode != HImode && mode != QImode)) - && general_operand (op, mode)); - - case CONST_DOUBLE: - return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode); - - case CONST_INT: - return mode == QImode || mode == HImode || add_operand (op, mode); - - default: - break; - } - - return 0; -} - -/* Return 1 if OP is a SYMBOL_REF for a function known to be in this - file. */ - -int -current_file_function_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == SYMBOL_REF - && ! profile_flag && ! profile_block_flag - && (SYMBOL_REF_FLAG (op) - || op == XEXP (DECL_RTL (current_function_decl), 0))); -} - -/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */ - -int -call_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode != Pmode) - return 0; - - return (GET_CODE (op) == SYMBOL_REF - || (GET_CODE (op) == REG - && (TARGET_OPEN_VMS || TARGET_WINDOWS_NT || REGNO (op) == 27))); -} - -/* Return 1 if OP is a valid Alpha comparison operator. Here we know which - comparisons are valid in which insn. */ - -int -alpha_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode; -{ - enum rtx_code code = GET_CODE (op); - - if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<') - return 0; - - return (code == EQ || code == LE || code == LT - || (mode == DImode && (code == LEU || code == LTU))); -} - -/* Return 1 if OP is a valid Alpha swapped comparison operator. */ - -int -alpha_swapped_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode; -{ - enum rtx_code code = GET_CODE (op); - - if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<') - return 0; - - code = swap_condition (code); - return (code == EQ || code == LE || code == LT - || (mode == DImode && (code == LEU || code == LTU))); -} - -/* Return 1 if OP is a signed comparison operation. */ - -int -signed_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - switch (GET_CODE (op)) - { - case EQ: case NE: case LE: case LT: case GE: case GT: - return 1; - - default: - break; - } - - return 0; -} - -/* Return 1 if this is a divide or modulus operator. */ - -int -divmod_operator (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - switch (GET_CODE (op)) - { - case DIV: case MOD: case UDIV: case UMOD: - return 1; - - default: - break; - } - - return 0; -} - -/* Return 1 if this memory address is a known aligned register plus - a constant. It must be a valid address. This means that we can do - this as an aligned reference plus some offset. - - Take into account what reload will do. - - We could say that out-of-range stack slots are alignable, but that would - complicate get_aligned_mem and it isn't worth the trouble since few - functions have large stack space. */ - -int -aligned_memory_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == SUBREG) - { - if (GET_MODE (op) != mode) - return 0; - op = SUBREG_REG (op); - mode = GET_MODE (op); - } - - if (reload_in_progress && GET_CODE (op) == REG - && REGNO (op) >= FIRST_PSEUDO_REGISTER) - op = reg_equiv_mem[REGNO (op)]; - - if (GET_CODE (op) != MEM || GET_MODE (op) != mode - || ! memory_address_p (mode, XEXP (op, 0))) - return 0; - - op = XEXP (op, 0); - - if (GET_CODE (op) == PLUS) - op = XEXP (op, 0); - - return (GET_CODE (op) == REG - && REGNO_POINTER_ALIGN (REGNO (op)) >= 4); -} - -/* Similar, but return 1 if OP is a MEM which is not alignable. */ - -int -unaligned_memory_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == SUBREG) - { - if (GET_MODE (op) != mode) - return 0; - op = SUBREG_REG (op); - mode = GET_MODE (op); - } - - if (reload_in_progress && GET_CODE (op) == REG - && REGNO (op) >= FIRST_PSEUDO_REGISTER) - op = reg_equiv_mem[REGNO (op)]; - - if (GET_CODE (op) != MEM || GET_MODE (op) != mode) - return 0; - - op = XEXP (op, 0); - - if (! memory_address_p (mode, op)) - return 1; - - if (GET_CODE (op) == PLUS) - op = XEXP (op, 0); - - return (GET_CODE (op) != REG - || REGNO_POINTER_ALIGN (REGNO (op)) < 4); -} - -/* Return 1 if OP is either a register or an unaligned memory location. */ - -int -reg_or_unaligned_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return register_operand (op, mode) || unaligned_memory_operand (op, mode); -} - -/* Return 1 if OP is any memory location. During reload a pseudo matches. */ - -int -any_memory_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == MEM - || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) - || (reload_in_progress && GET_CODE (op) == REG - && REGNO (op) >= FIRST_PSEUDO_REGISTER) - || (reload_in_progress && GET_CODE (op) == SUBREG - && GET_CODE (SUBREG_REG (op)) == REG - && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)); -} - -/* Returns 1 if OP is not an eliminable register. - - This exists to cure a pathological abort in the s8addq (et al) patterns, - - long foo () { long t; bar(); return (long) &t * 26107; } - - which run afoul of a hack in reload to cure a (presumably) similar - problem with lea-type instructions on other targets. But there is - one of us and many of them, so work around the problem by selectively - preventing combine from making the optimization. */ - -int -reg_not_elim_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - rtx inner = op; - if (GET_CODE (op) == SUBREG) - inner = SUBREG_REG (op); - if (inner == frame_pointer_rtx || inner == arg_pointer_rtx) - return 0; - - return register_operand (op, mode); -} - -/* Return 1 if this function can directly return via $26. */ - -int -direct_return () -{ - return (! TARGET_OPEN_VMS && reload_completed && alpha_sa_size () == 0 - && get_frame_size () == 0 - && current_function_outgoing_args_size == 0 - && current_function_pretend_args_size == 0); -} - -/* REF is an alignable memory location. Place an aligned SImode - reference into *PALIGNED_MEM and the number of bits to shift into - *PBITNUM. */ - -void -get_aligned_mem (ref, paligned_mem, pbitnum) - rtx ref; - rtx *paligned_mem, *pbitnum; -{ - rtx base; - HOST_WIDE_INT offset = 0; - - if (GET_CODE (ref) == SUBREG) - { - offset = SUBREG_WORD (ref) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref))) - - MIN (UNITS_PER_WORD, - GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref))))); - ref = SUBREG_REG (ref); - } - - if (GET_CODE (ref) == REG) - ref = reg_equiv_mem[REGNO (ref)]; - - if (reload_in_progress) - base = find_replacement (&XEXP (ref, 0)); - else - base = XEXP (ref, 0); - - if (GET_CODE (base) == PLUS) - offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0); - - *paligned_mem = gen_rtx_MEM (SImode, plus_constant (base, offset & ~3)); - MEM_COPY_ATTRIBUTES (*paligned_mem, ref); - RTX_UNCHANGING_P (*paligned_mem) = RTX_UNCHANGING_P (ref); - - /* Sadly, we cannot use alias sets here because we may overlap other - data in a different alias set. */ - /* MEM_ALIAS_SET (*paligned_mem) = MEM_ALIAS_SET (ref); */ - - *pbitnum = GEN_INT ((offset & 3) * 8); -} - -/* Similar, but just get the address. Handle the two reload cases. - Add EXTRA_OFFSET to the address we return. */ - -rtx -get_unaligned_address (ref, extra_offset) - rtx ref; - int extra_offset; -{ - rtx base; - HOST_WIDE_INT offset = 0; - - if (GET_CODE (ref) == SUBREG) - { - offset = SUBREG_WORD (ref) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref))) - - MIN (UNITS_PER_WORD, - GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref))))); - ref = SUBREG_REG (ref); - } - - if (GET_CODE (ref) == REG) - ref = reg_equiv_mem[REGNO (ref)]; - - if (reload_in_progress) - base = find_replacement (&XEXP (ref, 0)); - else - base = XEXP (ref, 0); - - if (GET_CODE (base) == PLUS) - offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0); - - return plus_constant (base, offset + extra_offset); -} - -/* Subfunction of the following function. Update the flags of any MEM - found in part of X. */ - -static void -alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) - rtx x; - int in_struct_p, volatile_p, unchanging_p; -{ - int i; - - switch (GET_CODE (x)) - { - case SEQUENCE: - case PARALLEL: - for (i = XVECLEN (x, 0) - 1; i >= 0; i--) - alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p, - unchanging_p); - break; - - case INSN: - alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p, - unchanging_p); - break; - - case SET: - alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p, - unchanging_p); - alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p, - unchanging_p); - break; - - case MEM: - MEM_IN_STRUCT_P (x) = in_struct_p; - MEM_VOLATILE_P (x) = volatile_p; - RTX_UNCHANGING_P (x) = unchanging_p; - /* Sadly, we cannot use alias sets because the extra aliasing - produced by the AND interferes. Given that two-byte quantities - are the only thing we would be able to differentiate anyway, - there does not seem to be any point in convoluting the early - out of the alias check. */ - /* MEM_ALIAS_SET (x) = alias_set; */ - break; - - default: - break; - } -} - -/* Given INSN, which is either an INSN or a SEQUENCE generated to - perform a memory operation, look for any MEMs in either a SET_DEST or - a SET_SRC and copy the in-struct, unchanging, and volatile flags from - REF into each of the MEMs found. If REF is not a MEM, don't do - anything. */ - -void -alpha_set_memflags (insn, ref) - rtx insn; - rtx ref; -{ - int in_struct_p, volatile_p, unchanging_p; - - if (GET_CODE (ref) != MEM) - return; - - in_struct_p = MEM_IN_STRUCT_P (ref); - volatile_p = MEM_VOLATILE_P (ref); - unchanging_p = RTX_UNCHANGING_P (ref); - - /* This is only called from alpha.md, after having had something - generated from one of the insn patterns. So if everything is - zero, the pattern is already up-to-date. */ - if (! in_struct_p && ! volatile_p && ! unchanging_p) - return; - - alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p); -} - -/* 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. Returns the place - where the output has been placed if it can be done and the insns have been - emitted. If it would take more than N insns, zero is returned and no - insns and emitted. */ - -rtx -alpha_emit_set_const (target, mode, c, n) - rtx target; - enum machine_mode mode; - HOST_WIDE_INT c; - int n; -{ - rtx pat; - int i; - - /* Try 1 insn, then 2, then up to N. */ - for (i = 1; i <= n; i++) - if ((pat = alpha_emit_set_const_1 (target, mode, c, i)) != 0) - return pat; - - return 0; -} - -/* Internal routine for the above to check for N or below insns. */ - -static rtx -alpha_emit_set_const_1 (target, mode, c, n) - rtx target; - enum machine_mode mode; - HOST_WIDE_INT c; - int n; -{ - HOST_WIDE_INT new = c; - int i, bits; - /* Use a pseudo if highly optimizing and still generating RTL. */ - rtx subtarget - = (flag_expensive_optimizations && rtx_equal_function_value_matters - ? 0 : target); - rtx temp; - -#if HOST_BITS_PER_WIDE_INT == 64 - /* We are only called for SImode and DImode. If this is SImode, ensure that - we are sign extended to a full word. This does not make any sense when - cross-compiling on a narrow machine. */ - - if (mode == SImode) - c = (c & 0xffffffff) - 2 * (c & 0x80000000); -#endif - - /* If this is a sign-extended 32-bit constant, we can do this in at most - three insns, so do it if we have enough insns left. We always have - a sign-extended 32-bit constant when compiling on a narrow machine. */ - - if (HOST_BITS_PER_WIDE_INT != 64 - || c >> 31 == -1 || c >> 31 == 0) - { - HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000); - HOST_WIDE_INT tmp1 = c - low; - HOST_WIDE_INT high - = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); - HOST_WIDE_INT extra = 0; - - /* If HIGH will be interpreted as negative but the constant is - positive, we must adjust it to do two ldha insns. */ - - if ((high & 0x8000) != 0 && c >= 0) - { - extra = 0x4000; - tmp1 -= 0x40000000; - high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); - } - - if (c == low || (low == 0 && extra == 0)) - { - /* We used to use copy_to_suggested_reg (GEN_INT (c), target, mode) - but that meant that we can't handle INT_MIN on 32-bit machines - (like NT/Alpha), because we recurse indefinitely through - emit_move_insn to gen_movdi. So instead, since we know exactly - what we want, create it explicitly. */ - - if (target == NULL) - target = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c))); - return target; - } - else if (n >= 2 + (extra != 0)) - { - temp = copy_to_suggested_reg (GEN_INT (low), subtarget, mode); - - if (extra != 0) - temp = expand_binop (mode, add_optab, temp, GEN_INT (extra << 16), - subtarget, 0, OPTAB_WIDEN); - - return expand_binop (mode, add_optab, temp, GEN_INT (high << 16), - target, 0, OPTAB_WIDEN); - } - } - - /* If we couldn't do it that way, try some other methods. But if we have - no instructions left, don't bother. Likewise, if this is SImode and - we can't make pseudos, we can't do anything since the expand_binop - and expand_unop calls will widen and try to make pseudos. */ - - if (n == 1 - || (mode == SImode && ! rtx_equal_function_value_matters)) - return 0; - -#if HOST_BITS_PER_WIDE_INT == 64 - /* First, see if can load a value into the target that is the same as the - constant except that all bytes that are 0 are changed to be 0xff. If we - can, then we can do a ZAPNOT to obtain the desired constant. */ - - for (i = 0; i < 64; i += 8) - if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0) - new |= (HOST_WIDE_INT) 0xff << i; - - /* We are only called for SImode and DImode. If this is SImode, ensure that - we are sign extended to a full word. */ - - if (mode == SImode) - new = (new & 0xffffffff) - 2 * (new & 0x80000000); - - if (new != c - && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0) - return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new), - target, 0, OPTAB_WIDEN); -#endif - - /* Next, see if we can load a related constant and then shift and possibly - negate it to get the constant we want. Try this once each increasing - numbers of insns. */ - - for (i = 1; i < n; i++) - { - /* First try complementing. */ - if ((temp = alpha_emit_set_const (subtarget, mode, ~ c, i)) != 0) - return expand_unop (mode, one_cmpl_optab, temp, target, 0); - - /* Next try to form a constant and do a left shift. We can do this - if some low-order bits are zero; the exact_log2 call below tells - us that information. The bits we are shifting out could be any - value, but here we'll just try the 0- and sign-extended forms of - the constant. To try to increase the chance of having the same - constant in more than one insn, start at the highest number of - bits to shift, but try all possibilities in case a ZAPNOT will - be useful. */ - - if ((bits = exact_log2 (c & - c)) > 0) - for (; bits > 0; bits--) - if ((temp = (alpha_emit_set_const - (subtarget, mode, - (unsigned HOST_WIDE_INT) (c >> bits), i))) != 0 - || ((temp = (alpha_emit_set_const - (subtarget, mode, - ((unsigned HOST_WIDE_INT) c) >> bits, i))) - != 0)) - return expand_binop (mode, ashl_optab, temp, GEN_INT (bits), - target, 0, OPTAB_WIDEN); - - /* Now try high-order zero bits. Here we try the shifted-in bits as - all zero and all ones. Be careful to avoid shifting outside the - mode and to avoid shifting outside the host wide int size. */ - /* On narrow hosts, don't shift a 1 into the high bit, since we'll - confuse the recursive call and set all of the high 32 bits. */ - - if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) - - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64))) > 0) - for (; bits > 0; bits--) - if ((temp = alpha_emit_set_const (subtarget, mode, - c << bits, i)) != 0 - || ((temp = (alpha_emit_set_const - (subtarget, mode, - ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)), - i))) - != 0)) - return expand_binop (mode, lshr_optab, temp, GEN_INT (bits), - target, 1, OPTAB_WIDEN); - - /* Now try high-order 1 bits. We get that with a sign-extension. - But one bit isn't enough here. Be careful to avoid shifting outside - the mode and to avoid shifting outside the host wide int size. */ - - if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) - - floor_log2 (~ c) - 2)) > 0) - for (; bits > 0; bits--) - if ((temp = alpha_emit_set_const (subtarget, mode, - c << bits, i)) != 0 - || ((temp = (alpha_emit_set_const - (subtarget, mode, - ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)), - i))) - != 0)) - return expand_binop (mode, ashr_optab, temp, GEN_INT (bits), - target, 0, OPTAB_WIDEN); - } - - return 0; -} - -/* Having failed to find a 3 insn sequence in alpha_emit_set_const, - fall back to a straight forward decomposition. We do this to avoid - exponential run times encountered when looking for longer sequences - with alpha_emit_set_const. */ - -rtx -alpha_emit_set_long_const (target, c1, c2) - rtx target; - HOST_WIDE_INT c1, c2; -{ - HOST_WIDE_INT d1, d2, d3, d4; - - /* Decompose the entire word */ -#if HOST_BITS_PER_WIDE_INT >= 64 - if (c2 != -(c1 < 0)) - abort (); - d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000; - c1 -= d1; - d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000; - c1 = (c1 - d2) >> 32; - d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000; - c1 -= d3; - d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000; - if (c1 != d4) - abort (); -#else - d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000; - c1 -= d1; - d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000; - if (c1 != d2) - abort (); - c2 += (d2 < 0); - d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000; - c2 -= d3; - d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000; - if (c2 != d4) - abort (); -#endif - - /* Construct the high word */ - if (d4) - { - emit_move_insn (target, GEN_INT (d4)); - if (d3) - emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d3))); - } - else - emit_move_insn (target, GEN_INT (d3)); - - /* Shift it into place */ - emit_move_insn (target, gen_rtx_ASHIFT (DImode, target, GEN_INT (32))); - - /* Add in the low bits. */ - if (d2) - emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d2))); - if (d1) - emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d1))); - - return target; -} - -/* Generate the comparison for a conditional branch. */ - -rtx -alpha_emit_conditional_branch (code) - enum rtx_code code; -{ - enum rtx_code cmp_code, branch_code; - enum machine_mode cmp_mode, branch_mode = VOIDmode; - rtx op0 = alpha_compare_op0, op1 = alpha_compare_op1; - rtx tem; - - /* The general case: fold the comparison code to the types of compares - that we have, choosing the branch as necessary. */ - switch (code) - { - case EQ: case LE: case LT: case LEU: case LTU: - /* We have these compares: */ - cmp_code = code, branch_code = NE; - break; - - case NE: - /* This must be reversed. */ - cmp_code = EQ, branch_code = EQ; - break; - - case GE: case GT: case GEU: case GTU: - /* For FP, we swap them, for INT, we reverse them. */ - if (alpha_compare_fp_p) - { - cmp_code = swap_condition (code); - branch_code = NE; - tem = op0, op0 = op1, op1 = tem; - } - else - { - cmp_code = reverse_condition (code); - branch_code = EQ; - } - break; - - default: - abort (); - } - - if (alpha_compare_fp_p) - { - cmp_mode = DFmode; - if (flag_fast_math) - { - /* When we are not as concerned about non-finite values, and we - are comparing against zero, we can branch directly. */ - if (op1 == CONST0_RTX (DFmode)) - cmp_code = NIL, branch_code = code; - else if (op0 == CONST0_RTX (DFmode)) - { - /* Undo the swap we probably did just above. */ - tem = op0, op0 = op1, op1 = tem; - branch_code = swap_condition (cmp_code); - cmp_code = NIL; - } - } - else - { - /* ??? We mark the the branch mode to be CCmode to prevent the - compare and branch from being combined, since the compare - insn follows IEEE rules that the branch does not. */ - branch_mode = CCmode; - } - } - else - { - cmp_mode = DImode; - - /* The following optimizations are only for signed compares. */ - if (code != LEU && code != LTU && code != GEU && code != GTU) - { - /* Whee. Compare and branch against 0 directly. */ - if (op1 == const0_rtx) - cmp_code = NIL, branch_code = code; - - /* We want to use cmpcc/bcc when we can, since there is a zero delay - bypass between logicals and br/cmov on EV5. But we don't want to - force valid immediate constants into registers needlessly. */ - else if (GET_CODE (op1) == CONST_INT) - { - HOST_WIDE_INT v = INTVAL (op1), n = -v; - - if (! CONST_OK_FOR_LETTER_P (v, 'I') - && (CONST_OK_FOR_LETTER_P (n, 'K') - || CONST_OK_FOR_LETTER_P (n, 'L'))) - { - cmp_code = PLUS, branch_code = code; - op1 = GEN_INT (n); - } - } - } - } - - /* Force op0 into a register. */ - if (GET_CODE (op0) != REG) - op0 = force_reg (cmp_mode, op0); - - /* Emit an initial compare instruction, if necessary. */ - tem = op0; - if (cmp_code != NIL) - { - tem = gen_reg_rtx (cmp_mode); - emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1)); - } - - /* Return the branch comparison. */ - return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode)); -} - - -/* Rewrite a comparison against zero CMP of the form - (CODE (cc0) (const_int 0)) so it can be written validly in - a conditional move (if_then_else CMP ...). - If both of the operands that set cc0 are non-zero we must emit - an insn to perform the compare (it can't be done within - the conditional move). */ -rtx -alpha_emit_conditional_move (cmp, mode) - rtx cmp; - enum machine_mode mode; -{ - enum rtx_code code = GET_CODE (cmp); - enum rtx_code cmov_code = NE; - rtx op0 = alpha_compare_op0; - rtx op1 = alpha_compare_op1; - enum machine_mode cmp_mode - = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0)); - enum machine_mode cmp_op_mode = alpha_compare_fp_p ? DFmode : DImode; - enum machine_mode cmov_mode = VOIDmode; - rtx tem; - - if (alpha_compare_fp_p != FLOAT_MODE_P (mode)) - return 0; - - /* We may be able to use a conditional move directly. - This avoids emitting spurious compares. */ - if (signed_comparison_operator (cmp, cmp_op_mode) - && (!alpha_compare_fp_p || flag_fast_math) - && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode))) - return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); - - /* We can't put the comparison insides a conditional move; - emit a compare instruction and put that inside the - conditional move. Make sure we emit only comparisons we have; - swap or reverse as necessary. */ - - switch (code) - { - case EQ: case LE: case LT: case LEU: case LTU: - /* We have these compares: */ - break; - - case NE: - /* This must be reversed. */ - code = reverse_condition (code); - cmov_code = EQ; - break; - - case GE: case GT: case GEU: case GTU: - /* These must be swapped. Make sure the new first operand is in - a register. */ - code = swap_condition (code); - tem = op0, op0 = op1, op1 = tem; - op0 = force_reg (cmp_mode, op0); - break; - - default: - abort (); - } - - /* ??? We mark the branch mode to be CCmode to prevent the compare - and cmov from being combined, since the compare insn follows IEEE - rules that the cmov does not. */ - if (alpha_compare_fp_p && !flag_fast_math) - cmov_mode = CCmode; - - tem = gen_reg_rtx (cmp_op_mode); - emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1)); - return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode)); -} - -/* Use ext[wlq][lh] as the Architecture Handbook describes for extracting - unaligned data: - - unsigned: signed: - word: ldq_u r1,X(r11) ldq_u r1,X(r11) - ldq_u r2,X+1(r11) ldq_u r2,X+1(r11) - lda r3,X(r11) lda r3,X+2(r11) - extwl r1,r3,r1 extql r1,r3,r1 - extwh r2,r3,r2 extqh r2,r3,r2 - or r1.r2.r1 or r1,r2,r1 - sra r1,48,r1 - - long: ldq_u r1,X(r11) ldq_u r1,X(r11) - ldq_u r2,X+3(r11) ldq_u r2,X+3(r11) - lda r3,X(r11) lda r3,X(r11) - extll r1,r3,r1 extll r1,r3,r1 - extlh r2,r3,r2 extlh r2,r3,r2 - or r1.r2.r1 addl r1,r2,r1 - - quad: ldq_u r1,X(r11) - ldq_u r2,X+7(r11) - lda r3,X(r11) - extql r1,r3,r1 - extqh r2,r3,r2 - or r1.r2.r1 -*/ - -void -alpha_expand_unaligned_load (tgt, mem, size, ofs, sign) - rtx tgt, mem; - HOST_WIDE_INT size, ofs; - int sign; -{ - rtx meml, memh, addr, extl, exth; - enum machine_mode mode; - - meml = gen_reg_rtx (DImode); - memh = gen_reg_rtx (DImode); - addr = gen_reg_rtx (DImode); - extl = gen_reg_rtx (DImode); - exth = gen_reg_rtx (DImode); - - emit_move_insn (meml, - change_address (mem, DImode, - gen_rtx_AND (DImode, - plus_constant (XEXP (mem, 0), - ofs), - GEN_INT (-8)))); - - emit_move_insn (memh, - change_address (mem, DImode, - gen_rtx_AND (DImode, - plus_constant (XEXP (mem, 0), - ofs + size - 1), - GEN_INT (-8)))); - - if (sign && size == 2) - { - emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs+2)); - - emit_insn (gen_extxl (extl, meml, GEN_INT (64), addr)); - emit_insn (gen_extqh (exth, memh, addr)); - - /* We must use tgt here for the target. Alpha-vms port fails if we use - addr for the target, because addr is marked as a pointer and combine - knows that pointers are always sign-extended 32 bit values. */ - addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN); - addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (48), - addr, 1, OPTAB_WIDEN); - } - else - { - emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs)); - emit_insn (gen_extxl (extl, meml, GEN_INT (size*8), addr)); - switch (size) - { - case 2: - emit_insn (gen_extwh (exth, memh, addr)); - mode = HImode; - break; - - case 4: - emit_insn (gen_extlh (exth, memh, addr)); - mode = SImode; - break; - - case 8: - emit_insn (gen_extqh (exth, memh, addr)); - mode = DImode; - break; - } - - addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl), - gen_lowpart (mode, exth), gen_lowpart (mode, tgt), - sign, OPTAB_WIDEN); - } - - if (addr != tgt) - emit_move_insn (tgt, gen_lowpart(GET_MODE (tgt), addr)); -} - -/* Similarly, use ins and msk instructions to perform unaligned stores. */ - -void -alpha_expand_unaligned_store (dst, src, size, ofs) - rtx dst, src; - HOST_WIDE_INT size, ofs; -{ - rtx dstl, dsth, addr, insl, insh, meml, memh; - - dstl = gen_reg_rtx (DImode); - dsth = gen_reg_rtx (DImode); - insl = gen_reg_rtx (DImode); - insh = gen_reg_rtx (DImode); - - meml = change_address (dst, DImode, - gen_rtx_AND (DImode, - plus_constant (XEXP (dst, 0), ofs), - GEN_INT (-8))); - memh = change_address (dst, DImode, - gen_rtx_AND (DImode, - plus_constant (XEXP (dst, 0), - ofs+size-1), - GEN_INT (-8))); - - emit_move_insn (dsth, memh); - emit_move_insn (dstl, meml); - addr = copy_addr_to_reg (plus_constant (XEXP (dst, 0), ofs)); - - if (src != const0_rtx) - { - emit_insn (gen_insxh (insh, gen_lowpart (DImode, src), - GEN_INT (size*8), addr)); - - switch (size) - { - case 2: - emit_insn (gen_inswl (insl, gen_lowpart (HImode, src), addr)); - break; - case 4: - emit_insn (gen_insll (insl, gen_lowpart (SImode, src), addr)); - break; - case 8: - emit_insn (gen_insql (insl, src, addr)); - break; - } - } - - emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr)); - - switch (size) - { - case 2: - emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffff), addr)); - break; - case 4: - emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffffffff), addr)); - break; - case 8: - { -#if HOST_BITS_PER_WIDE_INT == 32 - rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode); -#else - rtx msk = immed_double_const (0xffffffffffffffff, 0, DImode); -#endif - emit_insn (gen_mskxl (dstl, dstl, msk, addr)); - } - break; - } - - if (src != const0_rtx) - { - dsth = expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN); - dstl = expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN); - } - - /* Must store high before low for degenerate case of aligned. */ - emit_move_insn (memh, dsth); - emit_move_insn (meml, dstl); -} - -/* The block move code tries to maximize speed by separating loads and - stores at the expense of register pressure: we load all of the data - before we store it back out. There are two secondary effects worth - mentioning, that this speeds copying to/from aligned and unaligned - buffers, and that it makes the code significantly easier to write. */ - -#define MAX_MOVE_WORDS 8 - -/* Load an integral number of consecutive unaligned quadwords. */ - -static void -alpha_expand_unaligned_load_words (out_regs, smem, words, ofs) - rtx *out_regs; - rtx smem; - HOST_WIDE_INT words, ofs; -{ - rtx const im8 = GEN_INT (-8); - rtx const i64 = GEN_INT (64); - rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1]; - rtx sreg, areg; - HOST_WIDE_INT i; - - /* Generate all the tmp registers we need. */ - for (i = 0; i < words; ++i) - { - data_regs[i] = out_regs[i]; - ext_tmps[i] = gen_reg_rtx (DImode); - } - data_regs[words] = gen_reg_rtx (DImode); - - if (ofs != 0) - smem = change_address (smem, GET_MODE (smem), - plus_constant (XEXP (smem, 0), ofs)); - - /* Load up all of the source data. */ - for (i = 0; i < words; ++i) - { - emit_move_insn (data_regs[i], - change_address (smem, DImode, - gen_rtx_AND (DImode, - plus_constant (XEXP(smem,0), - 8*i), - im8))); - } - emit_move_insn (data_regs[words], - change_address (smem, DImode, - gen_rtx_AND (DImode, - plus_constant (XEXP(smem,0), - 8*words - 1), - im8))); - - /* Extract the half-word fragments. Unfortunately DEC decided to make - extxh with offset zero a noop instead of zeroing the register, so - we must take care of that edge condition ourselves with cmov. */ - - sreg = copy_addr_to_reg (XEXP (smem, 0)); - areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL, - 1, OPTAB_WIDEN); - for (i = 0; i < words; ++i) - { - emit_insn (gen_extxl (data_regs[i], data_regs[i], i64, sreg)); - - emit_insn (gen_extqh (ext_tmps[i], data_regs[i+1], sreg)); - emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i], - gen_rtx_IF_THEN_ELSE (DImode, - gen_rtx_EQ (DImode, areg, - const0_rtx), - const0_rtx, ext_tmps[i]))); - } - - /* Merge the half-words into whole words. */ - for (i = 0; i < words; ++i) - { - out_regs[i] = expand_binop (DImode, ior_optab, data_regs[i], - ext_tmps[i], data_regs[i], 1, OPTAB_WIDEN); - } -} - -/* Store an integral number of consecutive unaligned quadwords. DATA_REGS - may be NULL to store zeros. */ - -static void -alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) - rtx *data_regs; - rtx dmem; - HOST_WIDE_INT words, ofs; -{ - rtx const im8 = GEN_INT (-8); - rtx const i64 = GEN_INT (64); -#if HOST_BITS_PER_WIDE_INT == 32 - rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode); -#else - rtx const im1 = immed_double_const (0xffffffffffffffff, 0, DImode); -#endif - rtx ins_tmps[MAX_MOVE_WORDS]; - rtx st_tmp_1, st_tmp_2, dreg; - rtx st_addr_1, st_addr_2; - HOST_WIDE_INT i; - - /* Generate all the tmp registers we need. */ - if (data_regs != NULL) - for (i = 0; i < words; ++i) - ins_tmps[i] = gen_reg_rtx(DImode); - st_tmp_1 = gen_reg_rtx(DImode); - st_tmp_2 = gen_reg_rtx(DImode); - - if (ofs != 0) - dmem = change_address (dmem, GET_MODE (dmem), - plus_constant (XEXP (dmem, 0), ofs)); - - - st_addr_2 = change_address (dmem, DImode, - gen_rtx_AND (DImode, - plus_constant (XEXP(dmem,0), - words*8 - 1), - im8)); - st_addr_1 = change_address (dmem, DImode, - gen_rtx_AND (DImode, - XEXP (dmem, 0), - im8)); - - /* Load up the destination end bits. */ - emit_move_insn (st_tmp_2, st_addr_2); - emit_move_insn (st_tmp_1, st_addr_1); - - /* Shift the input data into place. */ - dreg = copy_addr_to_reg (XEXP (dmem, 0)); - if (data_regs != NULL) - { - for (i = words-1; i >= 0; --i) - { - emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg)); - emit_insn (gen_insql (data_regs[i], data_regs[i], dreg)); - } - for (i = words-1; i > 0; --i) - { - ins_tmps[i-1] = expand_binop (DImode, ior_optab, data_regs[i], - ins_tmps[i-1], ins_tmps[i-1], 1, - OPTAB_WIDEN); - } - } - - /* Split and merge the ends with the destination data. */ - emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg)); - emit_insn (gen_mskxl (st_tmp_1, st_tmp_1, im1, dreg)); - - if (data_regs != NULL) - { - st_tmp_2 = expand_binop (DImode, ior_optab, st_tmp_2, ins_tmps[words-1], - st_tmp_2, 1, OPTAB_WIDEN); - st_tmp_1 = expand_binop (DImode, ior_optab, st_tmp_1, data_regs[0], - st_tmp_1, 1, OPTAB_WIDEN); - } - - /* Store it all. */ - emit_move_insn (st_addr_2, st_tmp_2); - for (i = words-1; i > 0; --i) - { - emit_move_insn (change_address (dmem, DImode, - gen_rtx_AND (DImode, - plus_constant(XEXP (dmem,0), - i*8), - im8)), - data_regs ? ins_tmps[i-1] : const0_rtx); - } - emit_move_insn (st_addr_1, st_tmp_1); -} - - -/* Expand string/block move operations. - - operands[0] is the pointer to the destination. - operands[1] is the pointer to the source. - operands[2] is the number of bytes to move. - operands[3] is the alignment. */ - -int -alpha_expand_block_move (operands) - rtx operands[]; -{ - rtx bytes_rtx = operands[2]; - rtx align_rtx = operands[3]; - HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx); - HOST_WIDE_INT bytes = orig_bytes; - HOST_WIDE_INT src_align = INTVAL (align_rtx); - HOST_WIDE_INT dst_align = src_align; - rtx orig_src = operands[1]; - rtx orig_dst = operands[0]; - rtx data_regs[2*MAX_MOVE_WORDS+16]; - rtx tmp; - int i, words, ofs, nregs = 0; - - if (bytes <= 0) - return 1; - if (bytes > MAX_MOVE_WORDS*8) - return 0; - - /* Look for additional alignment information from recorded register info. */ - - tmp = XEXP (orig_src, 0); - if (GET_CODE (tmp) == REG) - { - if (REGNO_POINTER_ALIGN (REGNO (tmp)) > src_align) - src_align = REGNO_POINTER_ALIGN (REGNO (tmp)); - } - else if (GET_CODE (tmp) == PLUS - && GET_CODE (XEXP (tmp, 0)) == REG - && GET_CODE (XEXP (tmp, 1)) == CONST_INT) - { - HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1)); - int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0))); - - if (a > src_align) - { - if (a >= 8 && c % 8 == 0) - src_align = 8; - else if (a >= 4 && c % 4 == 0) - src_align = 4; - else if (a >= 2 && c % 2 == 0) - src_align = 2; - } - } - - tmp = XEXP (orig_dst, 0); - if (GET_CODE (tmp) == REG) - { - if (REGNO_POINTER_ALIGN (REGNO (tmp)) > dst_align) - dst_align = REGNO_POINTER_ALIGN (REGNO (tmp)); - } - else if (GET_CODE (tmp) == PLUS - && GET_CODE (XEXP (tmp, 0)) == REG - && GET_CODE (XEXP (tmp, 1)) == CONST_INT) - { - HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1)); - int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0))); - - if (a > dst_align) - { - if (a >= 8 && c % 8 == 0) - dst_align = 8; - else if (a >= 4 && c % 4 == 0) - dst_align = 4; - else if (a >= 2 && c % 2 == 0) - dst_align = 2; - } - } - - /* - * Load the entire block into registers. - */ - - if (GET_CODE (XEXP (orig_src, 0)) == ADDRESSOF) - { - enum machine_mode mode; - tmp = XEXP (XEXP (orig_src, 0), 0); - - mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1); - if (mode != BLKmode - && GET_MODE_SIZE (GET_MODE (tmp)) <= bytes) - { - /* Whee! Optimize the load to use the existing register. */ - data_regs[nregs++] = gen_lowpart (mode, tmp); - goto src_done; - } - - /* ??? We could potentially be copying 3 bytes or whatnot from - a wider reg. Probably not worth worrying about. */ - /* No appropriate mode; fall back on memory. */ - orig_src = change_address (orig_src, GET_MODE (orig_src), - copy_addr_to_reg (XEXP (orig_src, 0))); - } - - ofs = 0; - if (src_align >= 8 && bytes >= 8) - { - words = bytes / 8; - - for (i = 0; i < words; ++i) - data_regs[nregs+i] = gen_reg_rtx(DImode); - - for (i = 0; i < words; ++i) - { - emit_move_insn (data_regs[nregs+i], - change_address(orig_src, DImode, - plus_constant (XEXP (orig_src, 0), - ofs + i*8))); - } - - nregs += words; - bytes -= words * 8; - ofs += words * 8; - } - if (src_align >= 4 && bytes >= 4) - { - words = bytes / 4; - - for (i = 0; i < words; ++i) - data_regs[nregs+i] = gen_reg_rtx(SImode); - - for (i = 0; i < words; ++i) - { - emit_move_insn (data_regs[nregs+i], - change_address(orig_src, SImode, - plus_constant (XEXP (orig_src, 0), - ofs + i*4))); - } - - nregs += words; - bytes -= words * 4; - ofs += words * 4; - } - if (bytes >= 16) - { - words = bytes / 8; - - for (i = 0; i < words+1; ++i) - data_regs[nregs+i] = gen_reg_rtx(DImode); - - alpha_expand_unaligned_load_words(data_regs+nregs, orig_src, words, ofs); - - nregs += words; - bytes -= words * 8; - ofs += words * 8; - } - if (!TARGET_BWX && bytes >= 8) - { - data_regs[nregs++] = tmp = gen_reg_rtx (DImode); - alpha_expand_unaligned_load (tmp, orig_src, 8, ofs, 0); - bytes -= 8; - ofs += 8; - } - if (!TARGET_BWX && bytes >= 4) - { - data_regs[nregs++] = tmp = gen_reg_rtx (SImode); - alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0); - bytes -= 4; - ofs += 4; - } - if (bytes >= 2) - { - if (src_align >= 2) - { - do { - data_regs[nregs++] = tmp = gen_reg_rtx (HImode); - emit_move_insn (tmp, - change_address (orig_src, HImode, - plus_constant (XEXP (orig_src, 0), - ofs))); - bytes -= 2; - ofs += 2; - } while (bytes >= 2); - } - else if (!TARGET_BWX) - { - data_regs[nregs++] = tmp = gen_reg_rtx (HImode); - alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0); - bytes -= 2; - ofs += 2; - } - } - while (bytes > 0) - { - data_regs[nregs++] = tmp = gen_reg_rtx (QImode); - emit_move_insn (tmp, - change_address (orig_src, QImode, - plus_constant (XEXP (orig_src, 0), - ofs))); - bytes -= 1; - ofs += 1; - } - src_done: - - if (nregs > (int)(sizeof(data_regs)/sizeof(*data_regs))) - abort(); - - /* - * Now save it back out again. - */ - - i = 0, ofs = 0; - - if (GET_CODE (XEXP (orig_dst, 0)) == ADDRESSOF) - { - enum machine_mode mode; - tmp = XEXP (XEXP (orig_dst, 0), 0); - - mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1); - if (GET_MODE (tmp) == mode && nregs == 1) - { - emit_move_insn (tmp, data_regs[0]); - i = 1; - goto dst_done; - } - - /* ??? If nregs > 1, consider reconstructing the word in regs. */ - /* ??? Optimize mode < dst_mode with strict_low_part. */ - - /* No appropriate mode; fall back on memory. We can speed things - up by recognizing extra alignment information. */ - orig_dst = change_address (orig_dst, GET_MODE (orig_dst), - copy_addr_to_reg (XEXP (orig_dst, 0))); - dst_align = GET_MODE_SIZE (GET_MODE (tmp)); - } - - /* Write out the data in whatever chunks reading the source allowed. */ - if (dst_align >= 8) - { - while (i < nregs && GET_MODE (data_regs[i]) == DImode) - { - emit_move_insn (change_address(orig_dst, DImode, - plus_constant (XEXP (orig_dst, 0), - ofs)), - data_regs[i]); - ofs += 8; - i++; - } - } - if (dst_align >= 4) - { - /* If the source has remaining DImode regs, write them out in - two pieces. */ - while (i < nregs && GET_MODE (data_regs[i]) == DImode) - { - tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32), - NULL_RTX, 1, OPTAB_WIDEN); - - emit_move_insn (change_address(orig_dst, SImode, - plus_constant (XEXP (orig_dst, 0), - ofs)), - gen_lowpart (SImode, data_regs[i])); - emit_move_insn (change_address(orig_dst, SImode, - plus_constant (XEXP (orig_dst, 0), - ofs+4)), - gen_lowpart (SImode, tmp)); - ofs += 8; - i++; - } - - while (i < nregs && GET_MODE (data_regs[i]) == SImode) - { - emit_move_insn (change_address(orig_dst, SImode, - plus_constant (XEXP (orig_dst, 0), - ofs)), - data_regs[i]); - ofs += 4; - i++; - } - } - if (i < nregs && GET_MODE (data_regs[i]) == DImode) - { - /* Write out a remaining block of words using unaligned methods. */ - - for (words = 1; i+words < nregs ; ++words) - if (GET_MODE (data_regs[i+words]) != DImode) - break; - - if (words == 1) - alpha_expand_unaligned_store (orig_dst, data_regs[i], 8, ofs); - else - alpha_expand_unaligned_store_words (data_regs+i, orig_dst, words, ofs); - - i += words; - ofs += words * 8; - } - - /* Due to the above, this won't be aligned. */ - /* ??? If we have more than one of these, consider constructing full - words in registers and using alpha_expand_unaligned_store_words. */ - while (i < nregs && GET_MODE (data_regs[i]) == SImode) - { - alpha_expand_unaligned_store (orig_dst, data_regs[i], 4, ofs); - ofs += 4; - i++; - } - - if (dst_align >= 2) - while (i < nregs && GET_MODE (data_regs[i]) == HImode) - { - emit_move_insn (change_address (orig_dst, HImode, - plus_constant (XEXP (orig_dst, 0), - ofs)), - data_regs[i]); - i++; - ofs += 2; - } - else - while (i < nregs && GET_MODE (data_regs[i]) == HImode) - { - alpha_expand_unaligned_store (orig_dst, data_regs[i], 2, ofs); - i++; - ofs += 2; - } - while (i < nregs && GET_MODE (data_regs[i]) == QImode) - { - emit_move_insn (change_address (orig_dst, QImode, - plus_constant (XEXP (orig_dst, 0), - ofs)), - data_regs[i]); - i++; - ofs += 1; - } - dst_done: - - if (i != nregs) - abort(); - - return 1; -} - -int -alpha_expand_block_clear (operands) - rtx operands[]; -{ - rtx bytes_rtx = operands[1]; - rtx align_rtx = operands[2]; - HOST_WIDE_INT bytes = INTVAL (bytes_rtx); - HOST_WIDE_INT align = INTVAL (align_rtx); - rtx orig_dst = operands[0]; - rtx tmp; - HOST_WIDE_INT i, words, ofs = 0; - - if (bytes <= 0) - return 1; - if (bytes > MAX_MOVE_WORDS*8) - return 0; - - /* Look for stricter alignment. */ - - tmp = XEXP (orig_dst, 0); - if (GET_CODE (tmp) == REG) - { - if (REGNO_POINTER_ALIGN (REGNO (tmp)) > align) - align = REGNO_POINTER_ALIGN (REGNO (tmp)); - } - else if (GET_CODE (tmp) == PLUS - && GET_CODE (XEXP (tmp, 0)) == REG - && GET_CODE (XEXP (tmp, 1)) == CONST_INT) - { - HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1)); - int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0))); - - if (a > align) - { - if (a >= 8 && c % 8 == 0) - align = 8; - else if (a >= 4 && c % 4 == 0) - align = 4; - else if (a >= 2 && c % 2 == 0) - align = 2; - } - } - - /* Handle a block of contiguous words first. */ - - if (align >= 8 && bytes >= 8) - { - words = bytes / 8; - - for (i = 0; i < words; ++i) - { - emit_move_insn (change_address(orig_dst, DImode, - plus_constant (XEXP (orig_dst, 0), - ofs + i*8)), - const0_rtx); - } - - bytes -= words * 8; - ofs += words * 8; - } - if (align >= 4 && bytes >= 4) - { - words = bytes / 4; - - for (i = 0; i < words; ++i) - { - emit_move_insn (change_address(orig_dst, SImode, - plus_constant (XEXP (orig_dst, 0), - ofs + i*4)), - const0_rtx); - } - - bytes -= words * 4; - ofs += words * 4; - } - if (bytes >= 16) - { - words = bytes / 8; - - alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs); - - bytes -= words * 8; - ofs += words * 8; - } - - /* Next clean up any trailing pieces. We know from the contiguous - block move that there are no aligned SImode or DImode hunks left. */ - - if (!TARGET_BWX && bytes >= 8) - { - alpha_expand_unaligned_store (orig_dst, const0_rtx, 8, ofs); - bytes -= 8; - ofs += 8; - } - if (!TARGET_BWX && bytes >= 4) - { - alpha_expand_unaligned_store (orig_dst, const0_rtx, 4, ofs); - bytes -= 4; - ofs += 4; - } - if (bytes >= 2) - { - if (align >= 2) - { - do { - emit_move_insn (change_address (orig_dst, HImode, - plus_constant (XEXP (orig_dst, 0), - ofs)), - const0_rtx); - bytes -= 2; - ofs += 2; - } while (bytes >= 2); - } - else if (!TARGET_BWX) - { - alpha_expand_unaligned_store (orig_dst, const0_rtx, 2, ofs); - bytes -= 2; - ofs += 2; - } - } - while (bytes > 0) - { - emit_move_insn (change_address (orig_dst, QImode, - plus_constant (XEXP (orig_dst, 0), - ofs)), - const0_rtx); - bytes -= 1; - ofs += 1; - } - - return 1; -} - - -/* 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. */ - -int -alpha_adjust_cost (insn, link, dep_insn, cost) - rtx insn; - rtx link; - rtx dep_insn; - int cost; -{ - rtx set, set_src; - enum attr_type insn_type, dep_insn_type; - - /* 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; - - insn_type = get_attr_type (insn); - dep_insn_type = get_attr_type (dep_insn); - - /* Bring in the user-defined memory latency. */ - if (dep_insn_type == TYPE_ILD - || dep_insn_type == TYPE_FLD - || dep_insn_type == TYPE_LDSYM) - cost += alpha_memory_latency-1; - - switch (alpha_cpu) - { - case PROCESSOR_EV4: - /* On EV4, if INSN is a store insn and DEP_INSN is setting the data - being stored, we can sometimes lower the cost. */ - - if ((insn_type == TYPE_IST || insn_type == TYPE_FST) - && (set = single_set (dep_insn)) != 0 - && GET_CODE (PATTERN (insn)) == SET - && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn)))) - { - switch (dep_insn_type) - { - case TYPE_ILD: - case TYPE_FLD: - /* No savings here. */ - return cost; - - case TYPE_IMUL: - /* In these cases, we save one cycle. */ - return cost - 1; - - default: - /* In all other cases, we save two cycles. */ - return MAX (0, cost - 2); - } - } - - /* Another case that needs adjustment is an arithmetic or logical - operation. It's cost is usually one cycle, but we default it to - two in the MD file. The only case that it is actually two is - for the address in loads, stores, and jumps. */ - - if (dep_insn_type == TYPE_IADD || dep_insn_type == TYPE_ILOG) - { - switch (insn_type) - { - case TYPE_ILD: - case TYPE_IST: - case TYPE_FLD: - case TYPE_FST: - case TYPE_JSR: - return cost; - default: - return 1; - } - } - - /* The final case is when a compare feeds into an integer branch; - the cost is only one cycle in that case. */ - - if (dep_insn_type == TYPE_ICMP && insn_type == TYPE_IBR) - return 1; - break; - - case PROCESSOR_EV5: - /* And the lord DEC saith: "A special bypass provides an effective - latency of 0 cycles for an ICMP or ILOG insn producing the test - operand of an IBR or ICMOV insn." */ - - if ((dep_insn_type == TYPE_ICMP || dep_insn_type == TYPE_ILOG) - && (set = single_set (dep_insn)) != 0) - { - /* A branch only has one input. This must be it. */ - if (insn_type == TYPE_IBR) - return 0; - /* A conditional move has three, make sure it is the test. */ - if (insn_type == TYPE_ICMOV - && GET_CODE (set_src = PATTERN (insn)) == SET - && GET_CODE (set_src = SET_SRC (set_src)) == IF_THEN_ELSE - && rtx_equal_p (SET_DEST (set), XEXP (set_src, 0))) - return 0; - } - - /* "The multiplier is unable to receive data from IEU bypass paths. - The instruction issues at the expected time, but its latency is - increased by the time it takes for the input data to become - available to the multiplier" -- which happens in pipeline stage - six, when results are comitted to the register file. */ - - if (insn_type == TYPE_IMUL) - { - switch (dep_insn_type) - { - /* These insns produce their results in pipeline stage five. */ - case TYPE_ILD: - case TYPE_ICMOV: - case TYPE_IMUL: - case TYPE_MVI: - return cost + 1; - - /* Other integer insns produce results in pipeline stage four. */ - default: - return cost + 2; - } - } - break; - - case PROCESSOR_EV6: - /* There is additional latency to move the result of (most) FP - operations anywhere but the FP register file. */ - - if ((insn_type == TYPE_FST || insn_type == TYPE_FTOI) - && (dep_insn_type == TYPE_FADD || - dep_insn_type == TYPE_FMUL || - dep_insn_type == TYPE_FCMOV)) - return cost + 2; - - break; - } - - /* Otherwise, return the default cost. */ - return cost; -} - -/* Functions to save and restore alpha_return_addr_rtx. */ - -struct machine_function -{ - rtx ra_rtx; -}; - -static void -alpha_save_machine_status (p) - struct function *p; -{ - struct machine_function *machine = - (struct machine_function *) xmalloc (sizeof (struct machine_function)); - - p->machine = machine; - machine->ra_rtx = alpha_return_addr_rtx; -} - -static void -alpha_restore_machine_status (p) - struct function *p; -{ - struct machine_function *machine = p->machine; - - alpha_return_addr_rtx = machine->ra_rtx; - - free (machine); - p->machine = (struct machine_function *)0; -} - -/* Do anything needed before RTL is emitted for each function. */ - -void -alpha_init_expanders () -{ - alpha_return_addr_rtx = NULL_RTX; - alpha_eh_epilogue_sp_ofs = NULL_RTX; - - /* Arrange to save and restore machine status around nested functions. */ - save_machine_status = alpha_save_machine_status; - restore_machine_status = alpha_restore_machine_status; -} - -/* Start the ball rolling with RETURN_ADDR_RTX. */ - -rtx -alpha_return_addr (count, frame) - int count; - rtx frame ATTRIBUTE_UNUSED; -{ - rtx init; - - if (count != 0) - return const0_rtx; - - if (alpha_return_addr_rtx) - return alpha_return_addr_rtx; - - /* No rtx yet. Invent one, and initialize it from $26 in the prologue. */ - alpha_return_addr_rtx = gen_reg_rtx (Pmode); - init = gen_rtx_SET (VOIDmode, alpha_return_addr_rtx, - gen_rtx_REG (Pmode, REG_RA)); - - /* Emit the insn to the prologue with the other argument copies. */ - push_topmost_sequence (); - emit_insn_after (init, get_insns ()); - pop_topmost_sequence (); - - return alpha_return_addr_rtx; -} - -static int -alpha_ra_ever_killed () -{ - rtx top; - -#ifdef ASM_OUTPUT_MI_THUNK - if (current_function_is_thunk) - return 0; -#endif - if (!alpha_return_addr_rtx) - return regs_ever_live[REG_RA]; - - push_topmost_sequence (); - top = get_insns (); - pop_topmost_sequence (); - - return reg_set_between_p (gen_rtx_REG (Pmode, REG_RA), top, NULL_RTX); -} - - -/* Print an operand. Recognize special options, documented below. */ - -void -print_operand (file, x, code) - FILE *file; - rtx x; - char code; -{ - int i; - - switch (code) - { - case '&': - /* Generates fp-rounding mode suffix: nothing for normal, 'c' for - chopped, 'm' for minus-infinity, and 'd' for dynamic rounding - mode. alpha_fprm controls which suffix is generated. */ - switch (alpha_fprm) - { - case ALPHA_FPRM_NORM: - break; - case ALPHA_FPRM_MINF: - fputc ('m', file); - break; - case ALPHA_FPRM_CHOP: - fputc ('c', file); - break; - case ALPHA_FPRM_DYN: - fputc ('d', file); - break; - } - break; - - case '\'': - /* Generates trap-mode suffix for instructions that accept the su - suffix only (cmpt et al). */ - if (alpha_tp == ALPHA_TP_INSN) - fputs ("su", file); - break; - - case '`': - /* Generates trap-mode suffix for instructions that accept the - v and sv suffix. The only instruction that needs this is cvtql. */ - switch (alpha_fptm) - { - case ALPHA_FPTM_N: - break; - case ALPHA_FPTM_U: - fputs ("v", file); - break; - case ALPHA_FPTM_SU: - case ALPHA_FPTM_SUI: - fputs ("sv", file); - break; - } - break; - - case '(': - /* Generates trap-mode suffix for instructions that accept the - v, sv, and svi suffix. The only instruction that needs this - is cvttq. */ - switch (alpha_fptm) - { - case ALPHA_FPTM_N: - break; - case ALPHA_FPTM_U: - fputs ("v", file); - break; - case ALPHA_FPTM_SU: - fputs ("sv", file); - break; - case ALPHA_FPTM_SUI: - fputs ("svi", file); - break; - } - break; - - case ')': - /* Generates trap-mode suffix for instructions that accept the u, su, - and sui suffix. This is the bulk of the IEEE floating point - instructions (addt et al). */ - switch (alpha_fptm) - { - case ALPHA_FPTM_N: - break; - case ALPHA_FPTM_U: - fputc ('u', file); - break; - case ALPHA_FPTM_SU: - fputs ("su", file); - break; - case ALPHA_FPTM_SUI: - fputs ("sui", file); - break; - } - break; - - case '+': - /* Generates trap-mode suffix for instructions that accept the sui - suffix (cvtqt and cvtqs). */ - switch (alpha_fptm) - { - case ALPHA_FPTM_N: - case ALPHA_FPTM_U: - case ALPHA_FPTM_SU: /* cvtqt/cvtqs can't cause underflow */ - break; - case ALPHA_FPTM_SUI: - fputs ("sui", file); - break; - } - break; - - case ',': - /* Generates single precision instruction suffix. */ - fprintf (file, "%c", (TARGET_FLOAT_VAX ? 'f' : 's')); - break; - - case '-': - /* Generates double precision instruction suffix. */ - fprintf (file, "%c", (TARGET_FLOAT_VAX ? 'g' : 't')); - break; - - case 'r': - /* If this operand is the constant zero, write it as "$31". */ - if (GET_CODE (x) == REG) - fprintf (file, "%s", reg_names[REGNO (x)]); - else if (x == CONST0_RTX (GET_MODE (x))) - fprintf (file, "$31"); - else - output_operand_lossage ("invalid %%r value"); - - break; - - case 'R': - /* Similar, but for floating-point. */ - if (GET_CODE (x) == REG) - fprintf (file, "%s", reg_names[REGNO (x)]); - else if (x == CONST0_RTX (GET_MODE (x))) - fprintf (file, "$f31"); - else - output_operand_lossage ("invalid %%R value"); - - break; - - case 'N': - /* Write the 1's complement of a constant. */ - if (GET_CODE (x) != CONST_INT) - output_operand_lossage ("invalid %%N value"); - - fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (x)); - break; - - case 'P': - /* Write 1 << C, for a constant C. */ - if (GET_CODE (x) != CONST_INT) - output_operand_lossage ("invalid %%P value"); - - fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) 1 << INTVAL (x)); - break; - - case 'h': - /* Write the high-order 16 bits of a constant, sign-extended. */ - if (GET_CODE (x) != CONST_INT) - output_operand_lossage ("invalid %%h value"); - - fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) >> 16); - break; - - case 'L': - /* Write the low-order 16 bits of a constant, sign-extended. */ - if (GET_CODE (x) != CONST_INT) - output_operand_lossage ("invalid %%L value"); - - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000)); - break; - - case 'm': - /* Write mask for ZAP insn. */ - if (GET_CODE (x) == CONST_DOUBLE) - { - HOST_WIDE_INT mask = 0; - HOST_WIDE_INT value; - - value = CONST_DOUBLE_LOW (x); - for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; - i++, value >>= 8) - if (value & 0xff) - mask |= (1 << i); - - value = CONST_DOUBLE_HIGH (x); - for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; - i++, value >>= 8) - if (value & 0xff) - mask |= (1 << (i + sizeof (int))); - - fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask & 0xff); - } - - else if (GET_CODE (x) == CONST_INT) - { - HOST_WIDE_INT mask = 0, value = INTVAL (x); - - for (i = 0; i < 8; i++, value >>= 8) - if (value & 0xff) - mask |= (1 << i); - - fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask); - } - else - output_operand_lossage ("invalid %%m value"); - break; - - case 'M': - /* 'b', 'w', 'l', or 'q' as the value of the constant. */ - if (GET_CODE (x) != CONST_INT - || (INTVAL (x) != 8 && INTVAL (x) != 16 - && INTVAL (x) != 32 && INTVAL (x) != 64)) - output_operand_lossage ("invalid %%M value"); - - fprintf (file, "%s", - (INTVAL (x) == 8 ? "b" - : INTVAL (x) == 16 ? "w" - : INTVAL (x) == 32 ? "l" - : "q")); - break; - - case 'U': - /* Similar, except do it from the mask. */ - if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff) - fprintf (file, "b"); - else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff) - fprintf (file, "w"); - else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff) - fprintf (file, "l"); -#if HOST_BITS_PER_WIDE_INT == 32 - else if (GET_CODE (x) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (x) == 0 - && CONST_DOUBLE_LOW (x) == -1) - fprintf (file, "l"); - else if (GET_CODE (x) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (x) == -1 - && CONST_DOUBLE_LOW (x) == -1) - fprintf (file, "q"); -#else - else if (GET_CODE (x) == CONST_INT && INTVAL (x) == -1) - fprintf (file, "q"); - else if (GET_CODE (x) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (x) == 0 - && CONST_DOUBLE_LOW (x) == -1) - fprintf (file, "q"); -#endif - else - output_operand_lossage ("invalid %%U value"); - break; - - case 's': - /* Write the constant value divided by 8. */ - if (GET_CODE (x) != CONST_INT - && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64 - && (INTVAL (x) & 7) != 8) - output_operand_lossage ("invalid %%s value"); - - fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) / 8); - break; - - case 'S': - /* Same, except compute (64 - c) / 8 */ - - if (GET_CODE (x) != CONST_INT - && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64 - && (INTVAL (x) & 7) != 8) - output_operand_lossage ("invalid %%s value"); - - fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8); - break; - - case 'C': case 'D': case 'c': case 'd': - /* Write out comparison name. */ - { - enum rtx_code c = GET_CODE (x); - - if (GET_RTX_CLASS (c) != '<') - output_operand_lossage ("invalid %%C value"); - - if (code == 'D') - c = reverse_condition (c); - else if (code == 'c') - c = swap_condition (c); - else if (code == 'd') - c = swap_condition (reverse_condition (c)); - - if (c == LEU) - fprintf (file, "ule"); - else if (c == LTU) - fprintf (file, "ult"); - else - fprintf (file, "%s", GET_RTX_NAME (c)); - } - break; - - case 'E': - /* Write the divide or modulus operator. */ - switch (GET_CODE (x)) - { - case DIV: - fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q"); - break; - case UDIV: - fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q"); - break; - case MOD: - fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q"); - break; - case UMOD: - fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q"); - break; - default: - output_operand_lossage ("invalid %%E value"); - break; - } - break; - - case 'A': - /* Write "_u" for unaligned access. */ - if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND) - fprintf (file, "_u"); - break; - - case 0: - if (GET_CODE (x) == REG) - fprintf (file, "%s", reg_names[REGNO (x)]); - else if (GET_CODE (x) == MEM) - output_address (XEXP (x, 0)); - else - output_addr_const (file, x); - break; - - default: - output_operand_lossage ("invalid %%xn code"); - } -} - -/* Emit RTL insns to initialize the variable parts of a trampoline at - TRAMP. 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. - - The three offset parameters are for the individual template's - layout. A JMPOFS < 0 indicates that the trampoline does not - contain instructions at all. - - We assume here that a function will be called many more times than - its address is taken (e.g., it might be passed to qsort), so we - take the trouble to initialize the "hint" field in the JMP insn. - Note that the hint field is PC (new) + 4 * bits 13:0. */ - -void -alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs) - rtx tramp, fnaddr, cxt; - int fnofs, cxtofs, jmpofs; -{ - rtx temp, temp1, addr; - /* ??? Something is wrong with VMS codegen in that we get aborts when - using ptr_mode. Hack around it for now. */ - enum machine_mode mode = TARGET_OPEN_VMS ? Pmode : ptr_mode; - - /* Store function address and CXT. */ - addr = memory_address (mode, plus_constant (tramp, fnofs)); - emit_move_insn (gen_rtx (MEM, mode, addr), fnaddr); - addr = memory_address (mode, plus_constant (tramp, cxtofs)); - emit_move_insn (gen_rtx (MEM, mode, addr), cxt); - - /* This has been disabled since the hint only has a 32k range, and in - no existing OS is the stack within 32k of the text segment. */ - if (0 && jmpofs >= 0) - { - /* Compute hint value. */ - temp = force_operand (plus_constant (tramp, jmpofs+4), NULL_RTX); - temp = expand_binop (DImode, sub_optab, fnaddr, temp, temp, 1, - OPTAB_WIDEN); - temp = expand_shift (RSHIFT_EXPR, Pmode, temp, - build_int_2 (2, 0), NULL_RTX, 1); - temp = expand_and (gen_lowpart (SImode, temp), GEN_INT (0x3fff), 0); - - /* Merge in the hint. */ - addr = memory_address (SImode, plus_constant (tramp, jmpofs)); - temp1 = force_reg (SImode, gen_rtx (MEM, SImode, addr)); - temp1 = expand_and (temp1, GEN_INT (0xffffc000), NULL_RTX); - temp1 = expand_binop (SImode, ior_optab, temp1, temp, temp1, 1, - OPTAB_WIDEN); - emit_move_insn (gen_rtx (MEM, SImode, addr), temp1); - } - -#ifdef TRANSFER_FROM_TRAMPOLINE - emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"), - 0, VOIDmode, 1, addr, Pmode); -#endif - - if (jmpofs >= 0) - emit_insn (gen_imb ()); -} - -/* Do what is necessary for `va_start'. The argument is ignored; - We look at the current function to determine if stdarg or varargs - is used and fill in an initial va_list. A pointer to this constructor - is returned. */ - -struct rtx_def * -alpha_builtin_saveregs (arglist) - tree arglist ATTRIBUTE_UNUSED; -{ - rtx block, addr, dest, argsize; - tree fntype = TREE_TYPE (current_function_decl); - int stdarg = (TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) - != void_type_node)); - - /* Compute the current position into the args, taking into account - both registers and memory. Both of these are already included in - NUM_ARGS. */ - - argsize = GEN_INT (NUM_ARGS * UNITS_PER_WORD); - - /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base up by 48, - storing fp arg registers in the first 48 bytes, and the integer arg - registers in the next 48 bytes. This is only done, however, if any - integer registers need to be stored. - - If no integer registers need be stored, then we must subtract 48 in - order to account for the integer arg registers which are counted in - argsize above, but which are not actually stored on the stack. */ - - if (TARGET_OPEN_VMS) - addr = plus_constant (virtual_incoming_args_rtx, - NUM_ARGS <= 5 + stdarg - ? UNITS_PER_WORD : - 6 * UNITS_PER_WORD); - else - addr = (NUM_ARGS <= 5 + stdarg - ? plus_constant (virtual_incoming_args_rtx, - 6 * UNITS_PER_WORD) - : plus_constant (virtual_incoming_args_rtx, - - (6 * UNITS_PER_WORD))); - - /* For VMS, we include the argsize, while on Unix, it's handled as - a separate field. */ - if (TARGET_OPEN_VMS) - addr = plus_constant (addr, INTVAL (argsize)); - - addr = force_operand (addr, NULL_RTX); - -#ifdef POINTERS_EXTEND_UNSIGNED - addr = convert_memory_address (ptr_mode, addr); -#endif - - if (TARGET_OPEN_VMS) - return addr; - else - { - /* Allocate the va_list constructor */ - block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD); - RTX_UNCHANGING_P (block) = 1; - RTX_UNCHANGING_P (XEXP (block, 0)) = 1; - - /* Store the address of the first integer register in the __base - member. */ - - dest = change_address (block, ptr_mode, XEXP (block, 0)); - emit_move_insn (dest, addr); - - if (current_function_check_memory_usage) - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - dest, ptr_mode, - GEN_INT (GET_MODE_SIZE (ptr_mode)), - TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - - /* Store the argsize as the __va_offset member. */ - dest = change_address (block, TYPE_MODE (integer_type_node), - plus_constant (XEXP (block, 0), - POINTER_SIZE/BITS_PER_UNIT)); - emit_move_insn (dest, argsize); - - if (current_function_check_memory_usage) - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - dest, ptr_mode, - GEN_INT (GET_MODE_SIZE - (TYPE_MODE (integer_type_node))), - TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - - /* Return the address of the va_list constructor, but don't put it in a - register. Doing so would fail when not optimizing and produce worse - code when optimizing. */ - return XEXP (block, 0); - } -} - -/* This page contains routines that are used to determine what the function - prologue and epilogue code will do and write them out. */ - -/* Compute the size of the save area in the stack. */ - -/* These variables are used for communication between the following functions. - They indicate various things about the current function being compiled - that are used to tell what kind of prologue, epilogue and procedure - descriptior to generate. */ - -/* Nonzero if we need a stack procedure. */ -static int vms_is_stack_procedure; - -/* Register number (either FP or SP) that is used to unwind the frame. */ -static int vms_unwind_regno; - -/* Register number used to save FP. We need not have one for RA since - we don't modify it for register procedures. This is only defined - for register frame procedures. */ -static int vms_save_fp_regno; - -/* Register number used to reference objects off our PV. */ -static int vms_base_regno; - -/* Compute register masks for saved registers. */ - -static void -alpha_sa_mask (imaskP, fmaskP) - unsigned long *imaskP; - unsigned long *fmaskP; -{ - unsigned long imask = 0; - unsigned long fmask = 0; - int i; - -#ifdef ASM_OUTPUT_MI_THUNK - if (!current_function_is_thunk) -#endif - { - if (TARGET_OPEN_VMS && vms_is_stack_procedure) - imask |= (1L << HARD_FRAME_POINTER_REGNUM); - - /* One for every register we have to save. */ - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (! fixed_regs[i] && ! call_used_regs[i] - && regs_ever_live[i] && i != REG_RA) - { - if (i < 32) - imask |= (1L << i); - else - fmask |= (1L << (i - 32)); - } - - if (imask || fmask || alpha_ra_ever_killed ()) - imask |= (1L << REG_RA); - } - - *imaskP = imask; - *fmaskP = fmask; -} - -int -alpha_sa_size () -{ - int sa_size = 0; - int i; - -#ifdef ASM_OUTPUT_MI_THUNK - if (current_function_is_thunk) - sa_size = 0; - else -#endif - { - /* One for every register we have to save. */ - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (! fixed_regs[i] && ! call_used_regs[i] - && regs_ever_live[i] && i != REG_RA) - sa_size++; - } - - if (TARGET_OPEN_VMS) - { - /* Start by assuming we can use a register procedure if we don't - make any calls (REG_RA not used) or need to save any - registers and a stack procedure if we do. */ - vms_is_stack_procedure = sa_size != 0 || alpha_ra_ever_killed (); - - /* Decide whether to refer to objects off our PV via FP or PV. - If we need FP for something else or if we receive a nonlocal - goto (which expects PV to contain the value), we must use PV. - Otherwise, start by assuming we can use FP. */ - vms_base_regno = (frame_pointer_needed - || current_function_has_nonlocal_label - || vms_is_stack_procedure - || current_function_outgoing_args_size - ? REG_PV : HARD_FRAME_POINTER_REGNUM); - - /* If we want to copy PV into FP, we need to find some register - in which to save FP. */ - - vms_save_fp_regno = -1; - if (vms_base_regno == HARD_FRAME_POINTER_REGNUM) - for (i = 0; i < 32; i++) - if (! fixed_regs[i] && call_used_regs[i] && ! regs_ever_live[i]) - vms_save_fp_regno = i; - - if (vms_save_fp_regno == -1) - vms_base_regno = REG_PV, vms_is_stack_procedure = 1; - - /* Stack unwinding should be done via FP unless we use it for PV. */ - vms_unwind_regno = (vms_base_regno == REG_PV - ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); - - /* If this is a stack procedure, allow space for saving FP and RA. */ - if (vms_is_stack_procedure) - sa_size += 2; - } - else - { - /* If some registers were saved but not RA, RA must also be saved, - so leave space for it. */ - if (sa_size != 0 || alpha_ra_ever_killed ()) - sa_size++; - - /* Our size must be even (multiple of 16 bytes). */ - if (sa_size & 1) - sa_size++; - } - - return sa_size * 8; -} - -int -alpha_pv_save_size () -{ - alpha_sa_size (); - return vms_is_stack_procedure ? 8 : 0; -} - -int -alpha_using_fp () -{ - alpha_sa_size (); - return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM; -} - -int -vms_valid_decl_attribute_p (decl, attributes, identifier, args) - tree decl ATTRIBUTE_UNUSED; - tree attributes ATTRIBUTE_UNUSED; - tree identifier; - tree args; -{ - if (is_attribute_p ("overlaid", identifier)) - return (args == NULL_TREE); - return 0; -} - -static int -alpha_does_function_need_gp () -{ - rtx insn; - - /* We never need a GP for Windows/NT or VMS. */ - if (TARGET_WINDOWS_NT || TARGET_OPEN_VMS) - return 0; - -#ifdef TARGET_PROFILING_NEEDS_GP - if (profile_flag) - return 1; -#endif - -#ifdef ASM_OUTPUT_MI_THUNK - if (current_function_is_thunk) - return 1; -#endif - - /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first. - Even if we are a static function, we still need to do this in case - our address is taken and passed to something like qsort. */ - - push_topmost_sequence (); - insn = get_insns (); - pop_topmost_sequence (); - - for (; insn; insn = NEXT_INSN (insn)) - if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' - && GET_CODE (PATTERN (insn)) != USE - && GET_CODE (PATTERN (insn)) != CLOBBER) - { - enum attr_type type = get_attr_type (insn); - if (type == TYPE_LDSYM || type == TYPE_JSR) - return 1; - } - - return 0; -} - -/* Write a version stamp. Don't write anything if we are running as a - cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */ - -#ifdef HAVE_STAMP_H -#include -#endif - -void -alpha_write_verstamp (file) - FILE *file; -{ -#ifdef MS_STAMP - fprintf (file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP); -#endif -} - -/* Helper function to set RTX_FRAME_RELATED_P on instructions, including - sequences. */ - -static rtx -set_frame_related_p () -{ - rtx seq = gen_sequence (); - end_sequence (); - - if (GET_CODE (seq) == SEQUENCE) - { - int i = XVECLEN (seq, 0); - while (--i >= 0) - RTX_FRAME_RELATED_P (XVECEXP (seq, 0, i)) = 1; - return emit_insn (seq); - } - else - { - seq = emit_insn (seq); - RTX_FRAME_RELATED_P (seq) = 1; - return seq; - } -} - -#define FRP(exp) (start_sequence (), exp, set_frame_related_p ()) - -/* Write function prologue. */ - -/* On vms we have two kinds of functions: - - - stack frame (PROC_STACK) - these are 'normal' functions with local vars and which are - calling other functions - - register frame (PROC_REGISTER) - keeps all data in registers, needs no stack - - We must pass this to the assembler so it can generate the - proper pdsc (procedure descriptor) - This is done with the '.pdesc' command. - - On not-vms, we don't really differentiate between the two, as we can - simply allocate stack without saving registers. */ - -void -alpha_expand_prologue () -{ - /* Registers to save. */ - unsigned long imask = 0; - unsigned long fmask = 0; - /* Stack space needed for pushing registers clobbered by us. */ - HOST_WIDE_INT sa_size; - /* Complete stack size needed. */ - HOST_WIDE_INT frame_size; - /* Offset from base reg to register save area. */ - HOST_WIDE_INT reg_offset; - rtx sa_reg, mem; - int i; - - sa_size = alpha_sa_size (); - - frame_size = get_frame_size (); - if (TARGET_OPEN_VMS) - frame_size = ALPHA_ROUND (sa_size - + (vms_is_stack_procedure ? 8 : 0) - + frame_size - + current_function_pretend_args_size); - else - frame_size = (ALPHA_ROUND (current_function_outgoing_args_size) - + sa_size - + ALPHA_ROUND (frame_size - + current_function_pretend_args_size)); - - if (TARGET_OPEN_VMS) - reg_offset = 8; - else - reg_offset = ALPHA_ROUND (current_function_outgoing_args_size); - - alpha_sa_mask (&imask, &fmask); - - /* Adjust the stack by the frame size. If the frame size is > 4096 - bytes, we need to be sure we probe somewhere in the first and last - 4096 bytes (we can probably get away without the latter test) and - every 8192 bytes in between. If the frame size is > 32768, we - do this in a loop. Otherwise, we generate the explicit probe - instructions. - - Note that we are only allowed to adjust sp once in the prologue. */ - - if (frame_size <= 32768) - { - if (frame_size > 4096) - { - int probed = 4096; - - do - emit_insn (gen_probe_stack (GEN_INT (-probed))); - while ((probed += 8192) < frame_size); - - /* We only have to do this probe if we aren't saving registers. */ - if (sa_size == 0 && probed + 4096 < frame_size) - emit_insn (gen_probe_stack (GEN_INT (-frame_size))); - } - - if (frame_size != 0) - { - FRP (emit_move_insn (stack_pointer_rtx, - plus_constant (stack_pointer_rtx, -frame_size))); - } - } - else - { - /* Here we generate code to set R22 to SP + 4096 and set R23 to the - number of 8192 byte blocks to probe. We then probe each block - in the loop and then set SP to the proper location. If the - amount remaining is > 4096, we have to do one more probe if we - are not saving any registers. */ - - HOST_WIDE_INT blocks = (frame_size + 4096) / 8192; - HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192; - rtx ptr = gen_rtx_REG (DImode, 22); - rtx count = gen_rtx_REG (DImode, 23); - - emit_move_insn (count, GEN_INT (blocks)); - emit_move_insn (ptr, plus_constant (stack_pointer_rtx, 4096)); - - /* Because of the difficulty in emitting a new basic block this - late in the compilation, generate the loop as a single insn. */ - emit_insn (gen_prologue_stack_probe_loop (count, ptr)); - - if (leftover > 4096 && sa_size == 0) - { - rtx last = gen_rtx_MEM (DImode, plus_constant (ptr, -leftover)); - MEM_VOLATILE_P (last) = 1; - emit_move_insn (last, const0_rtx); - } - - ptr = emit_move_insn (stack_pointer_rtx, plus_constant (ptr, -leftover)); - - /* This alternative is special, because the DWARF code cannot possibly - intuit through the loop above. So we invent this note it looks at - instead. */ - RTX_FRAME_RELATED_P (ptr) = 1; - REG_NOTES (ptr) - = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, - gen_rtx_SET (VOIDmode, stack_pointer_rtx, - gen_rtx_PLUS (Pmode, stack_pointer_rtx, - GEN_INT (-frame_size))), - REG_NOTES (ptr)); - } - - /* Cope with very large offsets to the register save area. */ - sa_reg = stack_pointer_rtx; - if (reg_offset + sa_size > 0x8000) - { - int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000; - HOST_WIDE_INT bias; - - if (low + sa_size <= 0x8000) - bias = reg_offset - low, reg_offset = low; - else - bias = reg_offset, reg_offset = 0; - - sa_reg = gen_rtx_REG (DImode, 24); - FRP (emit_move_insn (sa_reg, plus_constant (stack_pointer_rtx, bias))); - } - - /* Save regs in stack order. Beginning with VMS PV. */ - if (TARGET_OPEN_VMS && vms_is_stack_procedure) - { - mem = gen_rtx_MEM (DImode, stack_pointer_rtx); - MEM_ALIAS_SET (mem) = alpha_sr_alias_set; - FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_PV))); - } - - /* Save register RA next. */ - if (imask & (1L << REG_RA)) - { - mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); - MEM_ALIAS_SET (mem) = alpha_sr_alias_set; - FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA))); - imask &= ~(1L << REG_RA); - reg_offset += 8; - } - - /* Now save any other registers required to be saved. */ - for (i = 0; i < 32; i++) - if (imask & (1L << i)) - { - mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); - MEM_ALIAS_SET (mem) = alpha_sr_alias_set; - FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i))); - reg_offset += 8; - } - - for (i = 0; i < 32; i++) - if (fmask & (1L << i)) - { - mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset)); - MEM_ALIAS_SET (mem) = alpha_sr_alias_set; - FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32))); - reg_offset += 8; - } - - if (TARGET_OPEN_VMS) - { - if (!vms_is_stack_procedure) - { - /* Register frame procedures fave the fp. */ - FRP (emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno), - hard_frame_pointer_rtx)); - } - - if (vms_base_regno != REG_PV) - FRP (emit_move_insn (gen_rtx_REG (DImode, vms_base_regno), - gen_rtx_REG (DImode, REG_PV))); - - if (vms_unwind_regno == HARD_FRAME_POINTER_REGNUM) - { - FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx)); - } - - /* If we have to allocate space for outgoing args, do it now. */ - if (current_function_outgoing_args_size != 0) - { - FRP (emit_move_insn (stack_pointer_rtx, - plus_constant (hard_frame_pointer_rtx, - - ALPHA_ROUND (current_function_outgoing_args_size)))); - } - } - else - { - /* If we need a frame pointer, set it from the stack pointer. */ - if (frame_pointer_needed) - { - if (TARGET_CAN_FAULT_IN_PROLOGUE) - FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx)); - else - { - /* This must always be the last instruction in the - prologue, thus we emit a special move + clobber. */ - FRP (emit_insn (gen_init_fp (hard_frame_pointer_rtx, - stack_pointer_rtx, sa_reg))); - } - } - } - - /* The ABIs for VMS and OSF/1 say that while we can schedule insns into - the prologue, for exception handling reasons, we cannot do this for - any insn that might fault. We could prevent this for mems with a - (clobber:BLK (scratch)), but this doesn't work for fp insns. So we - have to prevent all such scheduling with a blockage. - - Linux, on the other hand, never bothered to implement OSF/1's - exception handling, and so doesn't care about such things. Anyone - planning to use dwarf2 frame-unwind info can also omit the blockage. */ - - if (! TARGET_CAN_FAULT_IN_PROLOGUE) - emit_insn (gen_blockage ()); -} - -/* Output the textual info surrounding the prologue. */ - -void -alpha_start_function (file, fnname, decl) - FILE *file; - char *fnname; - tree decl ATTRIBUTE_UNUSED; -{ - unsigned long imask = 0; - unsigned long fmask = 0; - /* Stack space needed for pushing registers clobbered by us. */ - HOST_WIDE_INT sa_size; - /* Complete stack size needed. */ - HOST_WIDE_INT frame_size; - /* Offset from base reg to register save area. */ - HOST_WIDE_INT reg_offset; - char *entry_label = (char *) alloca (strlen (fnname) + 6); - int i; - - sa_size = alpha_sa_size (); - - frame_size = get_frame_size (); - if (TARGET_OPEN_VMS) - frame_size = ALPHA_ROUND (sa_size - + (vms_is_stack_procedure ? 8 : 0) - + frame_size - + current_function_pretend_args_size); - else - frame_size = (ALPHA_ROUND (current_function_outgoing_args_size) - + sa_size - + ALPHA_ROUND (frame_size - + current_function_pretend_args_size)); - - if (TARGET_OPEN_VMS) - reg_offset = 8; - else - reg_offset = ALPHA_ROUND (current_function_outgoing_args_size); - - alpha_sa_mask (&imask, &fmask); - - /* Ecoff can handle multiple .file directives, so put out file and lineno. - We have to do that before the .ent directive as we cannot switch - files within procedures with native ecoff because line numbers are - linked to procedure descriptors. - Outputting the lineno helps debugging of one line functions as they - would otherwise get no line number at all. Please note that we would - like to put out last_linenum from final.c, but it is not accessible. */ - - if (write_symbols == SDB_DEBUG) - { - ASM_OUTPUT_SOURCE_FILENAME (file, - DECL_SOURCE_FILE (current_function_decl)); - if (debug_info_level != DINFO_LEVEL_TERSE) - ASM_OUTPUT_SOURCE_LINE (file, - DECL_SOURCE_LINE (current_function_decl)); - } - - /* Issue function start and label. */ - if (TARGET_OPEN_VMS || !flag_inhibit_size_directive) - { - fputs ("\t.ent ", file); - assemble_name (file, fnname); - putc ('\n', file); - } - - strcpy (entry_label, fnname); - if (TARGET_OPEN_VMS) - strcat (entry_label, "..en"); - ASM_OUTPUT_LABEL (file, entry_label); - inside_function = TRUE; - - if (TARGET_OPEN_VMS) - fprintf (file, "\t.base $%d\n", vms_base_regno); - - if (!TARGET_OPEN_VMS && TARGET_IEEE_CONFORMANT - && !flag_inhibit_size_directive) - { - /* Set flags in procedure descriptor to request IEEE-conformant - math-library routines. The value we set it to is PDSC_EXC_IEEE - (/usr/include/pdsc.h). */ - fputs ("\t.eflag 48\n", file); - } - - /* Set up offsets to alpha virtual arg/local debugging pointer. */ - alpha_auto_offset = -frame_size + current_function_pretend_args_size; - alpha_arg_offset = -frame_size + 48; - - /* Describe our frame. If the frame size is larger than an integer, - print it as zero to avoid an assembler error. We won't be - properly describing such a frame, but that's the best we can do. */ - if (TARGET_OPEN_VMS) - { - fprintf (file, "\t.frame $%d,", vms_unwind_regno); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - frame_size >= (1l << 31) ? 0 : frame_size); - fputs (",$26,", file); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, reg_offset); - fputs ("\n", file); - } - else if (!flag_inhibit_size_directive) - { - fprintf (file, "\t.frame $%d,", - (frame_pointer_needed - ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM)); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - frame_size >= (1l << 31) ? 0 : frame_size); - fprintf (file, ",$26,%d\n", current_function_pretend_args_size); - } - - /* Describe which registers were spilled. */ - if (TARGET_OPEN_VMS) - { - if (imask) - /* ??? Does VMS care if mask contains ra? The old code did'nt - set it, so I don't here. */ - fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA)); - if (fmask) - fprintf (file, "\t.fmask 0x%lx,0\n", fmask); - if (!vms_is_stack_procedure) - fprintf (file, "\t.fp_save $%d\n", vms_save_fp_regno); - } - else if (!flag_inhibit_size_directive) - { - if (imask) - { - fprintf (file, "\t.mask 0x%lx,", imask); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - frame_size >= (1l << 31) ? 0 : reg_offset - frame_size); - putc ('\n', file); - - for (i = 0; i < 32; ++i) - if (imask & (1L << i)) - reg_offset += 8; - } - - if (fmask) - { - fprintf (file, "\t.fmask 0x%lx,", fmask); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - frame_size >= (1l << 31) ? 0 : reg_offset - frame_size); - putc ('\n', file); - } - } - - /* Emit GP related things. It is rather unfortunate about the alignment - issues surrounding a CODE_LABEL that forces us to do the label in - plain text. */ - if (!TARGET_OPEN_VMS && !TARGET_WINDOWS_NT) - { - alpha_function_needs_gp = alpha_does_function_need_gp (); - if (alpha_function_needs_gp) - fputs ("\tldgp $29,0($27)\n", file); - - putc ('$', file); - assemble_name (file, fnname); - fputs ("..ng:\n", file); - } - -#ifdef OPEN_VMS - /* Ifdef'ed cause readonly_section and link_section are only - available then. */ - readonly_section (); - fprintf (file, "\t.align 3\n"); - assemble_name (file, fnname); fputs ("..na:\n", file); - fputs ("\t.ascii \"", file); - assemble_name (file, fnname); - fputs ("\\0\"\n", file); - - link_section (); - fprintf (file, "\t.align 3\n"); - fputs ("\t.name ", file); - assemble_name (file, fnname); - fputs ("..na\n", file); - ASM_OUTPUT_LABEL (file, fnname); - fprintf (file, "\t.pdesc "); - assemble_name (file, fnname); - fprintf (file, "..en,%s\n", vms_is_stack_procedure ? "stack" : "reg"); - alpha_need_linkage (fnname, 1); - text_section (); -#endif -} - -/* Emit the .prologue note at the scheduled end of the prologue. */ - -void -output_end_prologue (file) - FILE *file; -{ - if (TARGET_OPEN_VMS) - fputs ("\t.prologue\n", file); - else if (TARGET_WINDOWS_NT) - fputs ("\t.prologue 0\n", file); - else if (!flag_inhibit_size_directive) - fprintf (file, "\t.prologue %d\n", alpha_function_needs_gp); -} - -/* Write function epilogue. */ - -/* ??? At some point we will want to support full unwind, and so will - need to mark the epilogue as well. At the moment, we just confuse - dwarf2out. */ -#undef FRP -#define FRP(exp) exp - -void -alpha_expand_epilogue () -{ - /* Registers to save. */ - unsigned long imask = 0; - unsigned long fmask = 0; - /* Stack space needed for pushing registers clobbered by us. */ - HOST_WIDE_INT sa_size; - /* Complete stack size needed. */ - HOST_WIDE_INT frame_size; - /* Offset from base reg to register save area. */ - HOST_WIDE_INT reg_offset; - int fp_is_frame_pointer, fp_offset; - rtx sa_reg, sa_reg_exp = NULL; - rtx sp_adj1, sp_adj2, mem; - int i; - - sa_size = alpha_sa_size (); - - frame_size = get_frame_size (); - if (TARGET_OPEN_VMS) - frame_size = ALPHA_ROUND (sa_size - + (vms_is_stack_procedure ? 8 : 0) - + frame_size - + current_function_pretend_args_size); - else - frame_size = (ALPHA_ROUND (current_function_outgoing_args_size) - + sa_size - + ALPHA_ROUND (frame_size - + current_function_pretend_args_size)); - - if (TARGET_OPEN_VMS) - reg_offset = 8; - else - reg_offset = ALPHA_ROUND (current_function_outgoing_args_size); - - alpha_sa_mask (&imask, &fmask); - - fp_is_frame_pointer = ((TARGET_OPEN_VMS && vms_is_stack_procedure) - || (!TARGET_OPEN_VMS && frame_pointer_needed)); - - if (sa_size) - { - /* If we have a frame pointer, restore SP from it. */ - if ((TARGET_OPEN_VMS - && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM) - || (!TARGET_OPEN_VMS && frame_pointer_needed)) - { - FRP (emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx)); - } - - /* Cope with very large offsets to the register save area. */ - sa_reg = stack_pointer_rtx; - if (reg_offset + sa_size > 0x8000) - { - int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000; - HOST_WIDE_INT bias; - - if (low + sa_size <= 0x8000) - bias = reg_offset - low, reg_offset = low; - else - bias = reg_offset, reg_offset = 0; - - sa_reg = gen_rtx_REG (DImode, 22); - sa_reg_exp = plus_constant (stack_pointer_rtx, bias); - - FRP (emit_move_insn (sa_reg, sa_reg_exp)); - } - - /* Restore registers in order, excepting a true frame pointer. */ - - if (! alpha_eh_epilogue_sp_ofs) - { - mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset)); - MEM_ALIAS_SET (mem) = alpha_sr_alias_set; - FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem)); - } - reg_offset += 8; - imask &= ~(1L << REG_RA); - - for (i = 0; i < 32; ++i) - if (imask & (1L << i)) - { - if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer) - fp_offset = reg_offset; - else - { - mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset)); - MEM_ALIAS_SET (mem) = alpha_sr_alias_set; - FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem)); - } - reg_offset += 8; - } - - for (i = 0; i < 32; ++i) - if (fmask & (1L << i)) - { - mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset)); - MEM_ALIAS_SET (mem) = alpha_sr_alias_set; - FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem)); - reg_offset += 8; - } - } - - if (frame_size || alpha_eh_epilogue_sp_ofs) - { - sp_adj1 = stack_pointer_rtx; - - if (alpha_eh_epilogue_sp_ofs) - { - sp_adj1 = gen_rtx_REG (DImode, 23); - emit_move_insn (sp_adj1, - gen_rtx_PLUS (Pmode, stack_pointer_rtx, - alpha_eh_epilogue_sp_ofs)); - } - - /* If the stack size is large, begin computation into a temporary - register so as not to interfere with a potential fp restore, - which must be consecutive with an SP restore. */ - if (frame_size < 32768) - sp_adj2 = GEN_INT (frame_size); - else if (frame_size < 0x40007fffL) - { - int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000; - - sp_adj2 = plus_constant (sp_adj1, frame_size - low); - if (sa_reg_exp && rtx_equal_p (sa_reg_exp, sp_adj2)) - sp_adj1 = sa_reg; - else - { - sp_adj1 = gen_rtx_REG (DImode, 23); - FRP (emit_move_insn (sp_adj1, sp_adj2)); - } - sp_adj2 = GEN_INT (low); - } - else - { - rtx tmp = gen_rtx_REG (DImode, 23); - FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, 3)); - if (!sp_adj2) - { - /* We can't drop new things to memory this late, afaik, - so build it up by pieces. */ - FRP (sp_adj2 = alpha_emit_set_long_const (tmp, frame_size, - -(frame_size < 0))); - if (!sp_adj2) - abort (); - } - } - - /* From now on, things must be in order. So emit blockages. */ - - /* Restore the frame pointer. */ - if (fp_is_frame_pointer) - { - emit_insn (gen_blockage ()); - mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, fp_offset)); - MEM_ALIAS_SET (mem) = alpha_sr_alias_set; - FRP (emit_move_insn (hard_frame_pointer_rtx, mem)); - } - else if (TARGET_OPEN_VMS) - { - emit_insn (gen_blockage ()); - FRP (emit_move_insn (hard_frame_pointer_rtx, - gen_rtx_REG (DImode, vms_save_fp_regno))); - } - - /* Restore the stack pointer. */ - emit_insn (gen_blockage ()); - FRP (emit_move_insn (stack_pointer_rtx, - gen_rtx_PLUS (DImode, sp_adj1, sp_adj2))); - } - else - { - if (TARGET_OPEN_VMS && !vms_is_stack_procedure) - { - emit_insn (gen_blockage ()); - FRP (emit_move_insn (hard_frame_pointer_rtx, - gen_rtx_REG (DImode, vms_save_fp_regno))); - } - } - - /* Return. */ - emit_jump_insn (gen_return_internal ()); -} - -/* Output the rest of the textual info surrounding the epilogue. */ - -void -alpha_end_function (file, fnname, decl) - FILE *file; - char *fnname; - tree decl ATTRIBUTE_UNUSED; -{ - /* End the function. */ - if (!flag_inhibit_size_directive) - { - fputs ("\t.end ", file); - assemble_name (file, fnname); - putc ('\n', file); - } - inside_function = FALSE; - - /* Show that we know this function if it is called again. - - Don't do this for global functions in object files destined for a - shared library because the function may be overridden by the application - or other libraries. - ??? Is this just ELF? */ - - if (!flag_pic || !TREE_PUBLIC (current_function_decl)) - SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1; -} - -/* Debugging support. */ - -#include "gstab.h" - -/* 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. */ - -static int sym_lineno = 0; - -/* Count the number of .file directives, so that .loc is up to date. */ - -static int num_source_filenames = 0; - -/* Name of the file containing the current function. */ - -static char *current_function_file = ""; - -/* Offsets to alpha virtual arg/local debugging pointers. */ - -long alpha_arg_offset; -long alpha_auto_offset; - -/* Emit a new filename to a stream. */ - -void -alpha_output_filename (stream, name) - FILE *stream; - char *name; -{ - static int first_time = TRUE; - char ltext_label_name[100]; - - if (first_time) - { - first_time = FALSE; - ++num_source_filenames; - current_function_file = name; - fprintf (stream, "\t.file\t%d ", num_source_filenames); - output_quoted_string (stream, name); - fprintf (stream, "\n"); - if (!TARGET_GAS && write_symbols == DBX_DEBUG) - fprintf (stream, "\t#@stabs\n"); - } - - else if (write_symbols == DBX_DEBUG) - { - ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0); - fprintf (stream, "%s ", ASM_STABS_OP); - output_quoted_string (stream, name); - fprintf (stream, ",%d,0,0,%s\n", N_SOL, <ext_label_name[1]); - } - - else if (name != current_function_file - && strcmp (name, current_function_file) != 0) - { - if (inside_function && ! TARGET_GAS) - fprintf (stream, "\t#.file\t%d ", num_source_filenames); - else - { - ++num_source_filenames; - current_function_file = name; - fprintf (stream, "\t.file\t%d ", num_source_filenames); - } - - output_quoted_string (stream, name); - fprintf (stream, "\n"); - } -} - -/* Emit a linenumber to a stream. */ - -void -alpha_output_lineno (stream, line) - FILE *stream; - int line; -{ - if (write_symbols == DBX_DEBUG) - { - /* mips-tfile doesn't understand .stabd directives. */ - ++sym_lineno; - fprintf (stream, "$LM%d:\n\t%s %d,0,%d,$LM%d\n", - sym_lineno, ASM_STABN_OP, N_SLINE, line, sym_lineno); - } - else - fprintf (stream, "\n\t.loc\t%d %d\n", num_source_filenames, line); -} - -/* Structure to show the current status of registers and memory. */ - -struct shadow_summary -{ - struct { - unsigned long i : 31; /* Mask of int regs */ - unsigned long fp : 31; /* Mask of fp regs */ - unsigned long mem : 1; /* mem == imem | fpmem */ - } used, defd; -}; - -static void summarize_insn PROTO((rtx, struct shadow_summary *, int)); -static void alpha_handle_trap_shadows PROTO((rtx)); - -/* Summary the effects of expression X on the machine. Update SUM, a pointer - to the summary structure. SET is nonzero if the insn is setting the - object, otherwise zero. */ - -static void -summarize_insn (x, sum, set) - rtx x; - struct shadow_summary *sum; - int set; -{ - char *format_ptr; - int i, j; - - if (x == 0) - return; - - switch (GET_CODE (x)) - { - /* ??? Note that this case would be incorrect if the Alpha had a - ZERO_EXTRACT in SET_DEST. */ - case SET: - summarize_insn (SET_SRC (x), sum, 0); - summarize_insn (SET_DEST (x), sum, 1); - break; - - case CLOBBER: - summarize_insn (XEXP (x, 0), sum, 1); - break; - - case USE: - summarize_insn (XEXP (x, 0), sum, 0); - break; - - case ASM_OPERANDS: - for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--) - summarize_insn (ASM_OPERANDS_INPUT (x, i), sum, 0); - break; - - case PARALLEL: - for (i = XVECLEN (x, 0) - 1; i >= 0; i--) - summarize_insn (XVECEXP (x, 0, i), sum, 0); - break; - - case SUBREG: - summarize_insn (SUBREG_REG (x), sum, 0); - break; - - case REG: - { - int regno = REGNO (x); - unsigned long mask = 1UL << (regno % 32); - - if (regno == 31 || regno == 63) - break; - - if (set) - { - if (regno < 32) - sum->defd.i |= mask; - else - sum->defd.fp |= mask; - } - else - { - if (regno < 32) - sum->used.i |= mask; - else - sum->used.fp |= mask; - } - } - break; - - case MEM: - if (set) - sum->defd.mem = 1; - else - sum->used.mem = 1; - - /* Find the regs used in memory address computation: */ - summarize_insn (XEXP (x, 0), sum, 0); - break; - - case CONST_INT: case CONST_DOUBLE: - case SYMBOL_REF: case LABEL_REF: case CONST: - break; - - /* Handle common unary and binary ops for efficiency. */ - case COMPARE: case PLUS: case MINUS: case MULT: case DIV: - case MOD: case UDIV: case UMOD: case AND: case IOR: - case XOR: case ASHIFT: case ROTATE: case ASHIFTRT: case LSHIFTRT: - case ROTATERT: case SMIN: case SMAX: case UMIN: case UMAX: - case NE: case EQ: case GE: case GT: case LE: - case LT: case GEU: case GTU: case LEU: case LTU: - summarize_insn (XEXP (x, 0), sum, 0); - summarize_insn (XEXP (x, 1), sum, 0); - break; - - case NEG: case NOT: case SIGN_EXTEND: case ZERO_EXTEND: - case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE: case FLOAT: - case FIX: case UNSIGNED_FLOAT: case UNSIGNED_FIX: case ABS: - case SQRT: case FFS: - summarize_insn (XEXP (x, 0), sum, 0); - break; - - default: - format_ptr = GET_RTX_FORMAT (GET_CODE (x)); - for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) - switch (format_ptr[i]) - { - case 'e': - summarize_insn (XEXP (x, i), sum, 0); - break; - - case 'E': - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - summarize_insn (XVECEXP (x, i, j), sum, 0); - break; - - case 'i': - break; - - default: - abort (); - } - } -} - -/* Ensure a sufficient number of `trapb' insns are in the code when - the user requests code with a trap precision of functions or - instructions. - - In naive mode, when the user requests a trap-precision of - "instruction", a trapb is needed after every instruction that may - generate a trap. This ensures that the code is resumption safe but - it is also slow. - - When optimizations are turned on, we delay issuing a trapb as long - as possible. In this context, a trap shadow is the sequence of - instructions that starts with a (potentially) trap generating - instruction and extends to the next trapb or call_pal instruction - (but GCC never generates call_pal by itself). We can delay (and - therefore sometimes omit) a trapb subject to the following - conditions: - - (a) On entry to the trap shadow, if any Alpha register or memory - location contains a value that is used as an operand value by some - instruction in the trap shadow (live on entry), then no instruction - in the trap shadow may modify the register or memory location. - - (b) Within the trap shadow, the computation of the base register - for a memory load or store instruction may not involve using the - result of an instruction that might generate an UNPREDICTABLE - result. - - (c) Within the trap shadow, no register may be used more than once - as a destination register. (This is to make life easier for the - trap-handler.) - - (d) The trap shadow may not include any branch instructions. */ - -static void -alpha_handle_trap_shadows (insns) - rtx insns; -{ - struct shadow_summary shadow; - int trap_pending, exception_nesting; - rtx i, n; - - trap_pending = 0; - exception_nesting = 0; - shadow.used.i = 0; - shadow.used.fp = 0; - shadow.used.mem = 0; - shadow.defd = shadow.used; - - for (i = insns; i ; i = NEXT_INSN (i)) - { - if (GET_CODE (i) == NOTE) - { - switch (NOTE_LINE_NUMBER (i)) - { - case NOTE_INSN_EH_REGION_BEG: - exception_nesting++; - if (trap_pending) - goto close_shadow; - break; - - case NOTE_INSN_EH_REGION_END: - exception_nesting--; - if (trap_pending) - goto close_shadow; - break; - - case NOTE_INSN_EPILOGUE_BEG: - if (trap_pending && alpha_tp >= ALPHA_TP_FUNC) - goto close_shadow; - break; - } - } - else if (trap_pending) - { - if (alpha_tp == ALPHA_TP_FUNC) - { - if (GET_CODE (i) == JUMP_INSN - && GET_CODE (PATTERN (i)) == RETURN) - goto close_shadow; - } - else if (alpha_tp == ALPHA_TP_INSN) - { - if (optimize > 0) - { - struct shadow_summary sum; - - sum.used.i = 0; - sum.used.fp = 0; - sum.used.mem = 0; - sum.defd = sum.used; - - switch (GET_CODE (i)) - { - case INSN: - /* Annoyingly, get_attr_trap will abort on these. */ - if (GET_CODE (PATTERN (i)) == USE - || GET_CODE (PATTERN (i)) == CLOBBER) - break; - - summarize_insn (PATTERN (i), &sum, 0); - - if ((sum.defd.i & shadow.defd.i) - || (sum.defd.fp & shadow.defd.fp)) - { - /* (c) would be violated */ - goto close_shadow; - } - - /* Combine shadow with summary of current insn: */ - shadow.used.i |= sum.used.i; - shadow.used.fp |= sum.used.fp; - shadow.used.mem |= sum.used.mem; - shadow.defd.i |= sum.defd.i; - shadow.defd.fp |= sum.defd.fp; - shadow.defd.mem |= sum.defd.mem; - - if ((sum.defd.i & shadow.used.i) - || (sum.defd.fp & shadow.used.fp) - || (sum.defd.mem & shadow.used.mem)) - { - /* (a) would be violated (also takes care of (b)) */ - if (get_attr_trap (i) == TRAP_YES - && ((sum.defd.i & sum.used.i) - || (sum.defd.fp & sum.used.fp))) - abort (); - - goto close_shadow; - } - break; - - case JUMP_INSN: - case CALL_INSN: - case CODE_LABEL: - goto close_shadow; - - default: - abort (); - } - } - else - { - close_shadow: - n = emit_insn_before (gen_trapb (), i); - PUT_MODE (n, TImode); - PUT_MODE (i, TImode); - trap_pending = 0; - shadow.used.i = 0; - shadow.used.fp = 0; - shadow.used.mem = 0; - shadow.defd = shadow.used; - } - } - } - - if ((exception_nesting > 0 || alpha_tp >= ALPHA_TP_FUNC) - && GET_CODE (i) == INSN - && GET_CODE (PATTERN (i)) != USE - && GET_CODE (PATTERN (i)) != CLOBBER - && get_attr_trap (i) == TRAP_YES) - { - if (optimize && !trap_pending) - summarize_insn (PATTERN (i), &shadow, 0); - trap_pending = 1; - } - } -} - -#ifdef HAIFA -/* Alpha can only issue instruction groups simultaneously if they are - suitibly aligned. This is very processor-specific. */ - -enum alphaev4_pipe { - EV4_STOP = 0, - EV4_IB0 = 1, - EV4_IB1 = 2, - EV4_IBX = 4 -}; - -enum alphaev5_pipe { - EV5_STOP = 0, - EV5_NONE = 1, - EV5_E01 = 2, - EV5_E0 = 4, - EV5_E1 = 8, - EV5_FAM = 16, - EV5_FA = 32, - EV5_FM = 64 -}; - -static enum alphaev4_pipe alphaev4_insn_pipe PROTO((rtx)); -static enum alphaev5_pipe alphaev5_insn_pipe PROTO((rtx)); -static rtx alphaev4_next_group PROTO((rtx, int*, int*)); -static rtx alphaev5_next_group PROTO((rtx, int*, int*)); -static rtx alphaev4_next_nop PROTO((int*)); -static rtx alphaev5_next_nop PROTO((int*)); - -static void alpha_align_insns - PROTO((rtx, int, rtx (*)(rtx, int*, int*), rtx (*)(int*), int)); - -static enum alphaev4_pipe -alphaev4_insn_pipe (insn) - rtx insn; -{ - if (recog_memoized (insn) < 0) - return EV4_STOP; - if (get_attr_length (insn) != 4) - return EV4_STOP; - - switch (get_attr_type (insn)) - { - case TYPE_ILD: - case TYPE_FLD: - return EV4_IBX; - - case TYPE_LDSYM: - case TYPE_IADD: - case TYPE_ILOG: - case TYPE_ICMOV: - case TYPE_ICMP: - case TYPE_IST: - case TYPE_FST: - case TYPE_SHIFT: - case TYPE_IMUL: - case TYPE_FBR: - return EV4_IB0; - - case TYPE_MISC: - case TYPE_IBR: - case TYPE_JSR: - case TYPE_FCPYS: - case TYPE_FCMOV: - case TYPE_FADD: - case TYPE_FDIV: - case TYPE_FMUL: - return EV4_IB1; - - default: - abort(); - } -} - -static enum alphaev5_pipe -alphaev5_insn_pipe (insn) - rtx insn; -{ - if (recog_memoized (insn) < 0) - return EV5_STOP; - if (get_attr_length (insn) != 4) - return EV5_STOP; - - switch (get_attr_type (insn)) - { - case TYPE_ILD: - case TYPE_FLD: - case TYPE_LDSYM: - case TYPE_IADD: - case TYPE_ILOG: - case TYPE_ICMOV: - case TYPE_ICMP: - return EV5_E01; - - case TYPE_IST: - case TYPE_FST: - case TYPE_SHIFT: - case TYPE_IMUL: - case TYPE_MISC: - case TYPE_MVI: - return EV5_E0; - - case TYPE_IBR: - case TYPE_JSR: - return EV5_E1; - - case TYPE_FCPYS: - return EV5_FAM; - - case TYPE_FBR: - case TYPE_FCMOV: - case TYPE_FADD: - case TYPE_FDIV: - return EV5_FA; - - case TYPE_FMUL: - return EV5_FM; - - default: - abort(); - } -} - -/* IN_USE is a mask of the slots currently filled within the insn group. - The mask bits come from alphaev4_pipe above. If EV4_IBX is set, then - the insn in EV4_IB0 can be swapped by the hardware into EV4_IB1. - - LEN is, of course, the length of the group in bytes. */ - -static rtx -alphaev4_next_group (insn, pin_use, plen) - rtx insn; - int *pin_use, *plen; -{ - int len, in_use; - - len = in_use = 0; - - if (GET_RTX_CLASS (GET_CODE (insn)) != 'i' - || GET_CODE (PATTERN (insn)) == CLOBBER - || GET_CODE (PATTERN (insn)) == USE) - goto next_and_done; - - while (1) - { - enum alphaev4_pipe pipe; - - pipe = alphaev4_insn_pipe (insn); - switch (pipe) - { - case EV4_STOP: - /* Force complex instructions to start new groups. */ - if (in_use) - goto done; - - /* If this is a completely unrecognized insn, its an asm. - We don't know how long it is, so record length as -1 to - signal a needed realignment. */ - if (recog_memoized (insn) < 0) - len = -1; - else - len = get_attr_length (insn); - goto next_and_done; - - case EV4_IBX: - if (in_use & EV4_IB0) - { - if (in_use & EV4_IB1) - goto done; - in_use |= EV4_IB1; - } - else - in_use |= EV4_IB0 | EV4_IBX; - break; - - case EV4_IB0: - if (in_use & EV4_IB0) - { - if (!(in_use & EV4_IBX) || (in_use & EV4_IB1)) - goto done; - in_use |= EV4_IB1; - } - in_use |= EV4_IB0; - break; - - case EV4_IB1: - if (in_use & EV4_IB1) - goto done; - in_use |= EV4_IB1; - break; - - default: - abort(); - } - len += 4; - - /* Haifa doesn't do well scheduling branches. */ - if (GET_CODE (insn) == JUMP_INSN) - goto next_and_done; - - next: - insn = next_nonnote_insn (insn); - - if (!insn || GET_RTX_CLASS (GET_CODE (insn)) != 'i') - goto done; - - /* Let Haifa tell us where it thinks insn group boundaries are. */ - if (GET_MODE (insn) == TImode) - goto done; - - if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE) - goto next; - } - - next_and_done: - insn = next_nonnote_insn (insn); - - done: - *plen = len; - *pin_use = in_use; - return insn; -} - -/* IN_USE is a mask of the slots currently filled within the insn group. - The mask bits come from alphaev5_pipe above. If EV5_E01 is set, then - the insn in EV5_E0 can be swapped by the hardware into EV5_E1. - - LEN is, of course, the length of the group in bytes. */ - -static rtx -alphaev5_next_group (insn, pin_use, plen) - rtx insn; - int *pin_use, *plen; -{ - int len, in_use; - - len = in_use = 0; - - if (GET_RTX_CLASS (GET_CODE (insn)) != 'i' - || GET_CODE (PATTERN (insn)) == CLOBBER - || GET_CODE (PATTERN (insn)) == USE) - goto next_and_done; - - while (1) - { - enum alphaev5_pipe pipe; - - pipe = alphaev5_insn_pipe (insn); - switch (pipe) - { - case EV5_STOP: - /* Force complex instructions to start new groups. */ - if (in_use) - goto done; - - /* If this is a completely unrecognized insn, its an asm. - We don't know how long it is, so record length as -1 to - signal a needed realignment. */ - if (recog_memoized (insn) < 0) - len = -1; - else - len = get_attr_length (insn); - goto next_and_done; - - /* ??? Most of the places below, we would like to abort, as - it would indicate an error either in Haifa, or in the - scheduling description. Unfortunately, Haifa never - schedules the last instruction of the BB, so we don't - have an accurate TI bit to go off. */ - case EV5_E01: - if (in_use & EV5_E0) - { - if (in_use & EV5_E1) - goto done; - in_use |= EV5_E1; - } - else - in_use |= EV5_E0 | EV5_E01; - break; - - case EV5_E0: - if (in_use & EV5_E0) - { - if (!(in_use & EV5_E01) || (in_use & EV5_E1)) - goto done; - in_use |= EV5_E1; - } - in_use |= EV5_E0; - break; - - case EV5_E1: - if (in_use & EV5_E1) - goto done; - in_use |= EV5_E1; - break; - - case EV5_FAM: - if (in_use & EV5_FA) - { - if (in_use & EV5_FM) - goto done; - in_use |= EV5_FM; - } - else - in_use |= EV5_FA | EV5_FAM; - break; - - case EV5_FA: - if (in_use & EV5_FA) - goto done; - in_use |= EV5_FA; - break; - - case EV5_FM: - if (in_use & EV5_FM) - goto done; - in_use |= EV5_FM; - break; - - case EV5_NONE: - break; - - default: - abort(); - } - len += 4; - - /* Haifa doesn't do well scheduling branches. */ - /* ??? If this is predicted not-taken, slotting continues, except - that no more IBR, FBR, or JSR insns may be slotted. */ - if (GET_CODE (insn) == JUMP_INSN) - goto next_and_done; - - next: - insn = next_nonnote_insn (insn); - - if (!insn || GET_RTX_CLASS (GET_CODE (insn)) != 'i') - goto done; - - /* Let Haifa tell us where it thinks insn group boundaries are. */ - if (GET_MODE (insn) == TImode) - goto done; - - if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE) - goto next; - } - - next_and_done: - insn = next_nonnote_insn (insn); - - done: - *plen = len; - *pin_use = in_use; - return insn; -} - -static rtx -alphaev4_next_nop (pin_use) - int *pin_use; -{ - int in_use = *pin_use; - rtx nop; - - if (!(in_use & EV4_IB0)) - { - in_use |= EV4_IB0; - nop = gen_nop (); - } - else if ((in_use & (EV4_IBX|EV4_IB1)) == EV4_IBX) - { - in_use |= EV4_IB1; - nop = gen_nop (); - } - else if (TARGET_FP && !(in_use & EV4_IB1)) - { - in_use |= EV4_IB1; - nop = gen_fnop (); - } - else - nop = gen_unop (); - - *pin_use = in_use; - return nop; -} - -static rtx -alphaev5_next_nop (pin_use) - int *pin_use; -{ - int in_use = *pin_use; - rtx nop; - - if (!(in_use & EV5_E1)) - { - in_use |= EV5_E1; - nop = gen_nop (); - } - else if (TARGET_FP && !(in_use & EV5_FA)) - { - in_use |= EV5_FA; - nop = gen_fnop (); - } - else if (TARGET_FP && !(in_use & EV5_FM)) - { - in_use |= EV5_FM; - nop = gen_fnop (); - } - else - nop = gen_unop (); - - *pin_use = in_use; - return nop; -} - -/* The instruction group alignment main loop. */ - -static void -alpha_align_insns (insns, max_align, next_group, next_nop, gp_in_use) - rtx insns; - int max_align; - rtx (*next_group) PROTO((rtx, int*, int*)); - rtx (*next_nop) PROTO((int*)); - int gp_in_use; -{ - /* ALIGN is the known alignment for the insn group. */ - int align; - /* OFS is the offset of the current insn in the insn group. */ - int ofs; - int prev_in_use, in_use, len; - rtx i, next; - - /* Let shorten branches care for assigning alignments to code labels. */ - shorten_branches (insns); - - align = (FUNCTION_BOUNDARY/BITS_PER_UNIT < max_align - ? FUNCTION_BOUNDARY/BITS_PER_UNIT : max_align); - - /* Account for the initial GP load, which happens before the scheduled - prologue we emitted as RTL. */ - ofs = prev_in_use = 0; - if (alpha_does_function_need_gp()) - { - ofs = 8 & (align - 1); - prev_in_use = gp_in_use; - } - - i = insns; - if (GET_CODE (i) == NOTE) - i = next_nonnote_insn (i); - - while (i) - { - next = (*next_group)(i, &in_use, &len); - - /* When we see a label, resync alignment etc. */ - if (GET_CODE (i) == CODE_LABEL) - { - int new_align = 1 << label_to_alignment (i); - if (new_align >= align) - { - align = new_align < max_align ? new_align : max_align; - ofs = 0; - } - else if (ofs & (new_align-1)) - ofs = (ofs | (new_align-1)) + 1; - if (len != 0) - abort(); - } - - /* Handle complex instructions special. */ - else if (in_use == 0) - { - /* Asms will have length < 0. This is a signal that we have - lost alignment knowledge. Assume, however, that the asm - will not mis-align instructions. */ - if (len < 0) - { - ofs = 0; - align = 4; - len = 0; - } - } - - /* If the known alignment is smaller than the recognized insn group, - realign the output. */ - else if (align < len) - { - int new_log_align = len > 8 ? 4 : 3; - rtx where; - - where = prev_nonnote_insn (i); - if (!where || GET_CODE (where) != CODE_LABEL) - where = i; - - emit_insn_before (gen_realign (GEN_INT (new_log_align)), where); - align = 1 << new_log_align; - ofs = 0; - } - - /* If the group won't fit in the same INT16 as the previous, - we need to add padding to keep the group together. Rather - than simply leaving the insn filling to the assembler, we - can make use of the knowledge of what sorts of instructions - were issued in the previous group to make sure that all of - the added nops are really free. */ - else if (ofs + len > align) - { - int nop_count = (align - ofs) / 4; - rtx where; - - /* Insert nops before labels and branches to truely merge the - execution of the nops with the previous instruction group. */ - where = prev_nonnote_insn (i); - if (where) - { - if (GET_CODE (where) == CODE_LABEL) - { - rtx where2 = prev_nonnote_insn (where); - if (where2 && GET_CODE (where2) == JUMP_INSN) - where = where2; - } - else if (GET_CODE (where) != JUMP_INSN) - where = i; - } - else - where = i; - - do - emit_insn_before ((*next_nop)(&prev_in_use), where); - while (--nop_count); - ofs = 0; - } - - ofs = (ofs + len) & (align - 1); - prev_in_use = in_use; - i = next; - } -} -#endif /* HAIFA */ - -/* Machine dependant reorg pass. */ - -void -alpha_reorg (insns) - rtx insns; -{ - if (alpha_tp != ALPHA_TP_PROG || flag_exceptions) - alpha_handle_trap_shadows (insns); - -#ifdef HAIFA - /* Due to the number of extra trapb insns, don't bother fixing up - alignment when trap precision is instruction. Moreover, we can - only do our job when sched2 is run and Haifa is our scheduler. */ - if (optimize && !optimize_size - && alpha_tp != ALPHA_TP_INSN - && flag_schedule_insns_after_reload) - { - if (alpha_cpu == PROCESSOR_EV4) - alpha_align_insns (insns, 8, alphaev4_next_group, - alphaev4_next_nop, EV4_IB0); - else if (alpha_cpu == PROCESSOR_EV5) - alpha_align_insns (insns, 16, alphaev5_next_group, - alphaev5_next_nop, EV5_E01 | EV5_E0); - } -#endif -} - - -/* Check a floating-point value for validity for a particular machine mode. */ - -static char * const float_strings[] = -{ - /* These are for FLOAT_VAX. */ - "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */ - "-1.70141173319264430e+38", - "2.93873587705571877e-39", /* 2^-128 */ - "-2.93873587705571877e-39", - /* These are for the default broken IEEE mode, which traps - on infinity or denormal numbers. */ - "3.402823466385288598117e+38", /* 2^128 (1 - 2^-24) */ - "-3.402823466385288598117e+38", - "1.1754943508222875079687e-38", /* 2^-126 */ - "-1.1754943508222875079687e-38", -}; - -static REAL_VALUE_TYPE float_values[8]; -static int inited_float_values = 0; - -int -check_float_value (mode, d, overflow) - enum machine_mode mode; - REAL_VALUE_TYPE *d; - int overflow ATTRIBUTE_UNUSED; -{ - - if (TARGET_IEEE || TARGET_IEEE_CONFORMANT || TARGET_IEEE_WITH_INEXACT) - return 0; - - if (inited_float_values == 0) - { - int i; - for (i = 0; i < 8; i++) - float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode); - - inited_float_values = 1; - } - - if (mode == SFmode) - { - REAL_VALUE_TYPE r; - REAL_VALUE_TYPE *fvptr; - - if (TARGET_FLOAT_VAX) - fvptr = &float_values[0]; - else - fvptr = &float_values[4]; - - bcopy ((char *) d, (char *) &r, sizeof (REAL_VALUE_TYPE)); - if (REAL_VALUES_LESS (fvptr[0], r)) - { - bcopy ((char *) &fvptr[0], (char *) d, - sizeof (REAL_VALUE_TYPE)); - return 1; - } - else if (REAL_VALUES_LESS (r, fvptr[1])) - { - bcopy ((char *) &fvptr[1], (char *) d, - sizeof (REAL_VALUE_TYPE)); - return 1; - } - else if (REAL_VALUES_LESS (dconst0, r) - && REAL_VALUES_LESS (r, fvptr[2])) - { - bcopy ((char *) &dconst0, (char *) d, sizeof (REAL_VALUE_TYPE)); - return 1; - } - else if (REAL_VALUES_LESS (r, dconst0) - && REAL_VALUES_LESS (fvptr[3], r)) - { - bcopy ((char *) &dconst0, (char *) d, sizeof (REAL_VALUE_TYPE)); - return 1; - } - } - - return 0; -} - -#if OPEN_VMS - -/* Return the VMS argument type corresponding to MODE. */ - -enum avms_arg_type -alpha_arg_type (mode) - enum machine_mode mode; -{ - switch (mode) - { - case SFmode: - return TARGET_FLOAT_VAX ? FF : FS; - case DFmode: - return TARGET_FLOAT_VAX ? FD : FT; - default: - return I64; - } -} - -/* Return an rtx for an integer representing the VMS Argument Information - register value. */ - -struct rtx_def * -alpha_arg_info_reg_val (cum) - CUMULATIVE_ARGS cum; -{ - unsigned HOST_WIDE_INT regval = cum.num_args; - int i; - - for (i = 0; i < 6; i++) - regval |= ((int) cum.atypes[i]) << (i * 3 + 8); - - return GEN_INT (regval); -} - -/* Structure to collect function names for final output - in link section. */ - -enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN}; - - -struct alpha_links { - struct alpha_links *next; - char *name; - enum links_kind kind; -}; - -static struct alpha_links *alpha_links_base = 0; - -/* Make (or fake) .linkage entry for function call. - - IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. */ - -void -alpha_need_linkage (name, is_local) - char *name; - int is_local; -{ - rtx x; - struct alpha_links *lptr, *nptr; - - if (name[0] == '*') - name++; - - /* Is this name already defined ? */ - - for (lptr = alpha_links_base; lptr; lptr = lptr->next) - if (strcmp (lptr->name, name) == 0) - { - if (is_local) - { - /* Defined here but external assumed. */ - if (lptr->kind == KIND_EXTERN) - lptr->kind = KIND_LOCAL; - } - else - { - /* Used here but unused assumed. */ - if (lptr->kind == KIND_UNUSED) - lptr->kind = KIND_LOCAL; - } - return; - } - - nptr = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); - nptr->next = alpha_links_base; - nptr->name = xstrdup (name); - - /* Assume external if no definition. */ - nptr->kind = (is_local ? KIND_UNUSED : KIND_EXTERN); - - /* Ensure we have an IDENTIFIER so assemble_name can mark is used. */ - get_identifier (name); - - alpha_links_base = nptr; - - return; -} - - -void -alpha_write_linkage (stream) - FILE *stream; -{ - struct alpha_links *lptr, *nptr; - - readonly_section (); - - fprintf (stream, "\t.align 3\n"); - - for (lptr = alpha_links_base; lptr; lptr = nptr) - { - nptr = lptr->next; - - if (lptr->kind == KIND_UNUSED - || ! TREE_SYMBOL_REFERENCED (get_identifier (lptr->name))) - continue; - - fprintf (stream, "$%s..lk:\n", lptr->name); - if (lptr->kind == KIND_LOCAL) - { - /* Local and used, build linkage pair. */ - fprintf (stream, "\t.quad %s..en\n", lptr->name); - fprintf (stream, "\t.quad %s\n", lptr->name); - } - else - /* External and used, request linkage pair. */ - fprintf (stream, "\t.linkage %s\n", lptr->name); - } -} - -#else - -void -alpha_need_linkage (name, is_local) - char *name ATTRIBUTE_UNUSED; - int is_local ATTRIBUTE_UNUSED; -{ -} - -#endif /* OPEN_VMS */ diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h deleted file mode 100755 index dc9f3d3..0000000 --- a/gcc/config/alpha/alpha.h +++ /dev/null @@ -1,2518 +0,0 @@ -/* Definitions of target machine for GNU compiler, for DEC Alpha. - Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -/* Write out the correct language type definition for the header files. - Unless we have assembler language, write out the symbols for C. */ -#define CPP_SPEC "\ -%{!undef:\ -%{.S:-D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY }}\ -%{.cc|.cxx|.C:-D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus }\ -%{.m:-D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C }\ -%{!.S:%{!.cc:%{!.cxx:%{!.C:%{!.m:-D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C }}}}}}\ -%{mieee:-D_IEEE_FP }\ -%{mieee-with-inexact:-D_IEEE_FP -D_IEEE_FP_INEXACT }}\ -%(cpp_cpu) %(cpp_subtarget)" - -#ifndef CPP_SUBTARGET_SPEC -#define CPP_SUBTARGET_SPEC "" -#endif - -/* Set the spec to use for signed char. The default tests the above macro - but DEC's compiler can't handle the conditional in a "constant" - operand. */ - -#define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" - -#define WORD_SWITCH_TAKES_ARG(STR) \ - (!strcmp (STR, "rpath") || !strcmp (STR, "include") \ - || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \ - || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \ - || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \ - || !strcmp (STR, "isystem")) - -/* Print subsidiary information on the compiler version in use. */ -#define TARGET_VERSION - -/* Run-time compilation parameters selecting different hardware subsets. */ - -/* Which processor to schedule for. The cpu attribute defines a list that - mirrors this list, so changes to alpha.md must be made at the same time. */ - -enum processor_type - {PROCESSOR_EV4, /* 2106[46]{a,} */ - PROCESSOR_EV5, /* 21164{a,pc,} */ - PROCESSOR_EV6}; /* 21264 */ - -extern enum processor_type alpha_cpu; - -enum alpha_trap_precision -{ - ALPHA_TP_PROG, /* No precision (default). */ - ALPHA_TP_FUNC, /* Trap contained within originating function. */ - ALPHA_TP_INSN /* Instruction accuracy and code is resumption safe. */ -}; - -enum alpha_fp_rounding_mode -{ - ALPHA_FPRM_NORM, /* Normal rounding mode. */ - ALPHA_FPRM_MINF, /* Round towards minus-infinity. */ - ALPHA_FPRM_CHOP, /* Chopped rounding mode (towards 0). */ - ALPHA_FPRM_DYN /* Dynamic rounding mode. */ -}; - -enum alpha_fp_trap_mode -{ - ALPHA_FPTM_N, /* Normal trap mode. */ - ALPHA_FPTM_U, /* Underflow traps enabled. */ - ALPHA_FPTM_SU, /* Software completion, w/underflow traps */ - ALPHA_FPTM_SUI /* Software completion, w/underflow & inexact traps */ -}; - -extern int target_flags; - -extern enum alpha_trap_precision alpha_tp; -extern enum alpha_fp_rounding_mode alpha_fprm; -extern enum alpha_fp_trap_mode alpha_fptm; - -/* This means that floating-point support exists in the target implementation - of the Alpha architecture. This is usually the default. */ - -#define MASK_FP 1 -#define TARGET_FP (target_flags & MASK_FP) - -/* This means that floating-point registers are allowed to be used. Note - that Alpha implementations without FP operations are required to - provide the FP registers. */ - -#define MASK_FPREGS 2 -#define TARGET_FPREGS (target_flags & MASK_FPREGS) - -/* This means that gas is used to process the assembler file. */ - -#define MASK_GAS 4 -#define TARGET_GAS (target_flags & MASK_GAS) - -/* This means that we should mark procedures as IEEE conformant. */ - -#define MASK_IEEE_CONFORMANT 8 -#define TARGET_IEEE_CONFORMANT (target_flags & MASK_IEEE_CONFORMANT) - -/* This means we should be IEEE-compliant except for inexact. */ - -#define MASK_IEEE 16 -#define TARGET_IEEE (target_flags & MASK_IEEE) - -/* This means we should be fully IEEE-compliant. */ - -#define MASK_IEEE_WITH_INEXACT 32 -#define TARGET_IEEE_WITH_INEXACT (target_flags & MASK_IEEE_WITH_INEXACT) - -/* This means we must construct all constants rather than emitting - them as literal data. */ - -#define MASK_BUILD_CONSTANTS 128 -#define TARGET_BUILD_CONSTANTS (target_flags & MASK_BUILD_CONSTANTS) - -/* This means we handle floating points in VAX F- (float) - or G- (double) Format. */ - -#define MASK_FLOAT_VAX 512 -#define TARGET_FLOAT_VAX (target_flags & MASK_FLOAT_VAX) - -/* This means that the processor has byte and half word loads and stores - (the BWX extension). */ - -#define MASK_BWX 1024 -#define TARGET_BWX (target_flags & MASK_BWX) - -/* This means that the processor has the CIX extension. */ -#define MASK_CIX 2048 -#define TARGET_CIX (target_flags & MASK_CIX) - -/* This means that the processor has the MAX extension. */ -#define MASK_MAX 4096 -#define TARGET_MAX (target_flags & MASK_MAX) - -/* This means that the processor is an EV5, EV56, or PCA56. This is defined - only in TARGET_CPU_DEFAULT. */ -#define MASK_CPU_EV5 8192 - -/* Likewise for EV6. */ -#define MASK_CPU_EV6 16384 - -/* This means we support the .arch directive in the assembler. Only - defined in TARGET_CPU_DEFAULT. */ -#define MASK_SUPPORT_ARCH 32768 -#define TARGET_SUPPORT_ARCH (target_flags & MASK_SUPPORT_ARCH) - -/* These are for target os support and cannot be changed at runtime. */ -#ifndef TARGET_WINDOWS_NT -#define TARGET_WINDOWS_NT 0 -#endif -#ifndef TARGET_OPEN_VMS -#define TARGET_OPEN_VMS 0 -#endif - -#ifndef TARGET_AS_CAN_SUBTRACT_LABELS -#define TARGET_AS_CAN_SUBTRACT_LABELS TARGET_GAS -#endif -#ifndef TARGET_CAN_FAULT_IN_PROLOGUE -#define TARGET_CAN_FAULT_IN_PROLOGUE 0 -#endif - -/* 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 \ - { {"no-soft-float", MASK_FP, "Use hardware fp"}, \ - {"soft-float", - MASK_FP, "Do not use hardware fp"}, \ - {"fp-regs", MASK_FPREGS, "Use fp registers"}, \ - {"no-fp-regs", - (MASK_FP|MASK_FPREGS), "Do not use fp registers"}, \ - {"alpha-as", -MASK_GAS, "Do not assume GAS"}, \ - {"gas", MASK_GAS, "Assume GAS"}, \ - {"ieee-conformant", MASK_IEEE_CONFORMANT, \ - "Request IEEE-conformant math library routines (OSF/1)"}, \ - {"ieee", MASK_IEEE|MASK_IEEE_CONFORMANT, \ - "Emit IEEE-conformant code, without inexact exceptions"}, \ - {"ieee-with-inexact", MASK_IEEE_WITH_INEXACT|MASK_IEEE_CONFORMANT, \ - "Emit IEEE-conformant code, with inexact exceptions"}, \ - {"build-constants", MASK_BUILD_CONSTANTS, \ - "Do not emit complex integer constants to read-only memory"}, \ - {"float-vax", MASK_FLOAT_VAX, "Use VAX fp"}, \ - {"float-ieee", -MASK_FLOAT_VAX, "Do not use VAX fp"}, \ - {"bwx", MASK_BWX, "Emit code for the byte/word ISA extension"}, \ - {"no-bwx", -MASK_BWX, ""}, \ - {"cix", MASK_CIX, "Emit code for the counting ISA extension"}, \ - {"no-cix", -MASK_CIX, ""}, \ - {"max", MASK_MAX, "Emit code for the motion video ISA extension"}, \ - {"no-max", -MASK_MAX, ""}, \ - {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT, ""} } - -#define TARGET_DEFAULT MASK_FP|MASK_FPREGS - -#ifndef TARGET_CPU_DEFAULT -#define TARGET_CPU_DEFAULT 0 -#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. - - Each subgrouping contains a string constant, that defines the fixed - part of the option name, and the address of a variable. The - variable, type `char *', is set to the variable part of the given - option if the fixed part matches. The actual option name is made - by appending `-m' to the specified name. - - Here is an example which defines `-mshort-data-NUMBER'. If the - given option is `-mshort-data-512', the variable `m88k_short_data' - will be set to the string `"512"'. - - extern char *m88k_short_data; - #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ - -extern char *alpha_cpu_string; /* For -mcpu= */ -extern char *alpha_fprm_string; /* For -mfp-rounding-mode=[n|m|c|d] */ -extern char *alpha_fptm_string; /* For -mfp-trap-mode=[n|u|su|sui] */ -extern char *alpha_tp_string; /* For -mtrap-precision=[p|f|i] */ -extern char *alpha_mlat_string; /* For -mmemory-latency= */ - -#define TARGET_OPTIONS \ -{ \ - {"cpu=", &alpha_cpu_string, \ - "Generate code for a given CPU"}, \ - {"fp-rounding-mode=", &alpha_fprm_string, \ - "Control the generated fp rounding mode"}, \ - {"fp-trap-mode=", &alpha_fptm_string, \ - "Control the IEEE trap mode"}, \ - {"trap-precision=", &alpha_tp_string, \ - "Control the precision given to fp exceptions"}, \ - {"memory-latency=", &alpha_mlat_string, \ - "Tune expected memory latency"}, \ -} - -/* Attempt to describe CPU characteristics to the preprocessor. */ - -/* Corresponding to amask... */ -#define CPP_AM_BWX_SPEC "-D__alpha_bwx__ -Acpu(bwx)" -#define CPP_AM_MAX_SPEC "-D__alpha_max__ -Acpu(max)" -#define CPP_AM_CIX_SPEC "-D__alpha_cix__ -Acpu(cix)" - -/* Corresponding to implver... */ -#define CPP_IM_EV4_SPEC "-D__alpha_ev4__ -Acpu(ev4)" -#define CPP_IM_EV5_SPEC "-D__alpha_ev5__ -Acpu(ev5)" -#define CPP_IM_EV6_SPEC "-D__alpha_ev6__ -Acpu(ev6)" - -/* Common combinations. */ -#define CPP_CPU_EV4_SPEC "%(cpp_im_ev4)" -#define CPP_CPU_EV5_SPEC "%(cpp_im_ev5)" -#define CPP_CPU_EV56_SPEC "%(cpp_im_ev5) %(cpp_am_bwx)" -#define CPP_CPU_PCA56_SPEC "%(cpp_im_ev5) %(cpp_am_bwx) %(cpp_am_max)" -#define CPP_CPU_EV6_SPEC "%(cpp_im_ev6) %(cpp_am_bwx) %(cpp_am_max) %(cpp_am_cix)" - -#ifndef CPP_CPU_DEFAULT_SPEC -# if TARGET_CPU_DEFAULT & MASK_CPU_EV6 -# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV6_SPEC -# else -# if TARGET_CPU_DEFAULT & MASK_CPU_EV5 -# if TARGET_CPU_DEFAULT & MASK_MAX -# define CPP_CPU_DEFAULT_SPEC CPP_CPU_PCA56_SPEC -# else -# if TARGET_CPU_DEFAULT & MASK_BWX -# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV56_SPEC -# else -# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV5_SPEC -# endif -# endif -# else -# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV4_SPEC -# endif -# endif -#endif /* CPP_CPU_DEFAULT_SPEC */ - -#ifndef CPP_CPU_SPEC -#define CPP_CPU_SPEC "\ -%{!undef:-Acpu(alpha) -Amachine(alpha) -D__alpha -D__alpha__ \ -%{mcpu=ev4|mcpu=21064:%(cpp_cpu_ev4) }\ -%{mcpu=ev5|mcpu=21164:%(cpp_cpu_ev5) }\ -%{mcpu=ev56|mcpu=21164a:%(cpp_cpu_ev56) }\ -%{mcpu=pca56|mcpu=21164pc|mcpu=21164PC:%(cpp_cpu_pca56) }\ -%{mcpu=ev6|mcpu=21264:%(cpp_cpu_ev6) }\ -%{!mcpu*:%(cpp_cpu_default) }}" -#endif - -/* 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 GNU CC driver - program. - - Do not define this macro if it does not need to do anything. */ - -#ifndef SUBTARGET_EXTRA_SPECS -#define SUBTARGET_EXTRA_SPECS -#endif - -#define EXTRA_SPECS \ - { "cpp_am_bwx", CPP_AM_BWX_SPEC }, \ - { "cpp_am_max", CPP_AM_MAX_SPEC }, \ - { "cpp_am_cix", CPP_AM_CIX_SPEC }, \ - { "cpp_im_ev4", CPP_IM_EV4_SPEC }, \ - { "cpp_im_ev5", CPP_IM_EV5_SPEC }, \ - { "cpp_im_ev6", CPP_IM_EV6_SPEC }, \ - { "cpp_cpu_ev4", CPP_CPU_EV4_SPEC }, \ - { "cpp_cpu_ev5", CPP_CPU_EV5_SPEC }, \ - { "cpp_cpu_ev56", CPP_CPU_EV56_SPEC }, \ - { "cpp_cpu_pca56", CPP_CPU_PCA56_SPEC }, \ - { "cpp_cpu_ev6", CPP_CPU_EV6_SPEC }, \ - { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \ - { "cpp_cpu", CPP_CPU_SPEC }, \ - { "cpp_subtarget", CPP_SUBTARGET_SPEC }, \ - SUBTARGET_EXTRA_SPECS - - -/* Sometimes certain combinations of command options do not make sense - on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. - - On the Alpha, it is used to translate target-option strings into - numeric values. */ - -extern void override_options (); -#define OVERRIDE_OPTIONS override_options () - - -/* Define this macro to change register usage conditional on target flags. - - On the Alpha, we use this to disable the floating-point registers when - they don't exist. */ - -#define CONDITIONAL_REGISTER_USAGE \ - if (! TARGET_FPREGS) \ - for (i = 32; i < 63; i++) \ - fixed_regs[i] = call_used_regs[i] = 1; - -/* Show we can debug even without a frame pointer. */ -#define CAN_DEBUG_WITHOUT_FP - -/* target machine storage layout */ - -/* Define to enable software floating point emulation. */ -#define REAL_ARITHMETIC - -/* The following #defines are used when compiling the routines in - libgcc1.c. Since the Alpha calling conventions require single - precision floats to be passed in the floating-point registers - (rather than in the general registers) we have to build the - libgcc1.c routines in such a way that they know the actual types - of their formal arguments and the actual types of their return - values. Otherwise, gcc will generate calls to the libgcc1.c - routines, passing arguments in the floating-point registers, - but the libgcc1.c routines will expect their arguments on the - stack (where the Alpha calling conventions require structs & - unions to be passed). */ - -#define FLOAT_VALUE_TYPE double -#define INTIFY(FLOATVAL) (FLOATVAL) -#define FLOATIFY(INTVAL) (INTVAL) -#define FLOAT_ARG_TYPE double - -/* Define the size of `int'. The default is the same as the word size. */ -#define INT_TYPE_SIZE 32 - -/* Define the size of `long long'. The default is the twice the word size. */ -#define LONG_LONG_TYPE_SIZE 64 - -/* The two floating-point formats we support are S-floating, which is - 4 bytes, and T-floating, which is 8 bytes. `float' is S and `double' - and `long double' are T. */ - -#define FLOAT_TYPE_SIZE 32 -#define DOUBLE_TYPE_SIZE 64 -#define LONG_DOUBLE_TYPE_SIZE 64 - -#define WCHAR_TYPE "unsigned int" -#define WCHAR_TYPE_SIZE 32 - -/* 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. - - For Alpha, we always store objects in a full register. 32-bit objects - are always sign-extended, but smaller objects retain their signedness. */ - -#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) = DImode; \ - } - -/* Define this if function arguments should also be promoted using the above - procedure. */ - -#define PROMOTE_FUNCTION_ARGS - -/* Likewise, if the function return value is promoted. */ - -#define PROMOTE_FUNCTION_RETURN - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. - - There are no such instructions on the Alpha, but the documentation - is little endian. */ -#define BITS_BIG_ENDIAN 0 - -/* Define this if most significant byte of a word is the lowest numbered. - This is false on the Alpha. */ -#define BYTES_BIG_ENDIAN 0 - -/* Define this if most significant word of a multiword number is lowest - numbered. - - For Alpha we can decide arbitrarily since there are no machine instructions - for them. Might as well be consistent with bytes. */ -#define WORDS_BIG_ENDIAN 0 - -/* number of bits in an addressable storage unit */ -#define BITS_PER_UNIT 8 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; - if using 16-bit ints on a 68000, this would still be 32. - But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 64 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 8 - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 64 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 64 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 64 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 256 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 64 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* A bitfield declared as `int' forces `int' alignment for the struct. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* Align loop starts for optimal branching. - - ??? Kludge this and the next macro for the moment by not doing anything if - we don't optimize and also if we are writing ECOFF symbols to work around - a bug in DEC's assembler. */ - -#define LOOP_ALIGN(LABEL) \ - (optimize > 0 && write_symbols != SDB_DEBUG ? 4 : 0) - -/* This is how to align an instruction for optimal branching. On - Alpha we'll get better performance by aligning on an octaword - boundary. */ - -#define LABEL_ALIGN_AFTER_BARRIER(FILE) \ - (optimize > 0 && write_symbols != SDB_DEBUG ? 4 : 0) - -/* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 64 - -/* For atomic access to objects, must have at least 32-bit alignment - unless the machine has byte operations. */ -#define MINIMUM_ATOMIC_ALIGNMENT (TARGET_BWX ? 8 : 32) - -/* Align all constants and variables to at least a word boundary so - we can pick up pieces of them faster. */ -/* ??? Only if block-move stuff knows about different source/destination - alignment. */ -#if 0 -#define CONSTANT_ALIGNMENT(EXP, ALIGN) MAX ((ALIGN), BITS_PER_WORD) -#define DATA_ALIGNMENT(EXP, ALIGN) MAX ((ALIGN), BITS_PER_WORD) -#endif - -/* Set this non-zero if move instructions will actually fail to work - when given unaligned data. - - Since we get an error message when we do one, call them invalid. */ - -#define STRICT_ALIGNMENT 1 - -/* Set this non-zero if unaligned move instructions are extremely slow. - - On the Alpha, they trap. */ - -#define SLOW_UNALIGNED_ACCESS 1 - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. - - We define all 32 integer registers, even though $31 is always zero, - and all 32 floating-point registers, even though $f31 is also - always zero. We do not bother defining the FP status register and - there are no other registers. - - Since $31 is always zero, we will use register number 31 as the - argument pointer. It will never appear in the generated code - because we will always be eliminating it in favor of the stack - pointer or hardware frame pointer. - - Likewise, we use $f31 for the frame pointer, which will always - be eliminated in favor of the hardware frame pointer or the - stack pointer. */ - -#define FIRST_PSEUDO_REGISTER 64 - -/* 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, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. */ -#define CALL_USED_REGISTERS \ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, \ - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } - -/* List the order in which to allocate registers. Each register must be - listed once, even those in FIXED_REGISTERS. - - We allocate in the following order: - $f10-$f15 (nonsaved floating-point register) - $f22-$f30 (likewise) - $f21-$f16 (likewise, but input args) - $f0 (nonsaved, but return value) - $f1 (nonsaved, but immediate before saved) - $f2-$f9 (saved floating-point registers) - $1-$8 (nonsaved integer registers) - $22-$25 (likewise) - $28 (likewise) - $0 (likewise, but return value) - $21-$16 (likewise, but input args) - $27 (procedure value in OSF, nonsaved in NT) - $9-$14 (saved integer registers) - $26 (return PC) - $15 (frame pointer) - $29 (global pointer) - $30, $31, $f31 (stack pointer and always zero/ap & fp) */ - -#define REG_ALLOC_ORDER \ - {42, 43, 44, 45, 46, 47, \ - 54, 55, 56, 57, 58, 59, 60, 61, 62, \ - 53, 52, 51, 50, 49, 48, \ - 32, 33, \ - 34, 35, 36, 37, 38, 39, 40, 41, \ - 1, 2, 3, 4, 5, 6, 7, 8, \ - 22, 23, 24, 25, \ - 28, \ - 0, \ - 21, 20, 19, 18, 17, 16, \ - 27, \ - 9, 10, 11, 12, 13, 14, \ - 26, \ - 15, \ - 29, \ - 30, 31, 63 } - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - On Alpha, the integer registers can hold any mode. The floating-point - registers can hold 32-bit and 64-bit integers as well, but not 16-bit - or 8-bit values. If we only allowed the larger integers into FP registers, - we'd have to say that QImode and SImode aren't tiable, which is a - pain. So say all registers can hold everything and see how that works. */ - -#define HARD_REGNO_MODE_OK(REGNO, MODE) 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, - for any hard reg, then this must be 0 for correct output. */ - -#define MODES_TIEABLE_P(MODE1, MODE2) 1 - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* Alpha 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 30 - -/* Base register for access to local variables of the function. */ -#define HARD_FRAME_POINTER_REGNUM 15 - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms - may be accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED 0 - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM 31 - -/* Base register for access to local variables of function. */ -#define FRAME_POINTER_REGNUM 63 - -/* Register in which static-chain is passed to a function. - - For the Alpha, this is based on an example; the calling sequence - doesn't seem to specify this. */ -#define STATIC_CHAIN_REGNUM 1 - -/* Register in which address to store a structure value - arrives in the function. On the Alpha, the address is passed - as a hidden argument. */ -#define STRUCT_VALUE 0 - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, - LIM_REG_CLASSES }; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ - {"NO_REGS", "GENERAL_REGS", "FLOAT_REGS", "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS \ - { {0, 0}, {~0, 0x80000000}, {0, 0x7fffffff}, {~0, ~0} } - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) \ - ((REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS : GENERAL_REGS) - -/* The class value for index registers, and the one for base regs. */ -#define INDEX_REG_CLASS NO_REGS -#define BASE_REG_CLASS GENERAL_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) \ - ((C) == 'f' ? FLOAT_REGS : NO_REGS) - -/* Define this macro to change register usage conditional on target flags. */ -/* #define CONDITIONAL_REGISTER_USAGE */ - -/* The letters I, J, K, L, M, N, O, 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. - - For Alpha: - `I' is used for the range of constants most insns can contain. - `J' is the constant zero. - `K' is used for the constant in an LDA insn. - `L' is used for the constant in a LDAH insn. - `M' is used for the constants that can be AND'ed with using a ZAP insn. - `N' is used for complemented 8-bit constants. - `O' is used for negated 8-bit constants. - `P' is used for the constants 1, 2 and 3. */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VALUE) < 0x100 \ - : (C) == 'J' ? (VALUE) == 0 \ - : (C) == 'K' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000 \ - : (C) == 'L' ? (((VALUE) & 0xffff) == 0 \ - && (((VALUE)) >> 31 == -1 || (VALUE) >> 31 == 0)) \ - : (C) == 'M' ? zap_mask (VALUE) \ - : (C) == 'N' ? (unsigned HOST_WIDE_INT) (~ (VALUE)) < 0x100 \ - : (C) == 'O' ? (unsigned HOST_WIDE_INT) (- (VALUE)) < 0x100 \ - : (C) == 'P' ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 3 \ - : 0) - -/* Similar, but for floating or large integer constants, and defining letters - G and H. Here VALUE is the CONST_DOUBLE rtx itself. - - For Alpha, `G' is the floating-point constant zero. `H' is a CONST_DOUBLE - that is the operand of a ZAP insn. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \ - && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) \ - : (C) == 'H' ? (GET_MODE (VALUE) == VOIDmode \ - && zap_mask (CONST_DOUBLE_LOW (VALUE)) \ - && zap_mask (CONST_DOUBLE_HIGH (VALUE))) \ - : 0) - -/* Optional extra constraints for this machine. - - For the Alpha, `Q' means that this is a memory operand but not a - reference to an unaligned location. - - `R' is a SYMBOL_REF that has SYMBOL_REF_FLAG set or is the current - function. - - 'S' is a 6-bit constant (valid for a shift insn). */ - -#define EXTRA_CONSTRAINT(OP, C) \ - ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) != AND \ - : (C) == 'R' ? current_file_function_operand (OP, Pmode) \ - : (C) == 'S' ? (GET_CODE (OP) == CONST_INT \ - && (unsigned HOST_WIDE_INT) INTVAL (OP) < 64) \ - : 0) - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. - - On the Alpha, all constants except zero go into a floating-point - register via memory. */ - -#define PREFERRED_RELOAD_CLASS(X, CLASS) \ - (CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \ - ? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS : GENERAL_REGS)\ - : (CLASS)) - -/* Loading and storing HImode or QImode values to and from memory - usually requires a scratch register. The exceptions are loading - QImode and HImode from an aligned address to a general register - unless byte instructions are permitted. - We also cannot load an unaligned address or a paradoxical SUBREG into an - FP register. */ - -#define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,IN) \ -(((GET_CODE (IN) == MEM \ - || (GET_CODE (IN) == REG && REGNO (IN) >= FIRST_PSEUDO_REGISTER) \ - || (GET_CODE (IN) == SUBREG \ - && (GET_CODE (SUBREG_REG (IN)) == MEM \ - || (GET_CODE (SUBREG_REG (IN)) == REG \ - && REGNO (SUBREG_REG (IN)) >= FIRST_PSEUDO_REGISTER)))) \ - && (((CLASS) == FLOAT_REGS \ - && ((MODE) == SImode || (MODE) == HImode || (MODE) == QImode)) \ - || (((MODE) == QImode || (MODE) == HImode) \ - && ! TARGET_BWX && unaligned_memory_operand (IN, MODE)))) \ - ? GENERAL_REGS \ - : ((CLASS) == FLOAT_REGS && GET_CODE (IN) == MEM \ - && GET_CODE (XEXP (IN, 0)) == AND) ? GENERAL_REGS \ - : ((CLASS) == FLOAT_REGS && GET_CODE (IN) == SUBREG \ - && (GET_MODE_SIZE (GET_MODE (IN)) \ - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (IN))))) ? GENERAL_REGS \ - : NO_REGS) - -#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,OUT) \ -(((GET_CODE (OUT) == MEM \ - || (GET_CODE (OUT) == REG && REGNO (OUT) >= FIRST_PSEUDO_REGISTER) \ - || (GET_CODE (OUT) == SUBREG \ - && (GET_CODE (SUBREG_REG (OUT)) == MEM \ - || (GET_CODE (SUBREG_REG (OUT)) == REG \ - && REGNO (SUBREG_REG (OUT)) >= FIRST_PSEUDO_REGISTER)))) \ - && ((((MODE) == HImode || (MODE) == QImode) \ - && (! TARGET_BWX || (CLASS) == FLOAT_REGS)) \ - || ((MODE) == SImode && (CLASS) == FLOAT_REGS))) \ - ? GENERAL_REGS \ - : ((CLASS) == FLOAT_REGS && GET_CODE (OUT) == MEM \ - && GET_CODE (XEXP (OUT, 0)) == AND) ? GENERAL_REGS \ - : ((CLASS) == FLOAT_REGS && GET_CODE (OUT) == SUBREG \ - && (GET_MODE_SIZE (GET_MODE (OUT)) \ - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (OUT))))) ? GENERAL_REGS \ - : NO_REGS) - -/* If we are copying between general and FP registers, we need a memory - location unless the CIX extension is available. */ - -#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \ - (! TARGET_CIX && (CLASS1) != (CLASS2)) - -/* Specify the mode to be used for memory when a secondary memory - location is needed. If MODE is floating-point, use it. Otherwise, - widen to a word like the default. This is needed because we always - store integers in FP registers in quadword format. This whole - area is very tricky! */ -#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \ - (GET_MODE_CLASS (MODE) == MODE_FLOAT ? (MODE) \ - : GET_MODE_SIZE (MODE) >= 4 ? (MODE) \ - : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 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) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* If defined, gives a class of registers that cannot be used as the - operand of a SUBREG that changes the size of the object. */ - -#define CLASS_CANNOT_CHANGE_SIZE FLOAT_REGS - -/* Define the cost of moving between registers of various classes. Moving - between FLOAT_REGS and anything else except float regs is expensive. - In fact, we make it quite expensive because we really don't want to - do these moves unless it is clearly worth it. Optimizations may - reduce the impact of not being able to allocate a pseudo to a - hard register. */ - -#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ - (((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) \ - ? 2 \ - : TARGET_CIX ? 3 : 4+2*alpha_memory_latency) - -/* A C expressions returning the cost of moving data of MODE from a register to - or from memory. - - On the Alpha, bump this up a bit. */ - -extern int alpha_memory_latency; -#define MEMORY_MOVE_COST(MODE,CLASS,IN) (2*alpha_memory_latency) - -/* Provide the cost of a branch. Exact meaning under development. */ -#define BRANCH_COST 5 - -/* Adjust the cost of dependencies. */ - -#define ADJUST_COST(INSN,LINK,DEP,COST) \ - (COST) = alpha_adjust_cost (INSN, LINK, DEP, COST) - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -#define STACK_GROWS_DOWNWARD - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -/* #define FRAME_GROWS_DOWNWARD */ - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ - -#define STARTING_FRAME_OFFSET 0 - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. - On Alpha, don't define this because there are no push insns. */ -/* #define PUSH_ROUNDING(BYTES) */ - -/* Define this to be nonzero if stack checking is built into the ABI. */ -#define STACK_CHECK_BUILTIN 1 - -/* Define this if the maximum size of all the outgoing args is to be - accumulated and pushed during the prologue. The amount can be - found in the variable current_function_outgoing_args_size. */ -#define ACCUMULATE_OUTGOING_ARGS - -/* Offset of first parameter from the argument pointer register value. */ - -#define FIRST_PARM_OFFSET(FNDECL) 0 - -/* Definitions for register eliminations. - - We have two registers that can be eliminated on the Alpha. First, the - frame pointer register can often be eliminated in favor of the stack - pointer register. Secondly, the argument pointer register can always be - eliminated; it is replaced with either the stack or frame pointer. */ - -/* This is an array of structures. Each structure initializes one pair - of eliminable registers. The "from" register number is given first, - followed by "to". Eliminations of the same "from" register are listed - in order of preference. */ - -#define ELIMINABLE_REGS \ -{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} - -/* Given FROM and TO register numbers, say whether this elimination is allowed. - Frame pointer elimination is automatically handled. - - All eliminations are valid since the cases where FP can't be - eliminated are already handled. */ - -#define CAN_ELIMINATE(FROM, TO) 1 - -/* Round up to a multiple of 16 bytes. */ -#define ALPHA_ROUND(X) (((X) + 15) & ~ 15) - -/* Define the offset between two registers, one to be eliminated, and the other - its replacement, at the start of a routine. */ -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ if ((FROM) == FRAME_POINTER_REGNUM) \ - (OFFSET) = (ALPHA_ROUND (current_function_outgoing_args_size) \ - + alpha_sa_size ()); \ - else if ((FROM) == ARG_POINTER_REGNUM) \ - (OFFSET) = (ALPHA_ROUND (current_function_outgoing_args_size) \ - + alpha_sa_size () \ - + (ALPHA_ROUND (get_frame_size () \ - + current_function_pretend_args_size) \ - - current_function_pretend_args_size)); \ -} - -/* Define this if stack space is still allocated for a parameter passed - in a register. */ -/* #define REG_PARM_STACK_SPACE */ - -/* Value is the number of bytes of arguments automatically - popped when returning from a subroutine call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - SIZE is the number of bytes of arguments passed on the stack. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. - - On Alpha the value is found in $0 for integer functions and - $f0 for floating-point functions. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, \ - ((INTEGRAL_TYPE_P (VALTYPE) \ - && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \ - || POINTER_TYPE_P (VALTYPE)) \ - ? word_mode : TYPE_MODE (VALTYPE), \ - ((TARGET_FPREGS \ - && (TREE_CODE (VALTYPE) == REAL_TYPE \ - || TREE_CODE (VALTYPE) == COMPLEX_TYPE)) \ - ? 32 : 0)) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ - -#define LIBCALL_VALUE(MODE) \ - gen_rtx (REG, MODE, \ - (TARGET_FPREGS \ - && (GET_MODE_CLASS (MODE) == MODE_FLOAT \ - || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \ - ? 32 : 0)) - -/* The definition of this macro implies that there are cases where - a scalar value cannot be returned in registers. - - For the Alpha, any structure or union type is returned in memory, as - are integers whose size is larger than 64 bits. */ - -#define RETURN_IN_MEMORY(TYPE) \ - (TYPE_MODE (TYPE) == BLKmode \ - || (TREE_CODE (TYPE) == INTEGER_TYPE && TYPE_PRECISION (TYPE) > 64)) - -/* 1 if N is a possible register number for a function value - as seen by the caller. */ - -#define FUNCTION_VALUE_REGNO_P(N) \ - ((N) == 0 || (N) == 1 || (N) == 32 || (N) == 33) - -/* 1 if N is a possible register number for function argument passing. - On Alpha, these are $16-$21 and $f16-$f21. */ - -#define FUNCTION_ARG_REGNO_P(N) \ - (((N) >= 16 && (N) <= 21) || ((N) >= 16 + 32 && (N) <= 21 + 32)) - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. - - On Alpha, this is a single integer, which is a number of words - of arguments scanned so far. - Thus 6 or more means all following args should go on the stack. */ - -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ - -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) (CUM) = 0 - -/* Define intermediate macro to compute the size (in registers) of an argument - for the Alpha. */ - -#define ALPHA_ARG_SIZE(MODE, TYPE, NAMED) \ -((MODE) != BLKmode \ - ? (GET_MODE_SIZE (MODE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD \ - : (int_size_in_bytes (TYPE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD) - -/* 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) \ - if (MUST_PASS_IN_STACK (MODE, TYPE)) \ - (CUM) = 6; \ - else \ - (CUM) += ALPHA_ARG_SIZE (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). - - On Alpha the first 6 words of args are normally in registers - and the rest are pushed. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ -((CUM) < 6 && ! MUST_PASS_IN_STACK (MODE, TYPE) \ - ? gen_rtx(REG, (MODE), \ - (CUM) + 16 + ((TARGET_FPREGS \ - && (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \ - || GET_MODE_CLASS (MODE) == MODE_FLOAT)) \ - * 32)) \ - : 0) - -/* Specify the padding direction of arguments. - - On the Alpha, we must pad upwards in order to be able to pass args in - registers. */ - -#define FUNCTION_ARG_PADDING(MODE, TYPE) upward - -/* 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) \ -((CUM) < 6 && 6 < (CUM) + ALPHA_ARG_SIZE (MODE, TYPE, NAMED) \ - ? 6 - (CUM) : 0) - -/* Perform any needed actions needed for a function that is receiving a - variable number of arguments. - - CUM is as above. - - MODE and TYPE are the mode and type of the current parameter. - - PRETEND_SIZE is a variable that should be set to the amount of stack - that must be pushed by the prolog to pretend that our caller pushed - it. - - Normally, this macro will push all remaining incoming registers on the - stack and set PRETEND_SIZE to the length of the registers pushed. - - On the Alpha, we allocate space for all 12 arg registers, but only - push those that are remaining. - - However, if NO registers need to be saved, don't allocate any space. - This is not only because we won't need the space, but because AP includes - the current_pretend_args_size and we don't want to mess up any - ap-relative addresses already made. - - If we are not to use the floating-point registers, save the integer - registers where we would put the floating-point registers. This is - not the most efficient way to implement varargs with just one register - class, but it isn't worth doing anything more efficient in this rare - case. */ - - -#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \ -{ if ((CUM) < 6) \ - { \ - if (! (NO_RTL)) \ - { \ - move_block_from_reg \ - (16 + CUM, \ - gen_rtx (MEM, BLKmode, \ - plus_constant (virtual_incoming_args_rtx, \ - ((CUM) + 6)* UNITS_PER_WORD)), \ - 6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \ - move_block_from_reg \ - (16 + (TARGET_FPREGS ? 32 : 0) + CUM, \ - gen_rtx (MEM, BLKmode, \ - plus_constant (virtual_incoming_args_rtx, \ - (CUM) * UNITS_PER_WORD)), \ - 6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD); \ - emit_insn (gen_blockage ()); \ - } \ - PRETEND_SIZE = 12 * UNITS_PER_WORD; \ - } \ -} - -/* 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. Returns the place - where the output has been placed if it can be done and the insns have been - emitted. If it would take more than N insns, zero is returned and no - insns and emitted. */ -extern struct rtx_def *alpha_emit_set_const (); -extern struct rtx_def *alpha_emit_set_long_const (); -extern struct rtx_def *alpha_emit_conditional_branch (); -extern struct rtx_def *alpha_emit_conditional_move (); - -/* Generate necessary RTL for __builtin_saveregs(). - ARGLIST is the argument list; see expr.c. */ -extern struct rtx_def *alpha_builtin_saveregs (); -#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) alpha_builtin_saveregs (ARGLIST) - -/* 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 *alpha_compare_op0, *alpha_compare_op1; -extern int alpha_compare_fp_p; - -/* Define the information needed to modify the epilogue for EH. */ - -extern struct rtx_def *alpha_eh_epilogue_sp_ofs; - -/* Make (or fake) .linkage entry for function call. - IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. */ -extern void alpha_need_linkage (); - -/* This macro defines the start of an assembly comment. */ - -#define ASM_COMMENT_START " #" - -/* This macro produces the initial definition of a function. */ - -#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ - alpha_start_function(FILE,NAME,DECL); -extern void alpha_start_function (); - -/* This macro closes up a function definition for the assembler. */ - -#define ASM_DECLARE_FUNCTION_SIZE(FILE,NAME,DECL) \ - alpha_end_function(FILE,NAME,DECL) -extern void alpha_end_function (); - -/* This macro notes the end of the prologue. */ - -#define FUNCTION_END_PROLOGUE(FILE) output_end_prologue (FILE) -extern void output_end_prologue (); - -/* Output any profiling code before the prologue. */ - -#define PROFILE_BEFORE_PROLOGUE 1 - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. Under OSF/1, profiling is enabled - by simply passing -pg to the assembler and linker. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) - -/* Output assembler code to FILE to initialize this source file's - basic block profiling info, if that has not already been done. - This assumes that __bb_init_func doesn't garble a1-a5. */ - -#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \ - do { \ - ASM_OUTPUT_REG_PUSH (FILE, 16); \ - fputs ("\tlda $16,$PBX32\n", (FILE)); \ - fputs ("\tldq $26,0($16)\n", (FILE)); \ - fputs ("\tbne $26,1f\n", (FILE)); \ - fputs ("\tlda $27,__bb_init_func\n", (FILE)); \ - fputs ("\tjsr $26,($27),__bb_init_func\n", (FILE)); \ - fputs ("\tldgp $29,0($26)\n", (FILE)); \ - fputs ("1:\n", (FILE)); \ - ASM_OUTPUT_REG_POP (FILE, 16); \ - } while (0); - -/* Output assembler code to FILE to increment the entry-count for - the BLOCKNO'th basic block in this source file. */ - -#define BLOCK_PROFILER(FILE, BLOCKNO) \ - do { \ - int blockn = (BLOCKNO); \ - fputs ("\tsubq $30,16,$30\n", (FILE)); \ - fputs ("\tstq $26,0($30)\n", (FILE)); \ - fputs ("\tstq $27,8($30)\n", (FILE)); \ - fputs ("\tlda $26,$PBX34\n", (FILE)); \ - fprintf ((FILE), "\tldq $27,%d($26)\n", 8*blockn); \ - fputs ("\taddq $27,1,$27\n", (FILE)); \ - fprintf ((FILE), "\tstq $27,%d($26)\n", 8*blockn); \ - fputs ("\tldq $26,0($30)\n", (FILE)); \ - fputs ("\tldq $27,8($30)\n", (FILE)); \ - fputs ("\taddq $30,16,$30\n", (FILE)); \ - } while (0) - - -/* 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 - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. - - The trampoline should set the static chain pointer to value placed - into the trampoline and should branch to the specified routine. - Note that $27 has been set to the address of the trampoline, so we can - use it for addressability of the two data items. Trampolines are always - aligned to FUNCTION_BOUNDARY, which is 64 bits. */ - -#define TRAMPOLINE_TEMPLATE(FILE) \ -do { \ - fprintf (FILE, "\tldq $1,24($27)\n"); \ - fprintf (FILE, "\tldq $27,16($27)\n"); \ - fprintf (FILE, "\tjmp $31,($27),0\n"); \ - fprintf (FILE, "\tnop\n"); \ - fprintf (FILE, "\t.quad 0,0\n"); \ -} while (0) - -/* Section in which to place the trampoline. On Alpha, instructions - may only be placed in a text segment. */ - -#define TRAMPOLINE_SECTION text_section - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 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. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ - alpha_initialize_trampoline (TRAMP, FNADDR, CXT, 16, 24, 8) -extern void alpha_initialize_trampoline (); - -/* A C expression whose value is RTL representing the value of the return - address for the frame COUNT steps up from the current frame. - FRAMEADDR is the frame pointer of the COUNT frame, or the frame pointer of - the COUNT-1 frame if RETURN_ADDR_IN_PREVIOUS_FRAME is defined. */ - -#define RETURN_ADDR_RTX alpha_return_addr -extern struct rtx_def *alpha_return_addr (); - -/* Before the prologue, RA lives in $26. */ -#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 26) - -/* Initialize data used by insn expanders. This is called from insn_emit, - once for every function before code is generated. */ - -#define INIT_EXPANDERS alpha_init_expanders () -extern void alpha_init_expanders (); - -/* Addressing modes, and classification of registers for them. */ - -/* #define HAVE_POST_INCREMENT 0 */ -/* #define HAVE_POST_DECREMENT 0 */ - -/* #define HAVE_PRE_DECREMENT 0 */ -/* #define HAVE_PRE_INCREMENT 0 */ - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_INDEX_P(REGNO) 0 -#define REGNO_OK_FOR_BASE_P(REGNO) \ -((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32 \ - || (REGNO) == 63 || reg_renumber[REGNO] == 63) - -/* Maximum number of registers that can appear in a valid memory address. */ -#define MAX_REGS_PER_ADDRESS 1 - -/* Recognize any constant value that is a valid address. For the Alpha, - there are only constants none since we want to use LDA to load any - symbolic addresses into registers. */ - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == CONST_INT \ - && (unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000) - -/* Include all constant integers and constant doubles, but not - floating-point, except for floating-point zero. */ - -#define LEGITIMATE_CONSTANT_P(X) \ - (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ - || (X) == CONST0_RTX (GET_MODE (X))) - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) 0 -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) \ - (REGNO (X) < 32 || REGNO (X) == 63 || REGNO (X) >= FIRST_PSEUDO_REGISTER) - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - For Alpha, we have either a constant address or the sum of a register - and a constant address, or just a register. For DImode, any of those - forms can be surrounded with an AND that clear the low-order three bits; - this is an "unaligned" access. - - First define the basic valid address. */ - -#define GO_IF_LEGITIMATE_SIMPLE_ADDRESS(MODE, X, ADDR) \ -{ if (REG_P (X) && REG_OK_FOR_BASE_P (X)) \ - goto ADDR; \ - if (CONSTANT_ADDRESS_P (X)) \ - goto ADDR; \ - if (GET_CODE (X) == PLUS \ - && REG_P (XEXP (X, 0)) \ - && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ - && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ - goto ADDR; \ -} - -/* Now accept the simple address, or, for DImode only, an AND of a simple - address that turns off the low three bits. */ - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ GO_IF_LEGITIMATE_SIMPLE_ADDRESS (MODE, X, ADDR); \ - if ((MODE) == DImode \ - && GET_CODE (X) == AND \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && INTVAL (XEXP (X, 1)) == -8) \ - GO_IF_LEGITIMATE_SIMPLE_ADDRESS (MODE, XEXP (X, 0), ADDR); \ -} - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. - - For the Alpha, there are three cases we handle: - - (1) If the address is (plus reg const_int) and the CONST_INT is not a - valid offset, compute the high part of the constant and add it to the - register. Then our address is (plus temp low-part-const). - (2) If the address is (const (plus FOO const_int)), find the low-order - part of the CONST_INT. Then load FOO plus any high-order part of the - CONST_INT into a register. Our address is (plus reg low-part-const). - This is done to reduce the number of GOT entries. - (3) If we have a (plus reg const), emit the load as in (2), then add - the two registers, and finally generate (plus reg low-part-const) as - our address. */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -{ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && ! CONSTANT_ADDRESS_P (XEXP (X, 1))) \ - { \ - HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \ - HOST_WIDE_INT lowpart = (val & 0xffff) - 2 * (val & 0x8000); \ - HOST_WIDE_INT highpart = val - lowpart; \ - rtx high = GEN_INT (highpart); \ - rtx temp = expand_binop (Pmode, add_optab, XEXP (x, 0), \ - high, NULL_RTX, 1, OPTAB_LIB_WIDEN); \ - \ - (X) = plus_constant (temp, lowpart); \ - goto WIN; \ - } \ - else if (GET_CODE (X) == CONST \ - && GET_CODE (XEXP (X, 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT) \ - { \ - HOST_WIDE_INT val = INTVAL (XEXP (XEXP (X, 0), 1)); \ - HOST_WIDE_INT lowpart = (val & 0xffff) - 2 * (val & 0x8000); \ - HOST_WIDE_INT highpart = val - lowpart; \ - rtx high = XEXP (XEXP (X, 0), 0); \ - \ - if (highpart) \ - high = plus_constant (high, highpart); \ - \ - (X) = plus_constant (force_reg (Pmode, high), lowpart); \ - goto WIN; \ - } \ - else if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \ - && GET_CODE (XEXP (X, 1)) == CONST \ - && GET_CODE (XEXP (XEXP (X, 1), 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (XEXP (X, 1), 0), 1)) == CONST_INT) \ - { \ - HOST_WIDE_INT val = INTVAL (XEXP (XEXP (XEXP (X, 1), 0), 1)); \ - HOST_WIDE_INT lowpart = (val & 0xffff) - 2 * (val & 0x8000); \ - HOST_WIDE_INT highpart = val - lowpart; \ - rtx high = XEXP (XEXP (XEXP (X, 1), 0), 0); \ - \ - if (highpart) \ - high = plus_constant (high, highpart); \ - \ - high = expand_binop (Pmode, add_optab, XEXP (X, 0), \ - force_reg (Pmode, high), \ - high, 1, OPTAB_LIB_WIDEN); \ - (X) = plus_constant (high, lowpart); \ - 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. - - For the Alpha, we wish to handle large displacements off a base - register by splitting the addend across an ldah and the mem insn. - This cuts number of extra insns needed from 3 to 1. */ - -#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \ -do { \ - /* We must recognize output that we have already generated ourselves. */ \ - if (GET_CODE (X) == PLUS \ - && GET_CODE (XEXP (X, 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \ - && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ - && GET_CODE (XEXP (X, 1)) == CONST_INT) \ - { \ - push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \ - BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \ - OPNUM, TYPE); \ - goto WIN; \ - } \ - if (GET_CODE (X) == PLUS \ - && GET_CODE (XEXP (X, 0)) == REG \ - && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER \ - && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT) \ - { \ - 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; \ - \ - /* Check for 32-bit overflow. */ \ - if (high + low != val) \ - break; \ - \ - /* Reload the high part into a base reg; leave the low part \ - 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)); \ - \ - push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \ - BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \ - OPNUM, TYPE); \ - 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. - On the Alpha this is true only for the unaligned modes. We can - simplify this test since we know that the address must be valid. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ -{ if (GET_CODE (ADDR) == AND) goto LABEL; } - -/* Compute the cost of an address. For the Alpha, all valid addresses are - the same cost. */ - -#define ADDRESS_COST(X) 0 - -/* Machine-dependent reorg pass. */ -#define MACHINE_DEPENDENT_REORG(X) alpha_reorg(X) - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - - Do not define this if the table should contain absolute addresses. - On the Alpha, the table is really GP-relative, not relative to the PC - of the table, but we pretend that it is PC-relative; this should be OK, - but we should try to find some better way sometime. */ -#define CASE_VECTOR_PC_RELATIVE 1 - -/* Specify the tree operation to be used to convert reals to integers. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* This is the kind of divide that is easiest to do in the general case. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* This flag, if defined, says the same insns that convert to a signed fixnum - also convert validly to an unsigned one. - - We actually lie a bit here as overflow conditions are different. But - they aren't being checked anyway. */ - -#define FIXUNS_TRUNC_LIKE_FIX_TRUNC - -/* Max number of bytes we can move to or from memory - in one reasonably fast instruction. */ - -#define MOVE_MAX 8 - -/* If a memory-to-memory move would take MOVE_RATIO or more simple - move-instruction pairs, we will do a movstr or libcall instead. - - Without byte/word accesses, we want no more than four instructions; - with, several single byte accesses are better. */ - -#define MOVE_RATIO (TARGET_BWX ? 7 : 2) - -/* Largest number of bytes of an object that can be placed in a register. - On the Alpha we have plenty of registers, so use TImode. */ -#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TImode) - -/* Nonzero if access to memory by bytes is no faster than for words. - Also non-zero if doing byte operations (specifically shifts) in registers - is undesirable. - - On the Alpha, we want to not use the byte operation and instead use - masking operations to access fields; these will save instructions. */ - -#define SLOW_BYTE_ACCESS 1 - -/* Define if operations between registers always perform the operation - on the full register even if a narrower mode is specified. */ -#define WORD_REGISTER_OPERATIONS - -/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD - will either zero-extend or sign-extend. The value of this macro should - be the code that says which one of the two operations is implicitly - done, NIL if none. */ -#define LOAD_EXTEND_OP(MODE) ((MODE) == SImode ? SIGN_EXTEND : ZERO_EXTEND) - -/* Define if loading short immediate values into registers sign extends. */ -#define SHORT_IMMEDIATES_SIGN_EXTEND - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* We assume that the store-condition-codes instructions store 0 for false - and some other value for true. This is the value stored for true. */ - -#define STORE_FLAG_VALUE 1 - -/* Define the value returned by a floating-point comparison instruction. */ - -#define FLOAT_STORE_FLAG_VALUE (TARGET_FLOAT_VAX ? 0.5 : 2.0) - -/* Canonicalize a comparison from one we don't have to one we do have. */ - -#define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \ - do { \ - if (((CODE) == GE || (CODE) == GT || (CODE) == GEU || (CODE) == GTU) \ - && (GET_CODE (OP1) == REG || (OP1) == const0_rtx)) \ - { \ - rtx tem = (OP0); \ - (OP0) = (OP1); \ - (OP1) = tem; \ - (CODE) = swap_condition (CODE); \ - } \ - if (((CODE) == LT || (CODE) == LTU) \ - && GET_CODE (OP1) == CONST_INT && INTVAL (OP1) == 256) \ - { \ - (CODE) = (CODE) == LT ? LE : LEU; \ - (OP1) = GEN_INT (255); \ - } \ - } while (0) - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -#define Pmode DImode - -/* Mode of a function address in a call instruction (for indexing purposes). */ - -#define FUNCTION_MODE Pmode - -/* Define this if addresses of constant functions - shouldn't be put through pseudo regs where they can be cse'd. - Desirable on machines where ordinary constants are expensive - but a CALL with constant address is cheap. - - We define this on the Alpha so that gen_call and gen_call_value - get to see the SYMBOL_REF (for the hint field of the jsr). It will - then copy it into a register, thus actually letting the address be - cse'ed. */ - -#define NO_FUNCTION_CSE - -/* Define this to be nonzero if shift instructions ignore all but the low-order - few bits. */ -#define SHIFT_COUNT_TRUNCATED 1 - -/* Use atexit for static constructors/destructors, instead of defining - our own exit function. */ -#define HAVE_ATEXIT - -/* The EV4 is dual issue; EV5/EV6 are quad issue. */ -#define ISSUE_RATE (alpha_cpu == PROCESSOR_EV4 ? 2 : 4) - -/* Describe the fact that MULTI instructions are multiple instructions - and so to assume they don't pair with anything. */ -#define MD_SCHED_VARIABLE_ISSUE(DUMP, SCHED_VERBOSE, INSN, CAN_ISSUE_MORE) \ - if (recog_memoized (INSN) < 0 || get_attr_type (INSN) == TYPE_MULTI) \ - (CAN_ISSUE_MORE) = 0 - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. - - If this is an 8-bit constant, return zero since it can be used - nearly anywhere with no cost. If it is a valid operand for an - ADD or AND, likewise return 0 if we know it will be used in that - context. Otherwise, return 2 since it might be used there later. - All other constants take at least two insns. */ - -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - if (INTVAL (RTX) >= 0 && INTVAL (RTX) < 256) \ - return 0; \ - case CONST_DOUBLE: \ - if ((RTX) == CONST0_RTX (GET_MODE (RTX))) \ - return 0; \ - else if (((OUTER_CODE) == PLUS && add_operand (RTX, VOIDmode)) \ - || ((OUTER_CODE) == AND && and_operand (RTX, VOIDmode))) \ - return 0; \ - else if (add_operand (RTX, VOIDmode) || and_operand (RTX, VOIDmode)) \ - return 2; \ - else \ - return COSTS_N_INSNS (2); \ - case CONST: \ - case SYMBOL_REF: \ - case LABEL_REF: \ - switch (alpha_cpu) \ - { \ - case PROCESSOR_EV4: \ - return COSTS_N_INSNS (3); \ - case PROCESSOR_EV5: \ - case PROCESSOR_EV6: \ - return COSTS_N_INSNS (2); \ - default: abort(); \ - } - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. */ - -#define RTX_COSTS(X,CODE,OUTER_CODE) \ - case PLUS: case MINUS: \ - if (FLOAT_MODE_P (GET_MODE (X))) \ - switch (alpha_cpu) \ - { \ - case PROCESSOR_EV4: \ - return COSTS_N_INSNS (6); \ - case PROCESSOR_EV5: \ - case PROCESSOR_EV6: \ - return COSTS_N_INSNS (4); \ - default: abort(); \ - } \ - else if (GET_CODE (XEXP (X, 0)) == MULT \ - && const48_operand (XEXP (XEXP (X, 0), 1), VOIDmode)) \ - return (2 + rtx_cost (XEXP (XEXP (X, 0), 0), OUTER_CODE) \ - + rtx_cost (XEXP (X, 1), OUTER_CODE)); \ - break; \ - case MULT: \ - switch (alpha_cpu) \ - { \ - case PROCESSOR_EV4: \ - if (FLOAT_MODE_P (GET_MODE (X))) \ - return COSTS_N_INSNS (6); \ - return COSTS_N_INSNS (23); \ - case PROCESSOR_EV5: \ - if (FLOAT_MODE_P (GET_MODE (X))) \ - return COSTS_N_INSNS (4); \ - else if (GET_MODE (X) == DImode) \ - return COSTS_N_INSNS (12); \ - else \ - return COSTS_N_INSNS (8); \ - case PROCESSOR_EV6: \ - if (FLOAT_MODE_P (GET_MODE (X))) \ - return COSTS_N_INSNS (4); \ - else \ - return COSTS_N_INSNS (7); \ - default: abort(); \ - } \ - case ASHIFT: \ - if (GET_CODE (XEXP (X, 1)) == CONST_INT \ - && INTVAL (XEXP (X, 1)) <= 3) \ - break; \ - /* ... fall through ... */ \ - case ASHIFTRT: case LSHIFTRT: \ - switch (alpha_cpu) \ - { \ - case PROCESSOR_EV4: \ - return COSTS_N_INSNS (2); \ - case PROCESSOR_EV5: \ - case PROCESSOR_EV6: \ - return COSTS_N_INSNS (1); \ - default: abort(); \ - } \ - case IF_THEN_ELSE: \ - switch (alpha_cpu) \ - { \ - case PROCESSOR_EV4: \ - case PROCESSOR_EV6: \ - return COSTS_N_INSNS (2); \ - case PROCESSOR_EV5: \ - return COSTS_N_INSNS (1); \ - default: abort(); \ - } \ - case DIV: case UDIV: case MOD: case UMOD: \ - switch (alpha_cpu) \ - { \ - case PROCESSOR_EV4: \ - if (GET_MODE (X) == SFmode) \ - return COSTS_N_INSNS (34); \ - else if (GET_MODE (X) == DFmode) \ - return COSTS_N_INSNS (63); \ - else \ - return COSTS_N_INSNS (70); \ - case PROCESSOR_EV5: \ - if (GET_MODE (X) == SFmode) \ - return COSTS_N_INSNS (15); \ - else if (GET_MODE (X) == DFmode) \ - return COSTS_N_INSNS (22); \ - else \ - return COSTS_N_INSNS (70); /* ??? */ \ - case PROCESSOR_EV6: \ - if (GET_MODE (X) == SFmode) \ - return COSTS_N_INSNS (12); \ - else if (GET_MODE (X) == DFmode) \ - return COSTS_N_INSNS (15); \ - else \ - return COSTS_N_INSNS (70); /* ??? */ \ - default: abort(); \ - } \ - case MEM: \ - switch (alpha_cpu) \ - { \ - case PROCESSOR_EV4: \ - case PROCESSOR_EV6: \ - return COSTS_N_INSNS (3); \ - case PROCESSOR_EV5: \ - return COSTS_N_INSNS (2); \ - default: abort(); \ - } \ - case NEG: case ABS: \ - if (! FLOAT_MODE_P (GET_MODE (X))) \ - break; \ - /* ... fall through ... */ \ - case FLOAT: case UNSIGNED_FLOAT: case FIX: case UNSIGNED_FIX: \ - case FLOAT_EXTEND: case FLOAT_TRUNCATE: \ - switch (alpha_cpu) \ - { \ - case PROCESSOR_EV4: \ - return COSTS_N_INSNS (6); \ - case PROCESSOR_EV5: \ - case PROCESSOR_EV6: \ - return COSTS_N_INSNS (4); \ - default: abort(); \ - } - -/* Control the assembler format that we output. */ - -/* We don't emit these labels, so as to avoid getting linker errors about - missing exception handling info. If we emit a gcc_compiled. label into - text, and the file has no code, then the DEC assembler gives us a zero - sized text section with no associated exception handling info. The - DEC linker sees this text section, and gives a warning saying that - the exception handling info is missing. */ -#define ASM_IDENTIFY_GCC(x) -#define ASM_IDENTIFY_LANGUAGE(x) - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF "" - -#define TEXT_SECTION_ASM_OP ".text" - -/* Output before read-only data. */ - -#define READONLY_DATA_SECTION_ASM_OP ".rdata" - -/* Output before writable data. */ - -#define DATA_SECTION_ASM_OP ".data" - -/* Define an extra section for read-only data, a routine to enter it, and - indicate that it is for read-only data. - - The first time we enter the readonly data section for a file, we write - eight bytes of zero. This works around a bug in DEC's assembler in - some versions of OSF/1 V3.x. */ - -#define EXTRA_SECTIONS readonly_data - -#define EXTRA_SECTION_FUNCTIONS \ -void \ -literal_section () \ -{ \ - if (in_section != readonly_data) \ - { \ - static int firsttime = 1; \ - \ - fprintf (asm_out_file, "%s\n", READONLY_DATA_SECTION_ASM_OP); \ - if (firsttime) \ - { \ - firsttime = 0; \ - ASM_OUTPUT_DOUBLE_INT (asm_out_file, const0_rtx); \ - } \ - \ - in_section = readonly_data; \ - } \ -} \ - -#define READONLY_DATA_SECTION literal_section - -/* If we are referencing a function that is static, make the SYMBOL_REF - special. We use this to see indicate we can branch to this function - without setting PV or restoring GP. */ - -#define ENCODE_SECTION_INFO(DECL) \ - if (TREE_CODE (DECL) == FUNCTION_DECL && ! TREE_PUBLIC (DECL)) \ - SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \ - "$9", "$10", "$11", "$12", "$13", "$14", "$15", \ - "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", \ - "$24", "$25", "$26", "$27", "$28", "$29", "$30", "AP", \ - "$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", "FP"} - -/* How to renumber registers for dbx and gdb. */ - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* This is how to output the definition of a user-level label named NAME, - such as the label on a static function or variable NAME. */ - -#define ASM_OUTPUT_LABEL(FILE,NAME) \ - do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) - -/* This is how to output a command to make the user-level label named NAME - defined for reference from other files. */ - -#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ - do { fputs ("\t.globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) - -/* The prefix to add to user-visible assembler symbols. */ - -#define USER_LABEL_PREFIX "" - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ - -#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - fprintf (FILE, "$%s%d:\n", PREFIX, NUM) - -/* This is how to output a label for a jump table. Arguments are the same as - for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is - passed. */ - -#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \ -{ ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, 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. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf ((LABEL), "*$%s%ld", (PREFIX), (long)(NUM)) - -/* Check a floating-point value for validity for a particular machine mode. */ - -#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \ - ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW)) - -/* This is how to output an assembler line defining a `double' constant. */ - -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ - { \ - if (REAL_VALUE_ISINF (VALUE) \ - || REAL_VALUE_ISNAN (VALUE) \ - || REAL_VALUE_MINUS_ZERO (VALUE)) \ - { \ - long t[2]; \ - REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ - fprintf (FILE, "\t.quad 0x%lx%08lx\n", \ - t[1] & 0xffffffff, t[0] & 0xffffffff); \ - } \ - else \ - { \ - char str[30]; \ - REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", str); \ - fprintf (FILE, "\t.%c_floating %s\n", (TARGET_FLOAT_VAX)?'g':'t', str); \ - } \ - } - -/* This is how to output an assembler line defining a `float' constant. */ - -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ - do { \ - long t; \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ -} while (0) - -/* This is how to output an assembler line defining an `int' constant. */ - -#define ASM_OUTPUT_INT(FILE,VALUE) \ -( fprintf (FILE, "\t.long "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* This is how to output an assembler line defining a `long' constant. */ - -#define ASM_OUTPUT_DOUBLE_INT(FILE,VALUE) \ -( fprintf (FILE, "\t.quad "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* Likewise for `char' and `short' constants. */ - -#define ASM_OUTPUT_SHORT(FILE,VALUE) \ - fprintf (FILE, "\t.word %d\n", \ - (int)(GET_CODE (VALUE) == CONST_INT \ - ? INTVAL (VALUE) & 0xffff : (abort (), 0))) - -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ - fprintf (FILE, "\t.byte %d\n", \ - (int)(GET_CODE (VALUE) == CONST_INT \ - ? INTVAL (VALUE) & 0xff : (abort (), 0))) - -/* We use the default ASCII-output routine, except that we don't write more - than 50 characters since the assembler doesn't support very long lines. */ - -#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \ - do { \ - FILE *_hide_asm_out_file = (MYFILE); \ - unsigned char *_hide_p = (unsigned char *) (MYSTRING); \ - int _hide_thissize = (MYLENGTH); \ - int _size_so_far = 0; \ - { \ - FILE *asm_out_file = _hide_asm_out_file; \ - unsigned char *p = _hide_p; \ - int thissize = _hide_thissize; \ - int i; \ - fprintf (asm_out_file, "\t.ascii \""); \ - \ - for (i = 0; i < thissize; i++) \ - { \ - register int c = p[i]; \ - \ - if (_size_so_far ++ > 50 && i < thissize - 4) \ - _size_so_far = 0, fprintf (asm_out_file, "\"\n\t.ascii \""); \ - \ - if (c == '\"' || c == '\\') \ - putc ('\\', asm_out_file); \ - if (c >= ' ' && c < 0177) \ - putc (c, asm_out_file); \ - else \ - { \ - fprintf (asm_out_file, "\\%o", c); \ - /* After an octal-escape, if a digit follows, \ - terminate one string constant and start another. \ - The Vax assembler fails to stop reading the escape \ - after three digits, so this is the only way we \ - can get it to parse the data properly. */ \ - if (i < thissize - 1 \ - && p[i + 1] >= '0' && p[i + 1] <= '9') \ - _size_so_far = 0, fprintf (asm_out_file, "\"\n\t.ascii \""); \ - } \ - } \ - fprintf (asm_out_file, "\"\n"); \ - } \ - } \ - while (0) - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tsubq $30,8,$30\n\tst%s $%s%d,0($30)\n", \ - (REGNO) > 32 ? "t" : "q", (REGNO) > 32 ? "f" : "", \ - (REGNO) & 31); - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tld%s $%s%d,0($30)\n\taddq $30,8,$30\n", \ - (REGNO) > 32 ? "t" : "q", (REGNO) > 32 ? "f" : "", \ - (REGNO) & 31); - -/* This is how to output an assembler line for a numeric constant byte. */ - -#define ASM_OUTPUT_BYTE(FILE,VALUE) \ - fprintf (FILE, "\t.byte 0x%x\n", (int) ((VALUE) & 0xff)) - -/* This is how to output an element of a case-vector that is absolute. - (Alpha does not use such vectors, but we must define this macro anyway.) */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) abort () - -/* This is how to output an element of a case-vector that is relative. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\t.%s $L%d\n", TARGET_WINDOWS_NT ? "long" : "gprel32", \ - (VALUE)) - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - if ((LOG) != 0) \ - fprintf (FILE, "\t.align %d\n", LOG); - -/* This is how to advance the location counter by SIZE bytes. */ - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t.space %d\n", (SIZE)) - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs ("\t.comm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d\n", (SIZE))) - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE,ROUNDED) \ -( fputs ("\t.lcomm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d\n", (SIZE))) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) - -/* Define the parentheses used to group arithmetic operations - in assembler code. */ - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* Output code to add DELTA to the first argument, and then jump to FUNCTION. - Used for C++ multiple inheritance. */ - -#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \ -do { \ - char *fn_name = XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0); \ - int reg; \ - \ - /* Mark end of prologue. */ \ - output_end_prologue (FILE); \ - \ - /* Rely on the assembler to macro expand a large delta. */ \ - reg = aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) ? 17 : 16; \ - fprintf (FILE, "\tlda $%d,%ld($%d)\n", reg, (long)(DELTA), reg); \ - \ - if (current_file_function_operand (XEXP (DECL_RTL (FUNCTION), 0))) \ - { \ - fprintf (FILE, "\tbr $31,$"); \ - assemble_name (FILE, fn_name); \ - fprintf (FILE, "..ng\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tjmp $31,"); \ - assemble_name (FILE, fn_name); \ - fputc ('\n', FILE); \ - } \ -} while (0) - - -/* Define results of standard character escape sequences. */ -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. */ - -#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE) - -/* Determine which codes are valid without a following integer. These must - not be alphabetic (the characters are chosen so that - PRINT_OPERAND_PUNCT_VALID_P translates into a simple range change when - using ASCII). - - & Generates fp-rounding mode suffix: nothing for normal, 'c' for - chopped, 'm' for minus-infinity, and 'd' for dynamic rounding - mode. alpha_fprm controls which suffix is generated. - - ' Generates trap-mode suffix for instructions that accept the - su suffix only (cmpt et al). - - ` Generates trap-mode suffix for instructions that accept the - v and sv suffix. The only instruction that needs this is cvtql. - - ( Generates trap-mode suffix for instructions that accept the - v, sv, and svi suffix. The only instruction that needs this - is cvttq. - - ) Generates trap-mode suffix for instructions that accept the - u, su, and sui suffix. This is the bulk of the IEEE floating - point instructions (addt et al). - - + Generates trap-mode suffix for instructions that accept the - sui suffix (cvtqt and cvtqs). - - , Generates single precision suffix for floating point - instructions (s for IEEE, f for VAX) - - - Generates double precision suffix for floating point - instructions (t for IEEE, g for VAX) - */ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ - ((CODE) == '&' || (CODE) == '`' || (CODE) == '\'' || (CODE) == '(' \ - || (CODE) == ')' || (CODE) == '+' || (CODE) == ',' || (CODE) == '-') - -/* Print a memory address as an operand to reference that memory location. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ -{ rtx addr = (ADDR); \ - int basereg = 31; \ - HOST_WIDE_INT offset = 0; \ - \ - if (GET_CODE (addr) == AND) \ - addr = XEXP (addr, 0); \ - \ - if (GET_CODE (addr) == REG) \ - basereg = REGNO (addr); \ - else if (GET_CODE (addr) == CONST_INT) \ - offset = INTVAL (addr); \ - else if (GET_CODE (addr) == PLUS \ - && GET_CODE (XEXP (addr, 0)) == REG \ - && GET_CODE (XEXP (addr, 1)) == CONST_INT) \ - basereg = REGNO (XEXP (addr, 0)), offset = INTVAL (XEXP (addr, 1)); \ - else \ - abort (); \ - \ - fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, offset); \ - fprintf (FILE, "($%d)", basereg); \ -} -/* Define the codes that are matched by predicates in alpha.c. */ - -#define PREDICATE_CODES \ - {"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \ - {"reg_or_6bit_operand", {SUBREG, REG, CONST_INT}}, \ - {"reg_or_8bit_operand", {SUBREG, REG, CONST_INT}}, \ - {"cint8_operand", {CONST_INT}}, \ - {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \ - {"add_operand", {SUBREG, REG, CONST_INT}}, \ - {"sext_add_operand", {SUBREG, REG, CONST_INT}}, \ - {"const48_operand", {CONST_INT}}, \ - {"and_operand", {SUBREG, REG, CONST_INT}}, \ - {"or_operand", {SUBREG, REG, CONST_INT}}, \ - {"mode_mask_operand", {CONST_INT}}, \ - {"mul8_operand", {CONST_INT}}, \ - {"mode_width_operand", {CONST_INT}}, \ - {"reg_or_fp0_operand", {SUBREG, REG, CONST_DOUBLE}}, \ - {"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}}, \ - {"alpha_swapped_comparison_operator", {EQ, GE, GT, GEU, GTU}}, \ - {"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}}, \ - {"divmod_operator", {DIV, MOD, UDIV, UMOD}}, \ - {"fp0_operand", {CONST_DOUBLE}}, \ - {"current_file_function_operand", {SYMBOL_REF}}, \ - {"call_operand", {REG, SYMBOL_REF}}, \ - {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ - SYMBOL_REF, CONST, LABEL_REF}}, \ - {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ - SYMBOL_REF, CONST, LABEL_REF}}, \ - {"aligned_memory_operand", {MEM}}, \ - {"unaligned_memory_operand", {MEM}}, \ - {"reg_or_unaligned_mem_operand", {SUBREG, REG, MEM}}, \ - {"any_memory_operand", {MEM}}, \ - {"hard_fp_register_operand", {SUBREG, REG}}, \ - {"reg_not_elim_operand", {SUBREG, REG}}, - -/* Tell collect that the object format is ECOFF. */ -#define OBJECT_FORMAT_COFF -#define EXTENDED_COFF - -/* If we use NM, pass -g to it so it only lists globals. */ -#define NM_FLAGS "-pg" - -/* Definitions for debugging. */ - -#define SDB_DEBUGGING_INFO /* generate info for mips-tfile */ -#define DBX_DEBUGGING_INFO /* generate embedded stabs */ -#define MIPS_DEBUGGING_INFO /* MIPS specific debugging info */ - -#ifndef PREFERRED_DEBUGGING_TYPE /* assume SDB_DEBUGGING_INFO */ -#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG -#endif - - -/* Correct the offset of automatic variables and arguments. Note that - the Alpha debug format wants all automatic variables and arguments - to be in terms of two different offsets from the virtual frame pointer, - which is the stack pointer before any adjustment in the function. - The offset for the argument pointer is fixed for the native compiler, - it is either zero (for the no arguments case) or large enough to hold - all argument registers. - The offset for the auto pointer is the fourth argument to the .frame - directive (local_offset). - To stay compatible with the native tools we use the same offsets - from the virtual frame pointer and adjust the debugger arg/auto offsets - accordingly. These debugger offsets are set up in output_prolog. */ - -extern long alpha_arg_offset; -extern long alpha_auto_offset; -#define DEBUGGER_AUTO_OFFSET(X) \ - ((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) + alpha_auto_offset) -#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET + alpha_arg_offset) - - -#define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) \ - alpha_output_lineno (STREAM, LINE) -extern void alpha_output_lineno (); - -#define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) \ - alpha_output_filename (STREAM, NAME) -extern void alpha_output_filename (); - -/* mips-tfile.c limits us to strings of one page. We must underestimate this - number, because the real length runs past this up to the next - continuation point. This is really a dbxout.c bug. */ -#define DBX_CONTIN_LENGTH 3000 - -/* By default, turn on GDB extensions. */ -#define DEFAULT_GDB_EXTENSIONS 1 - -/* Stabs-in-ECOFF can't handle dbxout_function_end(). */ -#define NO_DBX_FUNCTION_END 1 - -/* If we are smuggling stabs through the ALPHA ECOFF object - format, put a comment in front of the .stab operation so - that the ALPHA assembler does not choke. The mips-tfile program - will correctly put the stab into the object file. */ - -#define ASM_STABS_OP ((TARGET_GAS) ? ".stabs" : " #.stabs") -#define ASM_STABN_OP ((TARGET_GAS) ? ".stabn" : " #.stabn") -#define ASM_STABD_OP ((TARGET_GAS) ? ".stabd" : " #.stabd") - -/* Forward references to tags are allowed. */ -#define SDB_ALLOW_FORWARD_REFERENCES - -/* Unknown tags are also allowed. */ -#define SDB_ALLOW_UNKNOWN_REFERENCES - -#define PUT_SDB_DEF(a) \ -do { \ - fprintf (asm_out_file, "\t%s.def\t", \ - (TARGET_GAS) ? "" : "#"); \ - ASM_OUTPUT_LABELREF (asm_out_file, a); \ - fputc (';', asm_out_file); \ -} while (0) - -#define PUT_SDB_PLAIN_DEF(a) \ -do { \ - fprintf (asm_out_file, "\t%s.def\t.%s;", \ - (TARGET_GAS) ? "" : "#", (a)); \ -} while (0) - -#define PUT_SDB_TYPE(a) \ -do { \ - fprintf (asm_out_file, "\t.type\t0x%x;", (a)); \ -} while (0) - -/* 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. */ - -extern int sdb_label_count; /* block start/end next label # */ - -#define PUT_SDB_BLOCK_START(LINE) \ -do { \ - fprintf (asm_out_file, \ - "$Lb%d:\n\t%s.begin\t$Lb%d\t%d\n", \ - sdb_label_count, \ - (TARGET_GAS) ? "" : "#", \ - sdb_label_count, \ - (LINE)); \ - sdb_label_count++; \ -} while (0) - -#define PUT_SDB_BLOCK_END(LINE) \ -do { \ - fprintf (asm_out_file, \ - "$Le%d:\n\t%s.bend\t$Le%d\t%d\n", \ - sdb_label_count, \ - (TARGET_GAS) ? "" : "#", \ - sdb_label_count, \ - (LINE)); \ - sdb_label_count++; \ -} while (0) - -#define PUT_SDB_FUNCTION_START(LINE) - -#define PUT_SDB_FUNCTION_END(LINE) - -#define PUT_SDB_EPILOGUE_END(NAME) ((void)(NAME)) - -/* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for - mips-tdump.c to print them out. - - These must match the corresponding definitions in gdb/mipsread.c. - Unfortunately, gcc and gdb do not currently share any directories. */ - -#define CODE_MASK 0x8F300 -#define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK) -#define MIPS_MARK_STAB(code) ((code)+CODE_MASK) -#define MIPS_UNMARK_STAB(code) ((code)-CODE_MASK) - -/* Override some mips-tfile definitions. */ - -#define SHASH_SIZE 511 -#define THASH_SIZE 55 - -/* Align ecoff symbol tables to avoid OSF1/1.3 nm complaints. */ - -#define ALIGN_SYMTABLE_OFFSET(OFFSET) (((OFFSET) + 7) & ~7) - -/* The linker will stick __main into the .init section. */ -#define HAS_INIT_SECTION -#define LD_INIT_SWITCH "-init" -#define LD_FINI_SWITCH "-fini" - -/* The system headers under Alpha systems are generally C++-aware. */ -#define NO_IMPLICIT_EXTERN_C - -/* Prototypes for alpha.c functions used in the md file & elsewhere. */ -extern struct rtx_def *get_unaligned_address (); -extern void alpha_write_verstamp (); -extern void alpha_reorg (); -extern int check_float_value (); -extern int direct_return (); -extern int const48_operand (); -extern int add_operand (); -extern int and_operand (); -extern int unaligned_memory_operand (); -extern int zap_mask (); -extern int current_file_function_operand (); -extern int alpha_sa_size (); -extern int alpha_adjust_cost (); -extern void print_operand (); -extern int reg_or_0_operand (); -extern int reg_or_8bit_operand (); -extern int mul8_operand (); -extern int reg_or_6bit_operand (); -extern int alpha_comparison_operator (); -extern int alpha_swapped_comparison_operator (); -extern int sext_add_operand (); -extern int cint8_operand (); -extern int mode_mask_operand (); -extern int or_operand (); -extern int mode_width_operand (); -extern int reg_or_fp0_operand (); -extern int signed_comparison_operator (); -extern int fp0_operand (); -extern int some_operand (); -extern int input_operand (); -extern int divmod_operator (); -extern int call_operand (); -extern int reg_or_cint_operand (); -extern int hard_fp_register_operand (); -extern int reg_not_elim_operand (); -extern void alpha_set_memflags (); -extern int aligned_memory_operand (); -extern void get_aligned_mem (); -extern void alpha_expand_unaligned_load (); -extern void alpha_expand_unaligned_store (); -extern int alpha_expand_block_move (); -extern int alpha_expand_block_clear (); -extern void alpha_expand_prologue (); -extern void alpha_expand_epilogue (); diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md deleted file mode 100755 index e0ff2c5..0000000 --- a/gcc/config/alpha/alpha.md +++ /dev/null @@ -1,5313 +0,0 @@ -;; Machine description for DEC Alpha for GNU C compiler -;; Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc. -;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; Uses of UNSPEC in this file: -;; -;; 0 arg_home -;; 1 cttz -;; 2 insxh -;; 3 mskxh -;; 4 cvtlq -;; 5 cvtql -;; -;; UNSPEC_VOLATILE: -;; -;; 0 imb -;; 1 blockage -;; 2 builtin_setjmp_receiver -;; 3 builtin_longjmp -;; 4 trapb -;; 5 prologue_stack_probe_loop -;; 6 realign -;; 7 exception_receiver - -;; Processor type -- this attribute must exactly match the processor_type -;; enumeration in alpha.h. - -(define_attr "cpu" "ev4,ev5,ev6" - (const (symbol_ref "alpha_cpu"))) - -;; Define an insn type attribute. This is used in function unit delay -;; computations, among other purposes. For the most part, we use the names -;; defined in the EV4 documentation, but add a few that we have to know about -;; separately. - -(define_attr "type" - "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" - (const_string "iadd")) - -;; Describe a user's asm statement. -(define_asm_attributes - [(set_attr "type" "multi")]) - -;; Define the operand size an insn operates on. Used primarily by mul -;; and div operations that have size dependant timings. - -(define_attr "opsize" "si,di,udi" (const_string "di")) - -;; The TRAP_TYPE attribute marks instructions that may generate traps -;; (which are imprecise and may need a trapb if software completion -;; is desired). - -(define_attr "trap" "no,yes" (const_string "no")) - -;; The length of an instruction sequence in bytes. - -(define_attr "length" "" (const_int 4)) - -;; On EV4 there are two classes of resources to consider: resources needed -;; to issue, and resources needed to execute. IBUS[01] are in the first -;; category. ABOX, BBOX, EBOX, FBOX, IMUL & FDIV make up the second. -;; (There are a few other register-like resources, but ...) - -; First, describe all of the issue constraints with single cycle delays. -; All insns need a bus, but all except loads require one or the other. -(define_function_unit "ev4_ibus0" 1 0 - (and (eq_attr "cpu" "ev4") - (eq_attr "type" "fst,fbr,iadd,imul,ilog,shift,icmov,icmp")) - 1 1) - -(define_function_unit "ev4_ibus1" 1 0 - (and (eq_attr "cpu" "ev4") - (eq_attr "type" "ist,ibr,jsr,fadd,fcmov,fcpys,fmul,fdiv,misc")) - 1 1) - -; Memory delivers its result in three cycles. Actually return one and -; take care of this in adjust_cost, since we want to handle user-defined -; memory latencies. -(define_function_unit "ev4_abox" 1 0 - (and (eq_attr "cpu" "ev4") - (eq_attr "type" "ild,fld,ldsym,ist,fst")) - 1 1) - -; Branches have no delay cost, but do tie up the unit for two cycles. -(define_function_unit "ev4_bbox" 1 1 - (and (eq_attr "cpu" "ev4") - (eq_attr "type" "ibr,fbr,jsr")) - 2 2) - -; Arithmetic insns are normally have their results available after -; two cycles. There are a number of exceptions. They are encoded in -; ADJUST_COST. Some of the other insns have similar exceptions. -(define_function_unit "ev4_ebox" 1 0 - (and (eq_attr "cpu" "ev4") - (eq_attr "type" "iadd,ilog,shift,icmov,icmp,misc")) - 2 1) - -(define_function_unit "imul" 1 0 - (and (eq_attr "cpu" "ev4") - (and (eq_attr "type" "imul") - (eq_attr "opsize" "si"))) - 21 19) - -(define_function_unit "imul" 1 0 - (and (eq_attr "cpu" "ev4") - (and (eq_attr "type" "imul") - (eq_attr "opsize" "!si"))) - 23 21) - -(define_function_unit "ev4_fbox" 1 0 - (and (eq_attr "cpu" "ev4") - (eq_attr "type" "fadd,fmul,fcpys,fcmov")) - 6 1) - -(define_function_unit "fdiv" 1 0 - (and (eq_attr "cpu" "ev4") - (and (eq_attr "type" "fdiv") - (eq_attr "opsize" "si"))) - 34 30) - -(define_function_unit "fdiv" 1 0 - (and (eq_attr "cpu" "ev4") - (and (eq_attr "type" "fdiv") - (eq_attr "opsize" "di"))) - 63 59) - -;; EV5 scheduling. EV5 can issue 4 insns per clock. -;; -;; EV5 has two asymetric integer units. Model this with E0 & E1 along -;; with the combined resource EBOX. - -(define_function_unit "ev5_ebox" 2 0 - (and (eq_attr "cpu" "ev5") - (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv")) - 1 1) - -; Memory takes at least 2 clocks. Return one from here and fix up with -; user-defined latencies in adjust_cost. -; ??? How to: "An instruction of class LD cannot be issued in the _second_ -; cycle after an instruction of class ST is issued." -(define_function_unit "ev5_ebox" 2 0 - (and (eq_attr "cpu" "ev5") - (eq_attr "type" "ild,fld,ldsym")) - 1 1) - -; Stores, shifts, multiplies can only issue to E0 -(define_function_unit "ev5_e0" 1 0 - (and (eq_attr "cpu" "ev5") - (eq_attr "type" "ist,fst,shift,imul")) - 1 1) - -; Motion video insns also issue only to E0, and take two ticks. -(define_function_unit "ev5_e0" 1 0 - (and (eq_attr "cpu" "ev5") - (eq_attr "type" "mvi")) - 2 1) - -; Conditional moves always take 2 ticks. -(define_function_unit "ev5_ebox" 2 0 - (and (eq_attr "cpu" "ev5") - (eq_attr "type" "icmov")) - 2 1) - -; Branches can only issue to E1 -(define_function_unit "ev5_e1" 1 0 - (and (eq_attr "cpu" "ev5") - (eq_attr "type" "ibr,jsr")) - 1 1) - -; Multiplies also use the integer multiplier. -; ??? How to: "No instruction can be issued to pipe E0 exactly two -; cycles before an integer multiplication completes." -(define_function_unit "imul" 1 0 - (and (eq_attr "cpu" "ev5") - (and (eq_attr "type" "imul") - (eq_attr "opsize" "si"))) - 8 4) - -(define_function_unit "imul" 1 0 - (and (eq_attr "cpu" "ev5") - (and (eq_attr "type" "imul") - (eq_attr "opsize" "di"))) - 12 8) - -(define_function_unit "imul" 1 0 - (and (eq_attr "cpu" "ev5") - (and (eq_attr "type" "imul") - (eq_attr "opsize" "udi"))) - 14 8) - -;; Similarly for the FPU we have two asymetric units. But fcpys can issue -;; on either so we have to play the game again. - -(define_function_unit "ev5_fbox" 2 0 - (and (eq_attr "cpu" "ev5") - (eq_attr "type" "fadd,fcmov,fmul,fcpys,fbr,fdiv")) - 4 1) - -(define_function_unit "ev5_fm" 1 0 - (and (eq_attr "cpu" "ev5") - (eq_attr "type" "fmul")) - 4 1) - -; Add and cmov as you would expect; fbr never produces a result; -; fdiv issues through fa to the divider, -(define_function_unit "ev5_fa" 1 0 - (and (eq_attr "cpu" "ev5") - (eq_attr "type" "fadd,fcmov,fbr,fdiv")) - 4 1) - -; ??? How to: "No instruction can be issued to pipe FA exactly five -; cycles before a floating point divide completes." -(define_function_unit "fdiv" 1 0 - (and (eq_attr "cpu" "ev5") - (and (eq_attr "type" "fdiv") - (eq_attr "opsize" "si"))) - 15 15) ; 15 to 31 data dependant - -(define_function_unit "fdiv" 1 0 - (and (eq_attr "cpu" "ev5") - (and (eq_attr "type" "fdiv") - (eq_attr "opsize" "di"))) - 22 22) ; 22 to 60 data dependant - -;; EV6 scheduling. EV6 can issue 4 insns per clock. -;; -;; EV6 has two symmetric pairs ("clusters") of two asymetric integer units -;; ("upper" and "lower"), yielding pipe names U0, U1, L0, L1. - -;; Conditional moves decompose into two independant primitives, each -;; taking one cycle. Since ev6 is out-of-order, we can't see anything -;; but two cycles. -(define_function_unit "ev6_ebox" 4 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "icmov")) - 2 1) - -(define_function_unit "ev6_ebox" 4 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv,fsqrt")) - 1 1) - -;; Integer loads take at least 3 clocks, and only issue to lower units. -;; Return one from here and fix up with user-defined latencies in adjust_cost. -(define_function_unit "ev6_l" 2 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "ild,ldsym,ist,fst")) - 1 1) - -;; FP loads take at least 4 clocks. Return two from here... -(define_function_unit "ev6_l" 2 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "fld")) - 2 1) - -;; Motion video insns also issue only to U0, and take three ticks. -(define_function_unit "ev6_u0" 1 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "mvi")) - 3 1) - -(define_function_unit "ev6_u" 2 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "mvi")) - 3 1) - -;; Shifts issue to either upper pipe. -(define_function_unit "ev6_u" 2 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "shift")) - 1 1) - -;; Multiplies issue only to U1, and all take 7 ticks. -;; Rather than create a new function unit just for U1, reuse IMUL -(define_function_unit "imul" 1 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "imul")) - 7 1) - -(define_function_unit "ev6_u" 2 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "imul")) - 7 1) - -;; Branches issue to either upper pipe -(define_function_unit "ev6_u" 2 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "ibr")) - 3 1) - -;; Calls only issue to L0. -(define_function_unit "ev6_l0" 1 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "jsr")) - 1 1) - -(define_function_unit "ev6_l" 2 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "jsr")) - 1 1) - -;; Ftoi/itof only issue to lower pipes -(define_function_unit "ev6_l" 2 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "ftoi")) - 3 1) - -(define_function_unit "ev6_l" 2 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "itof")) - 4 1) - -;; For the FPU we are very similar to EV5, except there's no insn that -;; can issue to fm & fa, so we get to leave that out. - -(define_function_unit "ev6_fm" 1 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "fmul")) - 4 1) - -(define_function_unit "ev6_fa" 1 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "fadd,fcpys,fbr,fdiv,fsqrt")) - 4 1) - -(define_function_unit "ev6_fa" 1 0 - (and (eq_attr "cpu" "ev6") - (eq_attr "type" "fcmov")) - 8 1) - -(define_function_unit "fdiv" 1 0 - (and (eq_attr "cpu" "ev6") - (and (eq_attr "type" "fdiv") - (eq_attr "opsize" "si"))) - 12 10) - -(define_function_unit "fdiv" 1 0 - (and (eq_attr "cpu" "ev6") - (and (eq_attr "type" "fdiv") - (eq_attr "opsize" "di"))) - 15 13) - -(define_function_unit "fsqrt" 1 0 - (and (eq_attr "cpu" "ev6") - (and (eq_attr "type" "fsqrt") - (eq_attr "opsize" "si"))) - 16 14) - -(define_function_unit "fsqrt" 1 0 - (and (eq_attr "cpu" "ev6") - (and (eq_attr "type" "fsqrt") - (eq_attr "opsize" "di"))) - 32 30) - -; ??? The FPU communicates with memory and the integer register file -; via two fp store units. We need a slot in the fst immediately, and -; a slot in LOW after the operand data is ready. At which point the -; data may be moved either to the store queue or the integer register -; file and the insn retired. - - -;; First define the arithmetic insns. Note that the 32-bit forms also -;; sign-extend. - -;; Handle 32-64 bit extension from memory to a floating point register -;; specially, since this ocurrs frequently in int->double conversions. -;; This is done with a define_split after reload converting the plain -;; sign-extension into a load+unspec, which of course results in lds+cvtlq. -;; -;; Note that while we must retain the =f case in the insn for reload's -;; benefit, it should be eliminated after reload, so we should never emit -;; code for that case. But we don't reject the possibility. - -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=r,r,?f") - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,m")))] - "" - "@ - addl %1,$31,%0 - ldl %0,%1 - lds %0,%1\;cvtlq %0,%0" - [(set_attr "type" "iadd,ild,fld") - (set_attr "length" "*,*,8")]) - -;; Due to issues with CLASS_CANNOT_CHANGE_SIZE, we cannot use a subreg here. -(define_split - [(set (match_operand:DI 0 "hard_fp_register_operand" "") - (sign_extend:DI (match_operand:SI 1 "memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) (unspec:DI [(match_dup 2)] 4))] - "operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=f") - (unspec:DI [(match_operand:SI 1 "register_operand" "f")] 4))] - "" - "cvtlq %1,%0" - [(set_attr "type" "fadd")]) - -;; Do addsi3 the way expand_binop would do if we didn't have one. This -;; generates better code. We have the anonymous addsi3 pattern below in -;; case combine wants to make it. -(define_expand "addsi3" - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "") - (match_operand:SI 2 "add_operand" "")))] - "" - " -{ - if (optimize) - { - rtx op1 = gen_lowpart (DImode, operands[1]); - rtx op2 = gen_lowpart (DImode, operands[2]); - - if (! cse_not_expected) - { - rtx tmp = gen_reg_rtx (DImode); - emit_insn (gen_adddi3 (tmp, op1, op2)); - emit_move_insn (gen_lowpart (DImode, operands[0]), tmp); - } - else - emit_insn (gen_adddi3 (gen_lowpart (DImode, operands[0]), op1, op2)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ") - (match_operand:SI 2 "add_operand" "rI,O,K,L")))] - "" - "@ - addl %r1,%2,%0 - subl %r1,%n2,%0 - lda %0,%2(%r1) - ldah %0,%h2(%r1)") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] - "! add_operand (operands[2], SImode)" - [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3))) - (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))] - " -{ - HOST_WIDE_INT val = INTVAL (operands[2]); - HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); - HOST_WIDE_INT rest = val - low; - - operands[3] = GEN_INT (rest); - operands[4] = GEN_INT (low); -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (sign_extend:DI - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ") - (match_operand:SI 2 "sext_add_operand" "rI,O"))))] - "" - "@ - addl %r1,%2,%0 - subl %r1,%n2,%0") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))) - (clobber (match_operand:SI 3 "reg_not_elim_operand" ""))] - "! sext_add_operand (operands[2], SImode) && INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) % 4 == 0" - [(set (match_dup 3) (match_dup 4)) - (set (match_dup 0) (sign_extend:DI (plus:SI (mult:SI (match_dup 3) - (match_dup 5)) - (match_dup 1))))] - " -{ - HOST_WIDE_INT val = INTVAL (operands[2]) / 4; - int mult = 4; - - if (val % 2 == 0) - val /= 2, mult = 8; - - operands[4] = GEN_INT (val); - operands[5] = GEN_INT (mult); -}") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI - (plus:SI (match_operator:SI 1 "comparison_operator" - [(match_operand 2 "" "") - (match_operand 3 "" "")]) - (match_operand:SI 4 "add_operand" "")))) - (clobber (match_operand:DI 5 "register_operand" ""))] - "" - [(set (match_dup 5) (match_dup 6)) - (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 7) (match_dup 4))))] - " -{ - operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), DImode, - operands[2], operands[3]); - operands[7] = gen_lowpart (SImode, operands[5]); -}") - -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") - (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ") - (match_operand:DI 2 "add_operand" "rI,O,K,L")))] - "" - "@ - addq %r1,%2,%0 - subq %r1,%n2,%0 - lda %0,%2(%r1) - ldah %0,%h2(%r1)") - -;; Don't do this if we are adjusting SP since we don't want to do -;; it in two steps. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "const_int_operand" "")))] - "! add_operand (operands[2], DImode) - && REGNO (operands[0]) != STACK_POINTER_REGNUM" - [(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) - 2 * (val & 0x8000); - HOST_WIDE_INT rest = val - low; - - operands[3] = GEN_INT (rest); - operands[4] = GEN_INT (low); -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r,r") - (match_operand:SI 2 "const48_operand" "I,I")) - (match_operand:SI 3 "sext_add_operand" "rI,O")))] - "" - "@ - s%2addl %1,%3,%0 - s%2subl %1,%n3,%0") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (sign_extend:DI - (plus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r,r") - (match_operand:SI 2 "const48_operand" "I,I")) - (match_operand:SI 3 "sext_add_operand" "rI,O"))))] - "" - "@ - s%2addl %1,%3,%0 - s%2subl %1,%n3,%0") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI - (plus:SI (mult:SI (match_operator:SI 1 "comparison_operator" - [(match_operand 2 "" "") - (match_operand 3 "" "")]) - (match_operand:SI 4 "const48_operand" "")) - (match_operand:SI 5 "add_operand" "")))) - (clobber (match_operand:DI 6 "reg_not_elim_operand" ""))] - "" - [(set (match_dup 6) (match_dup 7)) - (set (match_dup 0) - (sign_extend:DI (plus:SI (mult:SI (match_dup 8) (match_dup 4)) - (match_dup 5))))] - " -{ - operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[1]), DImode, - operands[2], operands[3]); - operands[8] = gen_lowpart (SImode, operands[6]); -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (plus:DI (mult:DI (match_operand:DI 1 "reg_not_elim_operand" "r,r") - (match_operand:DI 2 "const48_operand" "I,I")) - (match_operand:DI 3 "sext_add_operand" "rI,O")))] - "" - "@ - s%2addq %1,%3,%0 - s%2subq %1,%n3,%0") - -;; These variants of the above insns can occur if the third operand -;; is the frame pointer. This is a kludge, but there doesn't -;; seem to be a way around it. Only recognize them while reloading. - -(define_insn "" - [(set (match_operand:DI 0 "some_operand" "=&r") - (plus:DI (plus:DI (match_operand:DI 1 "some_operand" "r") - (match_operand:DI 2 "some_operand" "r")) - (match_operand:DI 3 "some_operand" "rIOKL")))] - "reload_in_progress" - "#") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" "")) - (match_operand:DI 3 "add_operand" "")))] - "reload_completed" - [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] - "") - -(define_insn "" - [(set (match_operand:SI 0 "some_operand" "=&r") - (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "some_operand" "rJ") - (match_operand:SI 2 "const48_operand" "I")) - (match_operand:SI 3 "some_operand" "r")) - (match_operand:SI 4 "some_operand" "rIOKL")))] - "reload_in_progress" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "r") - (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "") - (match_operand:SI 2 "const48_operand" "")) - (match_operand:SI 3 "register_operand" "")) - (match_operand:SI 4 "add_operand" "rIOKL")))] - "reload_completed" - [(set (match_dup 0) - (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3))) - (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))] - "") - -(define_insn "" - [(set (match_operand:DI 0 "some_operand" "=&r") - (sign_extend:DI - (plus:SI (plus:SI - (mult:SI (match_operand:SI 1 "some_operand" "rJ") - (match_operand:SI 2 "const48_operand" "I")) - (match_operand:SI 3 "some_operand" "r")) - (match_operand:SI 4 "some_operand" "rIOKL"))))] - "reload_in_progress" - "#") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI - (plus:SI (plus:SI - (mult:SI (match_operand:SI 1 "reg_or_0_operand" "") - (match_operand:SI 2 "const48_operand" "")) - (match_operand:SI 3 "register_operand" "")) - (match_operand:SI 4 "add_operand" ""))))] - "reload_completed" - [(set (match_dup 5) - (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3))) - (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 5) (match_dup 4))))] - "operands[5] = gen_lowpart (SImode, operands[0]);") - -(define_insn "" - [(set (match_operand:DI 0 "some_operand" "=&r") - (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "some_operand" "rJ") - (match_operand:DI 2 "const48_operand" "I")) - (match_operand:DI 3 "some_operand" "r")) - (match_operand:DI 4 "some_operand" "rIOKL")))] - "reload_in_progress" - "#") - -(define_split - [(set (match_operand:DI 0 "register_operand" "=") - (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "") - (match_operand:DI 2 "const48_operand" "")) - (match_operand:DI 3 "register_operand" "")) - (match_operand:DI 4 "add_operand" "")))] - "reload_completed" - [(set (match_dup 0) - (plus:DI (mult:DI (match_dup 1) (match_dup 2)) (match_dup 3))) - (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))] - "") - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI")))] - "" - "subl $31,%1,%0") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI (neg:SI - (match_operand:SI 1 "reg_or_8bit_operand" "rI"))))] - "" - "subl $31,%1,%0") - -(define_insn "negdi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (neg:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))] - "" - "subq $31,%1,%0") - -(define_expand "subsi3" - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "") - (match_operand:SI 2 "reg_or_8bit_operand" "")))] - "" - " -{ - if (optimize) - { - rtx op1 = gen_lowpart (DImode, operands[1]); - rtx op2 = gen_lowpart (DImode, operands[2]); - - if (! cse_not_expected) - { - rtx tmp = gen_reg_rtx (DImode); - emit_insn (gen_subdi3 (tmp, op1, op2)); - emit_move_insn (gen_lowpart (DImode, operands[0]), tmp); - } - else - emit_insn (gen_subdi3 (gen_lowpart (DImode, operands[0]), op1, op2)); - DONE; - } -} ") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") - (match_operand:SI 2 "reg_or_8bit_operand" "rI")))] - "" - "subl %r1,%2,%0") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") - (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))] - "" - "subl %r1,%2,%0") - -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] - "" - "subq %r1,%2,%0") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r") - (match_operand:SI 2 "const48_operand" "I")) - (match_operand:SI 3 "reg_or_8bit_operand" "rI")))] - "" - "s%2subl %1,%3,%0") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI - (minus:SI (mult:SI (match_operand:SI 1 "reg_not_elim_operand" "r") - (match_operand:SI 2 "const48_operand" "I")) - (match_operand:SI 3 "reg_or_8bit_operand" "rI"))))] - "" - "s%2subl %1,%3,%0") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (minus:DI (mult:DI (match_operand:DI 1 "reg_not_elim_operand" "r") - (match_operand:DI 2 "const48_operand" "I")) - (match_operand:DI 3 "reg_or_8bit_operand" "rI")))] - "" - "s%2subq %1,%3,%0") - -(define_insn "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") - (match_operand:SI 2 "reg_or_8bit_operand" "rI")))] - "" - "mull %r1,%2,%0" - [(set_attr "type" "imul") - (set_attr "opsize" "si")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI - (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") - (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))] - "" - "mull %r1,%2,%0" - [(set_attr "type" "imul") - (set_attr "opsize" "si")]) - -(define_insn "muldi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (mult:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ") - (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] - "" - "mulq %r1,%2,%0" - [(set_attr "type" "imul")]) - -(define_insn "umuldi3_highpart" - [(set (match_operand:DI 0 "register_operand" "=r") - (truncate:DI - (lshiftrt:TI - (mult:TI (zero_extend:TI - (match_operand:DI 1 "reg_or_0_operand" "%rJ")) - (zero_extend:TI - (match_operand:DI 2 "reg_or_8bit_operand" "rI"))) - (const_int 64))))] - "" - "umulh %r1,%2,%0" - [(set_attr "type" "imul") - (set_attr "opsize" "udi")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (truncate:DI - (lshiftrt:TI - (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) - (match_operand:TI 2 "cint8_operand" "I")) - (const_int 64))))] - "" - "umulh %1,%2,%0" - [(set_attr "type" "imul") - (set_attr "opsize" "udi")]) - -;; The divide and remainder operations always take their inputs from -;; r24 and r25, put their output in r27, and clobber r23 and r28. - -;; ??? Force sign-extension here because some versions of OSF/1 don't -;; do the right thing if the inputs are not properly sign-extended. -;; But Linux, for instance, does not have this problem. Is it worth -;; the complication here to eliminate the sign extension? - -(define_expand "divsi3" - [(set (reg:DI 24) - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) - (set (reg:DI 25) - (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) - (parallel [(set (reg:DI 27) - (sign_extend:DI (div:SI (reg:DI 24) (reg:DI 25)))) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))]) - (set (match_operand:SI 0 "general_operand" "") - (subreg:SI (reg:DI 27) 0))] - "!TARGET_OPEN_VMS" - "") - -(define_expand "udivsi3" - [(set (reg:DI 24) - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) - (set (reg:DI 25) - (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) - (parallel [(set (reg:DI 27) - (sign_extend:DI (udiv:SI (reg:DI 24) (reg:DI 25)))) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))]) - (set (match_operand:SI 0 "general_operand" "") - (subreg:SI (reg:DI 27) 0))] - "!TARGET_OPEN_VMS" - "") - -(define_expand "modsi3" - [(set (reg:DI 24) - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) - (set (reg:DI 25) - (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) - (parallel [(set (reg:DI 27) - (sign_extend:DI (mod:SI (reg:DI 24) (reg:DI 25)))) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))]) - (set (match_operand:SI 0 "general_operand" "") - (subreg:SI (reg:DI 27) 0))] - "!TARGET_OPEN_VMS" - "") - -(define_expand "umodsi3" - [(set (reg:DI 24) - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))) - (set (reg:DI 25) - (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))) - (parallel [(set (reg:DI 27) - (sign_extend:DI (umod:SI (reg:DI 24) (reg:DI 25)))) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))]) - (set (match_operand:SI 0 "general_operand" "") - (subreg:SI (reg:DI 27) 0))] - "!TARGET_OPEN_VMS" - "") - -(define_expand "divdi3" - [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) - (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) - (parallel [(set (reg:DI 27) - (div:DI (reg:DI 24) - (reg:DI 25))) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))]) - (set (match_operand:DI 0 "general_operand" "") - (reg:DI 27))] - "!TARGET_OPEN_VMS" - "") - -(define_expand "udivdi3" - [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) - (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) - (parallel [(set (reg:DI 27) - (udiv:DI (reg:DI 24) - (reg:DI 25))) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))]) - (set (match_operand:DI 0 "general_operand" "") - (reg:DI 27))] - "!TARGET_OPEN_VMS" - "") - -(define_expand "moddi3" - [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) - (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) - (parallel [(set (reg:DI 27) - (mod:DI (reg:DI 24) - (reg:DI 25))) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))]) - (set (match_operand:DI 0 "general_operand" "") - (reg:DI 27))] - "!TARGET_OPEN_VMS" - "") - -(define_expand "umoddi3" - [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) - (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) - (parallel [(set (reg:DI 27) - (umod:DI (reg:DI 24) - (reg:DI 25))) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))]) - (set (match_operand:DI 0 "general_operand" "") - (reg:DI 27))] - "!TARGET_OPEN_VMS" - "") - -;; Lengths of 8 for ldq $t12,__divq($gp); jsr $t9,($t12),__divq as -;; expanded by the assembler. -(define_insn "" - [(set (reg:DI 27) - (sign_extend:DI (match_operator:SI 1 "divmod_operator" - [(reg:DI 24) (reg:DI 25)]))) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))] - "!TARGET_OPEN_VMS" - "%E1 $24,$25,$27" - [(set_attr "type" "jsr") - (set_attr "length" "8")]) - -(define_insn "" - [(set (reg:DI 27) - (match_operator:DI 1 "divmod_operator" - [(reg:DI 24) (reg:DI 25)])) - (clobber (reg:DI 23)) - (clobber (reg:DI 28))] - "!TARGET_OPEN_VMS" - "%E1 $24,$25,$27" - [(set_attr "type" "jsr") - (set_attr "length" "8")]) - -;; Next are the basic logical operations. These only exist in DImode. - -(define_insn "anddi3" - [(set (match_operand:DI 0 "register_operand" "=r,r,r") - (and:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ,rJ") - (match_operand:DI 2 "and_operand" "rI,N,MH")))] - "" - "@ - and %r1,%2,%0 - bic %r1,%N2,%0 - zapnot %r1,%m2,%0" - [(set_attr "type" "ilog,ilog,shift")]) - -;; There are times when we can split an AND into two AND insns. This occurs -;; when we can first clear any bytes and then clear anything else. For -;; example "I & 0xffff07" is "(I & 0xffffff) & 0xffffffffffffff07". -;; Only do this when running on 64-bit host since the computations are -;; too messy otherwise. - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (and:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "const_int_operand" "")))] - "HOST_BITS_PER_WIDE_INT == 64 && ! and_operand (operands[2], DImode)" - [(set (match_dup 0) (and:DI (match_dup 1) (match_dup 3))) - (set (match_dup 0) (and:DI (match_dup 0) (match_dup 4)))] - " -{ - unsigned HOST_WIDE_INT mask1 = INTVAL (operands[2]); - unsigned HOST_WIDE_INT mask2 = mask1; - int i; - - /* For each byte that isn't all zeros, make it all ones. */ - for (i = 0; i < 64; i += 8) - if ((mask1 & ((HOST_WIDE_INT) 0xff << i)) != 0) - mask1 |= (HOST_WIDE_INT) 0xff << i; - - /* Now turn on any bits we've just turned off. */ - mask2 |= ~ mask1; - - operands[3] = GEN_INT (mask1); - operands[4] = GEN_INT (mask2); -}") - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] - "" - "and %1,0xff,%0" - [(set_attr "type" "ilog")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] - "TARGET_BWX" - "@ - and %1,0xff,%0 - ldbu %0,%1" - [(set_attr "type" "ilog,ild")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))] - "! TARGET_BWX" - "and %1,0xff,%0" - [(set_attr "type" "ilog")]) - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] - "TARGET_BWX" - "@ - and %1,0xff,%0 - ldbu %0,%1" - [(set_attr "type" "ilog,ild")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (match_operand:QI 1 "register_operand" "r")))] - "! TARGET_BWX" - "and %1,0xff,%0" - [(set_attr "type" "ilog")]) - -(define_expand "zero_extendqidi2" - [(set (match_operand:DI 0 "register_operand" "") - (zero_extend:DI (match_operand:QI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] - "TARGET_BWX" - "@ - zapnot %1,3,%0 - ldwu %0,%1" - [(set_attr "type" "shift,ild")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))] - "! TARGET_BWX" - "zapnot %1,3,%0" - [(set_attr "type" "shift")]) - -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] - "TARGET_BWX" - "@ - zapnot %1,3,%0 - ldwu %0,%1" - [(set_attr "type" "shift,ild")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))] - "" - "zapnot %1,3,%0" - [(set_attr "type" "shift")]) - -(define_expand "zero_extendhidi2" - [(set (match_operand:DI 0 "register_operand" "") - (zero_extend:DI (match_operand:HI 1 "register_operand" "")))] - "" - "") - -(define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))] - "" - "zapnot %1,15,%0" - [(set_attr "type" "shift")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")) - (match_operand:DI 2 "reg_or_0_operand" "rJ")))] - "" - "bic %r2,%1,%0" - [(set_attr "type" "ilog")]) - -(define_insn "iordi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (ior:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ") - (match_operand:DI 2 "or_operand" "rI,N")))] - "" - "@ - bis %r1,%2,%0 - ornot %r1,%N2,%0" - [(set_attr "type" "ilog")]) - -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")))] - "" - "ornot $31,%1,%0" - [(set_attr "type" "ilog")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ior:DI (not:DI (match_operand:DI 1 "reg_or_8bit_operand" "rI")) - (match_operand:DI 2 "reg_or_0_operand" "rJ")))] - "" - "ornot %r2,%1,%0" - [(set_attr "type" "ilog")]) - -(define_insn "xordi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ") - (match_operand:DI 2 "or_operand" "rI,N")))] - "" - "@ - xor %r1,%2,%0 - eqv %r1,%N2,%0" - [(set_attr "type" "ilog")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (not:DI (xor:DI (match_operand:DI 1 "register_operand" "%rJ") - (match_operand:DI 2 "register_operand" "rI"))))] - "" - "eqv %r1,%2,%0" - [(set_attr "type" "ilog")]) - -;; Handle the FFS insn if we support CIX. - -(define_expand "ffsdi2" - [(set (match_dup 2) - (unspec [(match_operand:DI 1 "register_operand" "")] 1)) - (set (match_dup 3) - (plus:DI (match_dup 2) (const_int 1))) - (set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (eq (match_dup 1) (const_int 0)) - (const_int 0) (match_dup 3)))] - "TARGET_CIX" - " -{ - operands[2] = gen_reg_rtx (DImode); - operands[3] = gen_reg_rtx (DImode); -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (unspec [(match_operand:DI 1 "register_operand" "r")] 1))] - "TARGET_CIX" - "cttz %1,%0" - ; ev6 calls all mvi and cttz/ctlz/popc class imisc, so just - ; reuse the existing type name. - [(set_attr "type" "mvi")]) - -;; Next come the shifts and the various extract and insert operations. - -(define_insn "ashldi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ") - (match_operand:DI 2 "reg_or_6bit_operand" "P,rS")))] - "" - "* -{ - switch (which_alternative) - { - case 0: - if (operands[2] == const1_rtx) - return \"addq %r1,%r1,%0\"; - else - return \"s%P2addq %r1,0,%0\"; - case 1: - return \"sll %r1,%2,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "iadd,shift")]) - -;; ??? The following pattern is made by combine, but earlier phases -;; (specifically flow) can't handle it. This occurs in jump.c. Deal -;; with this in a better way at some point. -;;(define_insn "" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (sign_extend:DI -;; (subreg:SI (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") -;; (match_operand:DI 2 "const_int_operand" "P")) -;; 0)))] -;; "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3" -;; "* -;;{ -;; if (operands[2] == const1_rtx) -;; return \"addl %r1,%r1,%0\"; -;; else -;; return \"s%P2addl %r1,0,%0\"; -;; }" -;; [(set_attr "type" "iadd")]) - -(define_insn "lshrdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "reg_or_6bit_operand" "rS")))] - "" - "srl %r1,%2,%0" - [(set_attr "type" "shift")]) - -(define_insn "ashrdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "reg_or_6bit_operand" "rS")))] - "" - "sra %r1,%2,%0" - [(set_attr "type" "shift")]) - -(define_expand "extendqihi2" - [(set (match_dup 2) - (ashift:DI (match_operand:QI 1 "some_operand" "") - (const_int 56))) - (set (match_operand:HI 0 "register_operand" "") - (ashiftrt:DI (match_dup 2) - (const_int 56)))] - "" - " -{ - if (TARGET_BWX) - { - emit_insn (gen_extendqihi2x (operands[0], - force_reg (QImode, operands[1]))); - DONE; - } - - /* If we have an unaligned MEM, extend to DImode (which we do - specially) and then copy to the result. */ - if (unaligned_memory_operand (operands[1], HImode)) - { - rtx temp = gen_reg_rtx (DImode); - - emit_insn (gen_extendqidi2 (temp, operands[1])); - emit_move_insn (operands[0], gen_lowpart (HImode, temp)); - DONE; - } - - operands[0] = gen_lowpart (DImode, operands[0]); - operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1])); - operands[2] = gen_reg_rtx (DImode); -}") - -(define_insn "extendqidi2x" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI (match_operand:QI 1 "register_operand" "r")))] - "TARGET_BWX" - "sextb %1,%0" - [(set_attr "type" "shift")]) - -(define_insn "extendhidi2x" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI (match_operand:HI 1 "register_operand" "r")))] - "TARGET_BWX" - "sextw %1,%0" - [(set_attr "type" "shift")]) - -(define_insn "extendqisi2x" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))] - "TARGET_BWX" - "sextb %1,%0" - [(set_attr "type" "shift")]) - -(define_insn "extendhisi2x" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))] - "TARGET_BWX" - "sextw %1,%0" - [(set_attr "type" "shift")]) - -(define_insn "extendqihi2x" - [(set (match_operand:HI 0 "register_operand" "=r") - (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))] - "TARGET_BWX" - "sextb %1,%0" - [(set_attr "type" "shift")]) - -(define_expand "extendqisi2" - [(set (match_dup 2) - (ashift:DI (match_operand:QI 1 "some_operand" "") - (const_int 56))) - (set (match_operand:SI 0 "register_operand" "") - (ashiftrt:DI (match_dup 2) - (const_int 56)))] - "" - " -{ - if (TARGET_BWX) - { - emit_insn (gen_extendqisi2x (operands[0], - force_reg (QImode, operands[1]))); - DONE; - } - - /* If we have an unaligned MEM, extend to a DImode form of - the result (which we do specially). */ - if (unaligned_memory_operand (operands[1], QImode)) - { - rtx temp = gen_reg_rtx (DImode); - - emit_insn (gen_extendqidi2 (temp, operands[1])); - emit_move_insn (operands[0], gen_lowpart (SImode, temp)); - DONE; - } - - operands[0] = gen_lowpart (DImode, operands[0]); - operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1])); - operands[2] = gen_reg_rtx (DImode); -}") - -(define_expand "extendqidi2" - [(set (match_dup 2) - (ashift:DI (match_operand:QI 1 "some_operand" "") - (const_int 56))) - (set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_dup 2) - (const_int 56)))] - "" - " -{ - if (TARGET_BWX) - { - emit_insn (gen_extendqidi2x (operands[0], - force_reg (QImode, operands[1]))); - DONE; - } - - if (unaligned_memory_operand (operands[1], QImode)) - { - rtx seq - = gen_unaligned_extendqidi (operands[0], - get_unaligned_address (operands[1], 1)); - - alpha_set_memflags (seq, operands[1]); - emit_insn (seq); - DONE; - } - - operands[1] = gen_lowpart (DImode, force_reg (QImode, operands[1])); - operands[2] = gen_reg_rtx (DImode); -}") - -(define_expand "extendhisi2" - [(set (match_dup 2) - (ashift:DI (match_operand:HI 1 "some_operand" "") - (const_int 48))) - (set (match_operand:SI 0 "register_operand" "") - (ashiftrt:DI (match_dup 2) - (const_int 48)))] - "" - " -{ - if (TARGET_BWX) - { - emit_insn (gen_extendhisi2x (operands[0], - force_reg (HImode, operands[1]))); - DONE; - } - - /* If we have an unaligned MEM, extend to a DImode form of - the result (which we do specially). */ - if (unaligned_memory_operand (operands[1], HImode)) - { - rtx temp = gen_reg_rtx (DImode); - - emit_insn (gen_extendhidi2 (temp, operands[1])); - emit_move_insn (operands[0], gen_lowpart (SImode, temp)); - DONE; - } - - operands[0] = gen_lowpart (DImode, operands[0]); - operands[1] = gen_lowpart (DImode, force_reg (HImode, operands[1])); - operands[2] = gen_reg_rtx (DImode); -}") - -(define_expand "extendhidi2" - [(set (match_dup 2) - (ashift:DI (match_operand:HI 1 "some_operand" "") - (const_int 48))) - (set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_dup 2) - (const_int 48)))] - "" - " -{ - if (TARGET_BWX) - { - emit_insn (gen_extendhidi2x (operands[0], - force_reg (HImode, operands[1]))); - DONE; - } - - if (unaligned_memory_operand (operands[1], HImode)) - { - rtx seq - = gen_unaligned_extendhidi (operands[0], - get_unaligned_address (operands[1], 2)); - - alpha_set_memflags (seq, operands[1]); - emit_insn (seq); - DONE; - } - - operands[1] = gen_lowpart (DImode, force_reg (HImode, operands[1])); - operands[2] = gen_reg_rtx (DImode); -}") - -;; Here's how we sign extend an unaligned byte and halfword. Doing this -;; as a pattern saves one instruction. The code is similar to that for -;; the unaligned loads (see below). -;; -;; Operand 1 is the address + 1 (+2 for HI), operand 0 is the result. -(define_expand "unaligned_extendqidi" - [(set (match_dup 2) (match_operand:DI 1 "address_operand" "")) - (set (match_dup 3) - (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -1)) - (const_int -8)))) - (set (match_dup 4) - (ashift:DI (match_dup 3) - (minus:DI (const_int 56) - (ashift:DI - (and:DI (plus:DI (match_dup 2) (const_int -1)) - (const_int 7)) - (const_int 3))))) - (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) - (ashiftrt:DI (match_dup 4) (const_int 56)))] - "" - " -{ operands[2] = gen_reg_rtx (DImode); - operands[3] = gen_reg_rtx (DImode); - operands[4] = gen_reg_rtx (DImode); -}") - -(define_expand "unaligned_extendhidi" - [(set (match_dup 2) (match_operand:DI 1 "address_operand" "")) - (set (match_dup 3) - (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -2)) - (const_int -8)))) - (set (match_dup 4) - (ashift:DI (match_dup 3) - (minus:DI (const_int 56) - (ashift:DI - (and:DI (plus:DI (match_dup 2) (const_int -1)) - (const_int 7)) - (const_int 3))))) - (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) - (ashiftrt:DI (match_dup 4) (const_int 48)))] - "" - " -{ operands[2] = gen_reg_rtx (DImode); - operands[3] = gen_reg_rtx (DImode); - operands[4] = gen_reg_rtx (DImode); -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "mode_width_operand" "n") - (match_operand:DI 3 "mul8_operand" "I")))] - "" - "ext%M2l %r1,%s3,%0" - [(set_attr "type" "shift")]) - -(define_insn "extxl" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "mode_width_operand" "n") - (ashift:DI (match_operand:DI 3 "reg_or_8bit_operand" "rI") - (const_int 3))))] - "" - "ext%M2l %r1,%3,%0" - [(set_attr "type" "shift")]) - -;; Combine has some strange notion of preserving existing undefined behaviour -;; in shifts larger than a word size. So capture these patterns that it -;; should have turned into zero_extracts. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (and (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int 3))) - (match_operand:DI 3 "mode_mask_operand" "n")))] - "" - "ext%U3l %1,%2,%0" - [(set_attr "type" "shift")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int 3))))] - "" - "extql %1,%2,%0" - [(set_attr "type" "shift")]) - -(define_insn "extqh" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI - (match_operand:DI 1 "reg_or_0_operand" "rJ") - (minus:DI (const_int 56) - (ashift:DI - (and:DI - (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int -1)) - (const_int 7)) - (const_int 3)))))] - "" - "extqh %r1,%2,%0" - [(set_attr "type" "shift")]) - -(define_insn "extlh" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI - (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (const_int 2147483647)) - (minus:DI (const_int 56) - (ashift:DI - (and:DI - (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int -1)) - (const_int 7)) - (const_int 3)))))] - "" - "extlh %r1,%2,%0" - [(set_attr "type" "shift")]) - -(define_insn "extwh" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI - (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (const_int 65535)) - (minus:DI (const_int 56) - (ashift:DI - (and:DI - (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int -1)) - (const_int 7)) - (const_int 3)))))] - "" - "extwh %r1,%2,%0" - [(set_attr "type" "shift")]) - -;; This converts an extXl into an extXh with an appropriate adjustment -;; to the address calculation. - -;;(define_split -;; [(set (match_operand:DI 0 "register_operand" "") -;; (ashift:DI (zero_extract:DI (match_operand:DI 1 "register_operand" "") -;; (match_operand:DI 2 "mode_width_operand" "") -;; (ashift:DI (match_operand:DI 3 "" "") -;; (const_int 3))) -;; (match_operand:DI 4 "const_int_operand" ""))) -;; (clobber (match_operand:DI 5 "register_operand" ""))] -;; "INTVAL (operands[4]) == 64 - INTVAL (operands[2])" -;; [(set (match_dup 5) (match_dup 6)) -;; (set (match_dup 0) -;; (ashift:DI (zero_extract:DI (match_dup 1) (match_dup 2) -;; (ashift:DI (plus:DI (match_dup 5) -;; (match_dup 7)) -;; (const_int 3))) -;; (match_dup 4)))] -;; " -;;{ -;; operands[6] = plus_constant (operands[3], -;; INTVAL (operands[2]) / BITS_PER_UNIT); -;; operands[7] = GEN_INT (- INTVAL (operands[2]) / BITS_PER_UNIT); -;;}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r")) - (match_operand:DI 2 "mul8_operand" "I")))] - "" - "insbl %1,%s2,%0" - [(set_attr "type" "shift")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r")) - (match_operand:DI 2 "mul8_operand" "I")))] - "" - "inswl %1,%s2,%0" - [(set_attr "type" "shift")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) - (match_operand:DI 2 "mul8_operand" "I")))] - "" - "insll %1,%s2,%0" - [(set_attr "type" "shift")]) - -(define_insn "insbl" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r")) - (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int 3))))] - "" - "insbl %1,%2,%0" - [(set_attr "type" "shift")]) - -(define_insn "inswl" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r")) - (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int 3))))] - "" - "inswl %1,%2,%0" - [(set_attr "type" "shift")]) - -(define_insn "insll" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) - (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int 3))))] - "" - "insll %1,%2,%0" - [(set_attr "type" "shift")]) - -(define_insn "insql" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (match_operand:DI 1 "register_operand" "r") - (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") - (const_int 3))))] - "" - "insql %1,%2,%0" - [(set_attr "type" "shift")]) - -;; Combine has this sometimes habit of moving the and outside of the -;; shift, making life more interesting. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "mul8_operand" "I")) - (match_operand:DI 3 "immediate_operand" "i")))] - "HOST_BITS_PER_WIDE_INT == 64 - && GET_CODE (operands[3]) == CONST_INT - && (((unsigned HOST_WIDE_INT) 0xff << INTVAL (operands[2]) - == INTVAL (operands[3])) - || ((unsigned HOST_WIDE_INT) 0xffff << INTVAL (operands[2]) - == INTVAL (operands[3])) - || ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2]) - == INTVAL (operands[3])))" - "* -{ -#if HOST_BITS_PER_WIDE_INT == 64 - if ((unsigned HOST_WIDE_INT) 0xff << INTVAL (operands[2]) - == INTVAL (operands[3])) - return \"insbl %1,%s2,%0\"; - if ((unsigned HOST_WIDE_INT) 0xffff << INTVAL (operands[2]) - == INTVAL (operands[3])) - return \"inswl %1,%s2,%0\"; - if ((unsigned HOST_WIDE_INT) 0xffffffff << INTVAL (operands[2]) - == INTVAL (operands[3])) - return \"insll %1,%s2,%0\"; -#endif - abort(); -}" - [(set_attr "type" "shift")]) - -;; We do not include the insXh insns because they are complex to express -;; and it does not appear that we would ever want to generate them. -;; -;; Since we need them for block moves, though, cop out and use unspec. - -(define_insn "insxh" - [(set (match_operand:DI 0 "register_operand" "=r") - (unspec [(match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "mode_width_operand" "n") - (match_operand:DI 3 "reg_or_8bit_operand" "rI")] 2))] - "" - "ins%M2h %1,%3,%0" - [(set_attr "type" "shift")]) - -(define_insn "mskxl" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (not:DI (ashift:DI - (match_operand:DI 2 "mode_mask_operand" "n") - (ashift:DI - (match_operand:DI 3 "reg_or_8bit_operand" "rI") - (const_int 3)))) - (match_operand:DI 1 "reg_or_0_operand" "rJ")))] - "" - "msk%U2l %r1,%3,%0" - [(set_attr "type" "shift")]) - -;; We do not include the mskXh insns because it does not appear we would -;; ever generate one. -;; -;; Again, we do for block moves and we use unspec again. - -(define_insn "mskxh" - [(set (match_operand:DI 0 "register_operand" "=r") - (unspec [(match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "mode_width_operand" "n") - (match_operand:DI 3 "reg_or_8bit_operand" "rI")] 3))] - "" - "msk%M2h %1,%3,%0" - [(set_attr "type" "shift")]) - -;; Floating-point operations. All the double-precision insns can extend -;; from single, so indicate that. The exception are the ones that simply -;; play with the sign bits; it's not clear what to do there. - -(define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (abs:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "cpys $f31,%R1,%0" - [(set_attr "type" "fcpys")]) - -(define_insn "absdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "cpys $f31,%R1,%0" - [(set_attr "type" "fcpys")]) - -(define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "cpysn %R1,%R1,%0" - [(set_attr "type" "fadd")]) - -(define_insn "negdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "cpysn %R1,%R1,%0" - [(set_attr "type" "fadd")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=&f") - (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") - (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "add%,%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") - (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "add%,%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "add%-%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "adddf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "add%-%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "fG")) - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "add%-%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) - (float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "add%-%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -;; Define conversion operators between DFmode and SImode, using the cvtql -;; instruction. To allow combine et al to do useful things, we keep the -;; operation as a unit until after reload, at which point we split the -;; instructions. -;; -;; Note that we (attempt to) only consider this optimization when the -;; ultimate destination is memory. If we will be doing further integer -;; processing, it is cheaper to do the truncation in the int regs. - -(define_insn "*cvtql" - [(set (match_operand:SI 0 "register_operand" "=f") - (unspec:SI [(match_operand:DI 1 "reg_or_fp0_operand" "fG")] 5))] - "TARGET_FP" - "cvtql%` %R1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_split - [(set (match_operand:SI 0 "memory_operand" "") - (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "")) 0)) - (clobber (match_scratch:DI 2 "")) - (clobber (match_scratch:SI 3 ""))] - "TARGET_FP && reload_completed" - [(set (match_dup 2) (fix:DI (match_dup 1))) - (set (match_dup 3) (unspec:SI [(match_dup 2)] 5)) - (set (match_dup 0) (match_dup 3))] - "") - -(define_split - [(set (match_operand:SI 0 "memory_operand" "") - (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "")) 0)) - (clobber (match_scratch:DI 2 ""))] - "TARGET_FP && reload_completed" - [(set (match_dup 2) (fix:DI (match_dup 1))) - (set (match_dup 3) (unspec:SI [(match_dup 2)] 5)) - (set (match_dup 0) (match_dup 3))] - ;; Due to REG_CANNOT_CHANGE_SIZE issues, we cannot simply use SUBREG. - "operands[3] = gen_rtx_REG (SImode, REGNO (operands[2]));") - -(define_insn "" - [(set (match_operand:SI 0 "memory_operand" "=m") - (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0)) - (clobber (match_scratch:DI 2 "=&f")) - (clobber (match_scratch:SI 3 "=&f"))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "#" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:SI 0 "memory_operand" "=m") - (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0)) - (clobber (match_scratch:DI 2 "=f"))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "#" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=&f") - (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cvt%-q%(c %R1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "fix_truncdfdi2" - [(set (match_operand:DI 0 "register_operand" "=f") - (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "cvt%-q%(c %R1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -;; Likewise between SFmode and SImode. - -(define_split - [(set (match_operand:SI 0 "memory_operand" "") - (subreg:SI (fix:DI (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" ""))) 0)) - (clobber (match_scratch:DI 2 "")) - (clobber (match_scratch:SI 3 ""))] - "TARGET_FP && reload_completed" - [(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1)))) - (set (match_dup 3) (unspec:SI [(match_dup 2)] 5)) - (set (match_dup 0) (match_dup 3))] - "") - -(define_split - [(set (match_operand:SI 0 "memory_operand" "") - (subreg:SI (fix:DI (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" ""))) 0)) - (clobber (match_scratch:DI 2 ""))] - "TARGET_FP && reload_completed" - [(set (match_dup 2) (fix:DI (float_extend:DF (match_dup 1)))) - (set (match_dup 3) (unspec:SI [(match_dup 2)] 5)) - (set (match_dup 0) (match_dup 3))] - ;; Due to REG_CANNOT_CHANGE_SIZE issues, we cannot simply use SUBREG. - "operands[3] = gen_rtx_REG (SImode, REGNO (operands[2]));") - -(define_insn "" - [(set (match_operand:SI 0 "memory_operand" "=m") - (subreg:SI (fix:DI (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0)) - (clobber (match_scratch:DI 2 "=&f")) - (clobber (match_scratch:SI 3 "=&f"))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "#" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:SI 0 "memory_operand" "=m") - (subreg:SI (fix:DI (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0)) - (clobber (match_scratch:DI 2 "=f"))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "#" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=&f") - (fix:DI (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cvt%-q%(c %R1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "fix_truncsfdi2" - [(set (match_operand:DI 0 "register_operand" "=f") - (fix:DI (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP" - "cvt%-q%(c %R1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=&f") - (float:SF (match_operand:DI 1 "register_operand" "f")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cvtq%,%+%& %1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "floatdisf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (float:SF (match_operand:DI 1 "register_operand" "f")))] - "TARGET_FP" - "cvtq%,%+%& %1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (float:DF (match_operand:DI 1 "register_operand" "f")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cvtq%-%+%& %1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "floatdidf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (float:DF (match_operand:DI 1 "register_operand" "f")))] - "TARGET_FP" - "cvtq%-%+%& %1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_expand "extendsfdf2" - [(use (match_operand:DF 0 "register_operand" "")) - (use (match_operand:SF 1 "nonimmediate_operand" ""))] - "TARGET_FP" -" -{ - if (alpha_tp == ALPHA_TP_INSN) - emit_insn (gen_extendsfdf2_tp (operands[0], - force_reg (SFmode, operands[1]))); - else - emit_insn (gen_extendsfdf2_no_tp (operands[0], operands[1])); - - DONE; -}") -;; FIXME -(define_insn "extendsfdf2_tp" - [(set (match_operand:DF 0 "register_operand" "=&f") - (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cvtsts %1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "extendsfdf2_no_tp" - [(set (match_operand:DF 0 "register_operand" "=f,f,m") - (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m,f")))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "@ - cpys %1,%1,%0 - ld%, %0,%1 - st%- %1,%0" - [(set_attr "type" "fcpys,fld,fst") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=&f") - (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cvt%-%,%)%& %R1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "cvt%-%,%)%& %R1,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=&f") - (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") - (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "div%,%)%& %R1,%R2,%0" - [(set_attr "type" "fdiv") - (set_attr "opsize" "si") - (set_attr "trap" "yes")]) - -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") - (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "div%,%)%& %R1,%R2,%0" - [(set_attr "type" "fdiv") - (set_attr "opsize" "si") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "div%-%)%& %R1,%R2,%0" - [(set_attr "type" "fdiv") - (set_attr "trap" "yes")]) - -(define_insn "divdf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "div%-%)%& %R1,%R2,%0" - [(set_attr "type" "fdiv") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "div%-%)%& %R1,%R2,%0" - [(set_attr "type" "fdiv") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") - (float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "div%-%)%& %R1,%R2,%0" - [(set_attr "type" "fdiv") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG")) - (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "div%-%)%& %R1,%R2,%0" - [(set_attr "type" "fdiv") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=&f") - (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") - (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "mul%,%)%& %R1,%R2,%0" - [(set_attr "type" "fmul") - (set_attr "trap" "yes")]) - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") - (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "mul%,%)%& %R1,%R2,%0" - [(set_attr "type" "fmul") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "mul%-%)%& %R1,%R2,%0" - [(set_attr "type" "fmul") - (set_attr "trap" "yes")]) - -(define_insn "muldf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "mul%-%)%& %R1,%R2,%0" - [(set_attr "type" "fmul") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (mult:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "fG")) - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "mul%-%)%& %R1,%R2,%0" - [(set_attr "type" "fmul") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (mult:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) - (float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "mul%-%)%& %R1,%R2,%0" - [(set_attr "type" "fmul") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=&f") - (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") - (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "sub%,%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") - (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "sub%,%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "sub%-%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "subdf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP" - "sub%-%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "fG")) - (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "sub%-%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") - (float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "sub%-%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "fG")) - (float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "sub%-%)%& %R1,%R2,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=&f") - (sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && TARGET_CIX && alpha_tp == ALPHA_TP_INSN" - "sqrt%,%)%& %R1,%0" - [(set_attr "type" "fsqrt") - (set_attr "opsize" "si") - (set_attr "trap" "yes")]) - -(define_insn "sqrtsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && TARGET_CIX" - "sqrt%,%)%& %R1,%0" - [(set_attr "type" "fsqrt") - (set_attr "opsize" "si") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && TARGET_CIX && alpha_tp == ALPHA_TP_INSN" - "sqrt%-%)%& %R1,%0" - [(set_attr "type" "fsqrt") - (set_attr "trap" "yes")]) - -(define_insn "sqrtdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] - "TARGET_FP && TARGET_CIX" - "sqrt%-%)%& %1,%0" - [(set_attr "type" "fsqrt") - (set_attr "trap" "yes")]) - -;; Next are all the integer comparisons, and conditional moves and branches -;; and some of the related define_expand's and define_split's. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (match_operator:DI 1 "alpha_comparison_operator" - [(match_operand:DI 2 "reg_or_0_operand" "rJ") - (match_operand:DI 3 "reg_or_8bit_operand" "rI")]))] - "" - "cmp%C1 %r2,%3,%0" - [(set_attr "type" "icmp")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (match_operator:DI 1 "alpha_swapped_comparison_operator" - [(match_operand:DI 2 "reg_or_8bit_operand" "rI") - (match_operand:DI 3 "reg_or_0_operand" "rJ")]))] - "" - "cmp%c1 %r3,%2,%0" - [(set_attr "type" "icmp")]) - -;; This pattern exists so conditional moves of SImode values are handled. -;; Comparisons are still done in DImode though. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (if_then_else:SI - (match_operator 2 "signed_comparison_operator" - [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ,J,J") - (match_operand:DI 4 "reg_or_0_operand" "J,J,rJ,rJ")]) - (match_operand:SI 1 "reg_or_8bit_operand" "rI,0,rI,0") - (match_operand:SI 5 "reg_or_8bit_operand" "0,rI,0,rI")))] - "operands[3] == const0_rtx || operands[4] == const0_rtx" - "@ - cmov%C2 %r3,%1,%0 - cmov%D2 %r3,%5,%0 - cmov%c2 %r4,%1,%0 - cmov%d2 %r4,%5,%0" - [(set_attr "type" "icmov")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") - (if_then_else:DI - (match_operator 2 "signed_comparison_operator" - [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ,J,J") - (match_operand:DI 4 "reg_or_0_operand" "J,J,rJ,rJ")]) - (match_operand:DI 1 "reg_or_8bit_operand" "rI,0,rI,0") - (match_operand:DI 5 "reg_or_8bit_operand" "0,rI,0,rI")))] - "operands[3] == const0_rtx || operands[4] == const0_rtx" - "@ - cmov%C2 %r3,%1,%0 - cmov%D2 %r3,%5,%0 - cmov%c2 %r4,%1,%0 - cmov%d2 %r4,%5,%0" - [(set_attr "type" "icmov")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (if_then_else:DI - (eq (zero_extract:DI (match_operand:DI 2 "reg_or_0_operand" "rJ,rJ") - (const_int 1) - (const_int 0)) - (const_int 0)) - (match_operand:DI 1 "reg_or_8bit_operand" "rI,0") - (match_operand:DI 3 "reg_or_8bit_operand" "0,rI")))] - "" - "@ - cmovlbc %r2,%1,%0 - cmovlbs %r2,%3,%0" - [(set_attr "type" "icmov")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (if_then_else:DI - (ne (zero_extract:DI (match_operand:DI 2 "reg_or_0_operand" "rJ,rJ") - (const_int 1) - (const_int 0)) - (const_int 0)) - (match_operand:DI 1 "reg_or_8bit_operand" "rI,0") - (match_operand:DI 3 "reg_or_8bit_operand" "0,rI")))] - "" - "@ - cmovlbs %r2,%1,%0 - cmovlbc %r2,%3,%0" - [(set_attr "type" "icmov")]) - -;; This form is added since combine thinks that an IF_THEN_ELSE with both -;; arms constant is a single insn, so it won't try to form it if combine -;; knows they are really two insns. This occurs in divides by powers -;; of two. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (if_then_else:DI - (match_operator 2 "signed_comparison_operator" - [(match_operand:DI 3 "reg_or_0_operand" "rJ") - (const_int 0)]) - (plus:DI (match_dup 0) - (match_operand:DI 1 "reg_or_8bit_operand" "rI")) - (match_dup 0))) - (clobber (match_scratch:DI 4 "=&r"))] - "" - "addq %0,%1,%4\;cmov%C2 %r3,%4,%0" - [(set_attr "type" "icmov") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI - (match_operator 2 "signed_comparison_operator" - [(match_operand:DI 3 "reg_or_0_operand" "") - (const_int 0)]) - (plus:DI (match_dup 0) - (match_operand:DI 1 "reg_or_8bit_operand" "")) - (match_dup 0))) - (clobber (match_operand:DI 4 "register_operand" ""))] - "" - [(set (match_dup 4) (plus:DI (match_dup 0) (match_dup 1))) - (set (match_dup 0) (if_then_else:DI (match_op_dup 2 - [(match_dup 3) - (const_int 0)]) - (match_dup 4) (match_dup 0)))] - "") - -(define_split - [(parallel - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI - (match_operator 1 "comparison_operator" - [(zero_extract:DI (match_operand:DI 2 "register_operand" "") - (const_int 1) - (match_operand:DI 3 "const_int_operand" "")) - (const_int 0)]) - (match_operand:DI 4 "reg_or_8bit_operand" "") - (match_operand:DI 5 "reg_or_8bit_operand" ""))) - (clobber (match_operand:DI 6 "register_operand" ""))])] - "INTVAL (operands[3]) != 0" - [(set (match_dup 6) - (lshiftrt:DI (match_dup 2) (match_dup 3))) - (set (match_dup 0) - (if_then_else:DI (match_op_dup 1 - [(zero_extract:DI (match_dup 6) - (const_int 1) - (const_int 0)) - (const_int 0)]) - (match_dup 4) - (match_dup 5)))] - "") - -;; For ABS, we have two choices, depending on whether the input and output -;; registers are the same or not. -(define_expand "absdi2" - [(set (match_operand:DI 0 "register_operand" "") - (abs:DI (match_operand:DI 1 "register_operand" "")))] - "" - " -{ if (rtx_equal_p (operands[0], operands[1])) - emit_insn (gen_absdi2_same (operands[0], gen_reg_rtx (DImode))); - else - emit_insn (gen_absdi2_diff (operands[0], operands[1])); - - DONE; -}") - -(define_expand "absdi2_same" - [(set (match_operand:DI 1 "register_operand" "") - (neg:DI (match_operand:DI 0 "register_operand" ""))) - (set (match_dup 0) - (if_then_else:DI (ge (match_dup 0) (const_int 0)) - (match_dup 0) - (match_dup 1)))] - "" - "") - -(define_expand "absdi2_diff" - [(set (match_operand:DI 0 "register_operand" "") - (neg:DI (match_operand:DI 1 "register_operand" ""))) - (set (match_dup 0) - (if_then_else:DI (lt (match_dup 1) (const_int 0)) - (match_dup 0) - (match_dup 1)))] - "" - "") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (abs:DI (match_dup 0))) - (clobber (match_operand:DI 2 "register_operand" ""))] - "" - [(set (match_dup 1) (neg:DI (match_dup 0))) - (set (match_dup 0) (if_then_else:DI (ge (match_dup 0) (const_int 0)) - (match_dup 0) (match_dup 1)))] - "") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (abs:DI (match_operand:DI 1 "register_operand" "")))] - "! rtx_equal_p (operands[0], operands[1])" - [(set (match_dup 0) (neg:DI (match_dup 1))) - (set (match_dup 0) (if_then_else:DI (lt (match_dup 1) (const_int 0)) - (match_dup 0) (match_dup 1)))] - "") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (neg:DI (abs:DI (match_dup 0)))) - (clobber (match_operand:DI 2 "register_operand" ""))] - "" - [(set (match_dup 1) (neg:DI (match_dup 0))) - (set (match_dup 0) (if_then_else:DI (le (match_dup 0) (const_int 0)) - (match_dup 0) (match_dup 1)))] - "") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (neg:DI (abs:DI (match_operand:DI 1 "register_operand" ""))))] - "! rtx_equal_p (operands[0], operands[1])" - [(set (match_dup 0) (neg:DI (match_dup 1))) - (set (match_dup 0) (if_then_else:DI (gt (match_dup 1) (const_int 0)) - (match_dup 0) (match_dup 1)))] - "") - -(define_insn "sminqi3" - [(set (match_operand:QI 0 "register_operand" "=r") - (smin:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ") - (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] - "TARGET_MAX" - "minsb8 %r1,%2,%0" - [(set_attr "type" "mvi")]) - -(define_insn "uminqi3" - [(set (match_operand:QI 0 "register_operand" "=r") - (umin:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ") - (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] - "TARGET_MAX" - "minub8 %r1,%2,%0" - [(set_attr "type" "mvi")]) - -(define_insn "smaxqi3" - [(set (match_operand:QI 0 "register_operand" "=r") - (smax:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ") - (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] - "TARGET_MAX" - "maxsb8 %r1,%2,%0" - [(set_attr "type" "mvi")]) - -(define_insn "umaxqi3" - [(set (match_operand:QI 0 "register_operand" "=r") - (umax:QI (match_operand:QI 1 "reg_or_0_operand" "%rJ") - (match_operand:QI 2 "reg_or_8bit_operand" "rI")))] - "TARGET_MAX" - "maxub8 %r1,%2,%0" - [(set_attr "type" "mvi")]) - -(define_insn "sminhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (smin:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ") - (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] - "TARGET_MAX" - "minsw4 %r1,%2,%0" - [(set_attr "type" "mvi")]) - -(define_insn "uminhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (umin:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ") - (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] - "TARGET_MAX" - "minuw4 %r1,%2,%0" - [(set_attr "type" "mvi")]) - -(define_insn "smaxhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (smax:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ") - (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] - "TARGET_MAX" - "maxsw4 %r1,%2,%0" - [(set_attr "type" "mvi")]) - -(define_insn "umaxhi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (umax:HI (match_operand:HI 1 "reg_or_0_operand" "%rJ") - (match_operand:HI 2 "reg_or_8bit_operand" "rI")))] - "TARGET_MAX" - "maxuw4 %r1,%2,%0" - [(set_attr "type" "shift")]) - -(define_expand "smaxdi3" - [(set (match_dup 3) - (le:DI (match_operand:DI 1 "reg_or_0_operand" "") - (match_operand:DI 2 "reg_or_8bit_operand" ""))) - (set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (eq (match_dup 3) (const_int 0)) - (match_dup 1) (match_dup 2)))] - "" - " -{ operands[3] = gen_reg_rtx (DImode); -}") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (smax:DI (match_operand:DI 1 "reg_or_0_operand" "") - (match_operand:DI 2 "reg_or_8bit_operand" ""))) - (clobber (match_operand:DI 3 "register_operand" ""))] - "operands[2] != const0_rtx" - [(set (match_dup 3) (le:DI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (if_then_else:DI (eq (match_dup 3) (const_int 0)) - (match_dup 1) (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (smax:DI (match_operand:DI 1 "register_operand" "0") - (const_int 0)))] - "" - "cmovlt %0,0,%0" - [(set_attr "type" "icmov")]) - -(define_expand "smindi3" - [(set (match_dup 3) - (lt:DI (match_operand:DI 1 "reg_or_0_operand" "") - (match_operand:DI 2 "reg_or_8bit_operand" ""))) - (set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (ne (match_dup 3) (const_int 0)) - (match_dup 1) (match_dup 2)))] - "" - " -{ operands[3] = gen_reg_rtx (DImode); -}") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (smin:DI (match_operand:DI 1 "reg_or_0_operand" "") - (match_operand:DI 2 "reg_or_8bit_operand" ""))) - (clobber (match_operand:DI 3 "register_operand" ""))] - "operands[2] != const0_rtx" - [(set (match_dup 3) (lt:DI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (if_then_else:DI (ne (match_dup 3) (const_int 0)) - (match_dup 1) (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (smin:DI (match_operand:DI 1 "register_operand" "0") - (const_int 0)))] - "" - "cmovgt %0,0,%0" - [(set_attr "type" "icmov")]) - -(define_expand "umaxdi3" - [(set (match_dup 3) - (leu:DI (match_operand:DI 1 "reg_or_0_operand" "") - (match_operand:DI 2 "reg_or_8bit_operand" ""))) - (set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (eq (match_dup 3) (const_int 0)) - (match_dup 1) (match_dup 2)))] - "" - " -{ operands[3] = gen_reg_rtx (DImode); -}") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (umax:DI (match_operand:DI 1 "reg_or_0_operand" "") - (match_operand:DI 2 "reg_or_8bit_operand" ""))) - (clobber (match_operand:DI 3 "register_operand" ""))] - "operands[2] != const0_rtx" - [(set (match_dup 3) (leu:DI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (if_then_else:DI (eq (match_dup 3) (const_int 0)) - (match_dup 1) (match_dup 2)))] - "") - -(define_expand "umindi3" - [(set (match_dup 3) - (ltu:DI (match_operand:DI 1 "reg_or_0_operand" "") - (match_operand:DI 2 "reg_or_8bit_operand" ""))) - (set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (ne (match_dup 3) (const_int 0)) - (match_dup 1) (match_dup 2)))] - "" - " -{ operands[3] = gen_reg_rtx (DImode); -}") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (umin:DI (match_operand:DI 1 "reg_or_0_operand" "") - (match_operand:DI 2 "reg_or_8bit_operand" ""))) - (clobber (match_operand:DI 3 "register_operand" ""))] - "operands[2] != const0_rtx" - [(set (match_dup 3) (ltu:DI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (if_then_else:DI (ne (match_dup 3) (const_int 0)) - (match_dup 1) (match_dup 2)))] - "") - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 1 "signed_comparison_operator" - [(match_operand:DI 2 "reg_or_0_operand" "rJ") - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "b%C1 %r2,%0" - [(set_attr "type" "ibr")]) - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 1 "signed_comparison_operator" - [(const_int 0) - (match_operand:DI 2 "register_operand" "r")]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "b%c1 %2,%0" - [(set_attr "type" "ibr")]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (const_int 1) - (const_int 0)) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "blbs %r1,%0" - [(set_attr "type" "ibr")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (const_int 1) - (const_int 0)) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "blbc %r1,%0" - [(set_attr "type" "ibr")]) - -(define_split - [(parallel - [(set (pc) - (if_then_else - (match_operator 1 "comparison_operator" - [(zero_extract:DI (match_operand:DI 2 "register_operand" "") - (const_int 1) - (match_operand:DI 3 "const_int_operand" "")) - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc))) - (clobber (match_operand:DI 4 "register_operand" ""))])] - "INTVAL (operands[3]) != 0" - [(set (match_dup 4) - (lshiftrt:DI (match_dup 2) (match_dup 3))) - (set (pc) - (if_then_else (match_op_dup 1 - [(zero_extract:DI (match_dup 4) - (const_int 1) - (const_int 0)) - (const_int 0)]) - (label_ref (match_dup 0)) - (pc)))] - "") - -;; The following are the corresponding floating-point insns. Recall -;; we need to have variants that expand the arguments from SF mode -;; to DFmode. - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (match_operator:DF 1 "alpha_comparison_operator" - [(match_operand:DF 2 "reg_or_fp0_operand" "fG") - (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cmp%-%C1%' %R2,%R3,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (match_operator:DF 1 "alpha_comparison_operator" - [(match_operand:DF 2 "reg_or_fp0_operand" "fG") - (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "cmp%-%C1%' %R2,%R3,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (match_operator:DF 1 "alpha_comparison_operator" - [(float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG")) - (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cmp%-%C1%' %R2,%R3,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (match_operator:DF 1 "alpha_comparison_operator" - [(float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG")) - (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "cmp%-%C1%' %R2,%R3,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (match_operator:DF 1 "alpha_comparison_operator" - [(match_operand:DF 2 "reg_or_fp0_operand" "fG") - (float_extend:DF - (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cmp%-%C1%' %R2,%R3,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (match_operator:DF 1 "alpha_comparison_operator" - [(match_operand:DF 2 "reg_or_fp0_operand" "fG") - (float_extend:DF - (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "cmp%-%C1%' %R2,%R3,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=&f") - (match_operator:DF 1 "alpha_comparison_operator" - [(float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG")) - (float_extend:DF - (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] - "TARGET_FP && alpha_tp == ALPHA_TP_INSN" - "cmp%-%C1%' %R2,%R3,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (match_operator:DF 1 "alpha_comparison_operator" - [(float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG")) - (float_extend:DF - (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))] - "TARGET_FP && alpha_tp != ALPHA_TP_INSN" - "cmp%-%C1%' %R2,%R3,%0" - [(set_attr "type" "fadd") - (set_attr "trap" "yes")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (if_then_else:DF - (match_operator 3 "signed_comparison_operator" - [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG") - (match_operand:DF 2 "fp0_operand" "G,G")]) - (match_operand:DF 1 "reg_or_fp0_operand" "fG,0") - (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] - "TARGET_FP" - "@ - fcmov%C3 %R4,%R1,%0 - fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fcmov")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (if_then_else:SF - (match_operator 3 "signed_comparison_operator" - [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG") - (match_operand:DF 2 "fp0_operand" "G,G")]) - (match_operand:SF 1 "reg_or_fp0_operand" "fG,0") - (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))] - "TARGET_FP" - "@ - fcmov%C3 %R4,%R1,%0 - fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fcmov")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (if_then_else:DF - (match_operator 3 "signed_comparison_operator" - [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG") - (match_operand:DF 2 "fp0_operand" "G,G")]) - (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")) - (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] - "TARGET_FP" - "@ - fcmov%C3 %R4,%R1,%0 - fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fcmov")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (if_then_else:DF - (match_operator 3 "signed_comparison_operator" - [(float_extend:DF - (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG")) - (match_operand:DF 2 "fp0_operand" "G,G")]) - (match_operand:DF 1 "reg_or_fp0_operand" "fG,0") - (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] - "TARGET_FP" - "@ - fcmov%C3 %R4,%R1,%0 - fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fcmov")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (if_then_else:SF - (match_operator 3 "signed_comparison_operator" - [(float_extend:DF - (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG")) - (match_operand:DF 2 "fp0_operand" "G,G")]) - (match_operand:SF 1 "reg_or_fp0_operand" "fG,0") - (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))] - "TARGET_FP" - "@ - fcmov%C3 %R4,%R1,%0 - fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fcmov")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (if_then_else:DF - (match_operator 3 "signed_comparison_operator" - [(float_extend:DF - (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG")) - (match_operand:DF 2 "fp0_operand" "G,G")]) - (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")) - (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))] - "TARGET_FP" - "@ - fcmov%C3 %R4,%R1,%0 - fcmov%D3 %R4,%R5,%0" - [(set_attr "type" "fcmov")]) - -(define_expand "maxdf3" - [(set (match_dup 3) - (le:DF (match_operand:DF 1 "reg_or_fp0_operand" "") - (match_operand:DF 2 "reg_or_fp0_operand" ""))) - (set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (eq (match_dup 3) (match_dup 4)) - (match_dup 1) (match_dup 2)))] - "TARGET_FP" - " -{ operands[3] = gen_reg_rtx (DFmode); - operands[4] = CONST0_RTX (DFmode); -}") - -(define_expand "mindf3" - [(set (match_dup 3) - (lt:DF (match_operand:DF 1 "reg_or_fp0_operand" "") - (match_operand:DF 2 "reg_or_fp0_operand" ""))) - (set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (ne (match_dup 3) (match_dup 4)) - (match_dup 1) (match_dup 2)))] - "TARGET_FP" - " -{ operands[3] = gen_reg_rtx (DFmode); - operands[4] = CONST0_RTX (DFmode); -}") - -(define_expand "maxsf3" - [(set (match_dup 3) - (le:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "")) - (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "")))) - (set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (eq (match_dup 3) (match_dup 4)) - (match_dup 1) (match_dup 2)))] - "TARGET_FP" - " -{ operands[3] = gen_reg_rtx (DFmode); - operands[4] = CONST0_RTX (DFmode); -}") - -(define_expand "minsf3" - [(set (match_dup 3) - (lt:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "")) - (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "")))) - (set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (ne (match_dup 3) (match_dup 4)) - (match_dup 1) (match_dup 2)))] - "TARGET_FP" - " -{ operands[3] = gen_reg_rtx (DFmode); - operands[4] = CONST0_RTX (DFmode); -}") - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 1 "signed_comparison_operator" - [(match_operand:DF 2 "reg_or_fp0_operand" "fG") - (match_operand:DF 3 "fp0_operand" "G")]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_FP" - "fb%C1 %R2,%0" - [(set_attr "type" "fbr")]) - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 1 "signed_comparison_operator" - [(float_extend:DF - (match_operand:SF 2 "reg_or_fp0_operand" "fG")) - (match_operand:DF 3 "fp0_operand" "G")]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_FP" - "fb%C1 %R2,%0" - [(set_attr "type" "fbr")]) - -;; These are the main define_expand's used to make conditional branches -;; and compares. - -(define_expand "cmpdf" - [(set (cc0) (compare (match_operand:DF 0 "reg_or_fp0_operand" "") - (match_operand:DF 1 "reg_or_fp0_operand" "")))] - "TARGET_FP" - " -{ - alpha_compare_op0 = operands[0]; - alpha_compare_op1 = operands[1]; - alpha_compare_fp_p = 1; - DONE; -}") - -(define_expand "cmpdi" - [(set (cc0) (compare (match_operand:DI 0 "reg_or_0_operand" "") - (match_operand:DI 1 "reg_or_8bit_operand" "")))] - "" - " -{ - alpha_compare_op0 = operands[0]; - alpha_compare_op1 = operands[1]; - alpha_compare_fp_p = 0; - DONE; -}") - -(define_expand "beq" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (EQ); }") - -(define_expand "bne" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (NE); }") - -(define_expand "blt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LT); }") - -(define_expand "ble" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LE); }") - -(define_expand "bgt" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GT); }") - -(define_expand "bge" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GE); }") - -(define_expand "bltu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LTU); }") - -(define_expand "bleu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (LEU); }") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GTU); }") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ operands[1] = alpha_emit_conditional_branch (GEU); }") - -(define_expand "seq" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_EQ (DImode, alpha_compare_op0, alpha_compare_op1); -}") - -(define_expand "sne" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1)) - (set (match_dup 0) (xor:DI (match_dup 0) (const_int 1)))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_EQ (DImode, alpha_compare_op0, alpha_compare_op1); -}") - -(define_expand "slt" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_LT (DImode, alpha_compare_op0, alpha_compare_op1); -}") - -(define_expand "sle" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_LE (DImode, alpha_compare_op0, alpha_compare_op1); -}") - -(define_expand "sgt" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_LT (DImode, force_reg (DImode, alpha_compare_op1), - alpha_compare_op0); -}") - -(define_expand "sge" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_LE (DImode, force_reg (DImode, alpha_compare_op1), - alpha_compare_op0); -}") - -(define_expand "sltu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_LTU (DImode, alpha_compare_op0, alpha_compare_op1); -}") - -(define_expand "sleu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_LEU (DImode, alpha_compare_op0, alpha_compare_op1); -}") - -(define_expand "sgtu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_LTU (DImode, force_reg (DImode, alpha_compare_op1), - alpha_compare_op0); -}") - -(define_expand "sgeu" - [(set (match_operand:DI 0 "register_operand" "") - (match_dup 1))] - "" - " -{ - if (alpha_compare_fp_p) - FAIL; - - operands[1] = gen_rtx_LEU (DImode, force_reg (DImode, alpha_compare_op1), - alpha_compare_op0); -}") - -;; These are the main define_expand's used to make conditional moves. - -(define_expand "movsicc" - [(set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI (match_operand 1 "comparison_operator" "") - (match_operand:SI 2 "reg_or_8bit_operand" "") - (match_operand:SI 3 "reg_or_8bit_operand" "")))] - "" - " -{ - if ((operands[1] = alpha_emit_conditional_move (operands[1], SImode)) == 0) - FAIL; -}") - -(define_expand "movdicc" - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (match_operand 1 "comparison_operator" "") - (match_operand:DI 2 "reg_or_8bit_operand" "") - (match_operand:DI 3 "reg_or_8bit_operand" "")))] - "" - " -{ - if ((operands[1] = alpha_emit_conditional_move (operands[1], DImode)) == 0) - FAIL; -}") - -(define_expand "movsfcc" - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operand 1 "comparison_operator" "") - (match_operand:SF 2 "reg_or_8bit_operand" "") - (match_operand:SF 3 "reg_or_8bit_operand" "")))] - "" - " -{ - if ((operands[1] = alpha_emit_conditional_move (operands[1], SFmode)) == 0) - FAIL; -}") - -(define_expand "movdfcc" - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (match_operand 1 "comparison_operator" "") - (match_operand:DF 2 "reg_or_8bit_operand" "") - (match_operand:DF 3 "reg_or_8bit_operand" "")))] - "" - " -{ - if ((operands[1] = alpha_emit_conditional_move (operands[1], DFmode)) == 0) - FAIL; -}") - -;; These define_split definitions are used in cases when comparisons have -;; not be stated in the correct way and we need to reverse the second -;; comparison. For example, x >= 7 has to be done as x < 6 with the -;; comparison that tests the result being reversed. We have one define_split -;; for each use of a comparison. They do not match valid insns and need -;; not generate valid insns. -;; -;; We can also handle equality comparisons (and inequality comparisons in -;; cases where the resulting add cannot overflow) by doing an add followed by -;; a comparison with zero. This is faster since the addition takes one -;; less cycle than a compare when feeding into a conditional move. -;; For this case, we also have an SImode pattern since we can merge the add -;; and sign extend and the order doesn't matter. -;; -;; We do not do this for floating-point, since it isn't clear how the "wrong" -;; operation could have been generated. - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI - (match_operator 1 "comparison_operator" - [(match_operand:DI 2 "reg_or_0_operand" "") - (match_operand:DI 3 "reg_or_cint_operand" "")]) - (match_operand:DI 4 "reg_or_cint_operand" "") - (match_operand:DI 5 "reg_or_cint_operand" ""))) - (clobber (match_operand:DI 6 "register_operand" ""))] - "operands[3] != const0_rtx" - [(set (match_dup 6) (match_dup 7)) - (set (match_dup 0) - (if_then_else:DI (match_dup 8) (match_dup 4) (match_dup 5)))] - " -{ enum rtx_code code = GET_CODE (operands[1]); - int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU); - - /* If we are comparing for equality with a constant and that constant - appears in the arm when the register equals the constant, use the - register since that is more likely to match (and to produce better code - if both would). */ - - if (code == EQ && GET_CODE (operands[3]) == CONST_INT - && rtx_equal_p (operands[4], operands[3])) - operands[4] = operands[2]; - - else if (code == NE && GET_CODE (operands[3]) == CONST_INT - && rtx_equal_p (operands[5], operands[3])) - operands[5] = operands[2]; - - if (code == NE || code == EQ - || (extended_count (operands[2], DImode, unsignedp) >= 1 - && extended_count (operands[3], DImode, unsignedp) >= 1)) - { - if (GET_CODE (operands[3]) == CONST_INT) - operands[7] = gen_rtx_PLUS (DImode, operands[2], - GEN_INT (- INTVAL (operands[3]))); - else - operands[7] = gen_rtx_MINUS (DImode, operands[2], operands[3]); - - operands[8] = gen_rtx_fmt_ee (code, VOIDmode, operands[6], const0_rtx); - } - - else if (code == EQ || code == LE || code == LT - || code == LEU || code == LTU) - { - operands[7] = gen_rtx_fmt_ee (code, DImode, operands[2], operands[3]); - operands[8] = gen_rtx_NE (VOIDmode, operands[6], const0_rtx); - } - else - { - operands[7] = gen_rtx_fmt_ee (reverse_condition (code), DImode, - operands[2], operands[3]); - operands[8] = gen_rtx_EQ (VOIDmode, operands[6], const0_rtx); - } -}") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI - (match_operator 1 "comparison_operator" - [(match_operand:SI 2 "reg_or_0_operand" "") - (match_operand:SI 3 "reg_or_cint_operand" "")]) - (match_operand:DI 4 "reg_or_8bit_operand" "") - (match_operand:DI 5 "reg_or_8bit_operand" ""))) - (clobber (match_operand:DI 6 "register_operand" ""))] - "operands[3] != const0_rtx - && (GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)" - [(set (match_dup 6) (match_dup 7)) - (set (match_dup 0) - (if_then_else:DI (match_dup 8) (match_dup 4) (match_dup 5)))] - " -{ enum rtx_code code = GET_CODE (operands[1]); - int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU); - rtx tem; - - if ((code != NE && code != EQ - && ! (extended_count (operands[2], DImode, unsignedp) >= 1 - && extended_count (operands[3], DImode, unsignedp) >= 1))) - FAIL; - - if (GET_CODE (operands[3]) == CONST_INT) - tem = gen_rtx_PLUS (SImode, operands[2], - GEN_INT (- INTVAL (operands[3]))); - else - tem = gen_rtx_MINUS (SImode, operands[2], operands[3]); - - operands[7] = gen_rtx_SIGN_EXTEND (DImode, tem); - operands[8] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, - operands[6], const0_rtx); -}") - -(define_split - [(set (pc) - (if_then_else - (match_operator 1 "comparison_operator" - [(match_operand:DI 2 "reg_or_0_operand" "") - (match_operand:DI 3 "reg_or_cint_operand" "")]) - (label_ref (match_operand 0 "" "")) - (pc))) - (clobber (match_operand:DI 4 "register_operand" ""))] - "operands[3] != const0_rtx" - [(set (match_dup 4) (match_dup 5)) - (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 0)) (pc)))] - " -{ enum rtx_code code = GET_CODE (operands[1]); - int unsignedp = (code == GEU || code == LEU || code == GTU || code == LTU); - - if (code == NE || code == EQ - || (extended_count (operands[2], DImode, unsignedp) >= 1 - && extended_count (operands[3], DImode, unsignedp) >= 1)) - { - if (GET_CODE (operands[3]) == CONST_INT) - operands[5] = gen_rtx_PLUS (DImode, operands[2], - GEN_INT (- INTVAL (operands[3]))); - else - operands[5] = gen_rtx_MINUS (DImode, operands[2], operands[3]); - - operands[6] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx); - } - - else if (code == EQ || code == LE || code == LT - || code == LEU || code == LTU) - { - operands[5] = gen_rtx_fmt_ee (code, DImode, operands[2], operands[3]); - operands[6] = gen_rtx_NE (VOIDmode, operands[4], const0_rtx); - } - else - { - operands[5] = gen_rtx_fmt_ee (reverse_condition (code), DImode, - operands[2], operands[3]); - operands[6] = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx); - } -}") - -(define_split - [(set (pc) - (if_then_else - (match_operator 1 "comparison_operator" - [(match_operand:SI 2 "reg_or_0_operand" "") - (match_operand:SI 3 "const_int_operand" "")]) - (label_ref (match_operand 0 "" "")) - (pc))) - (clobber (match_operand:DI 4 "register_operand" ""))] - "operands[3] != const0_rtx - && (GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)" - [(set (match_dup 4) (match_dup 5)) - (set (pc) (if_then_else (match_dup 6) (label_ref (match_dup 0)) (pc)))] - " -{ rtx tem; - - if (GET_CODE (operands[3]) == CONST_INT) - tem = gen_rtx_PLUS (SImode, operands[2], - GEN_INT (- INTVAL (operands[3]))); - else - tem = gen_rtx_MINUS (SImode, operands[2], operands[3]); - - operands[5] = gen_rtx_SIGN_EXTEND (DImode, tem); - operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, - operands[4], const0_rtx); -}") - -;; We can convert such things as "a > 0xffff" to "t = a & ~ 0xffff; t != 0". -;; This eliminates one, and sometimes two, insns when the AND can be done -;; with a ZAP. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (match_operator 1 "comparison_operator" - [(match_operand:DI 2 "register_operand" "") - (match_operand:DI 3 "const_int_operand" "")])) - (clobber (match_operand:DI 4 "register_operand" ""))] - "exact_log2 (INTVAL (operands[3]) + 1) >= 0 - && (GET_CODE (operands[1]) == GTU - || GET_CODE (operands[1]) == LEU - || ((GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == LE) - && extended_count (operands[2], DImode, 1) > 0))" - [(set (match_dup 4) (and:DI (match_dup 2) (match_dup 5))) - (set (match_dup 0) (match_dup 6))] - " -{ - operands[5] = GEN_INT (~ INTVAL (operands[3])); - operands[6] = gen_rtx_fmt_ee (((GET_CODE (operands[1]) == GTU - || GET_CODE (operands[1]) == GT) - ? NE : EQ), - DImode, operands[4], const0_rtx); -}") - -;; Here are the CALL and unconditional branch insns. Calls on NT and OSF -;; work differently, so we have different patterns for each. - -(define_expand "call" - [(use (match_operand:DI 0 "" "")) - (use (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" ""))] - "" - " -{ if (TARGET_WINDOWS_NT) - emit_call_insn (gen_call_nt (operands[0], operands[1])); - else if (TARGET_OPEN_VMS) - emit_call_insn (gen_call_vms (operands[0], operands[2])); - else - emit_call_insn (gen_call_osf (operands[0], operands[1])); - - DONE; -}") - -(define_expand "call_osf" - [(parallel [(call (mem:DI (match_operand 0 "" "")) - (match_operand 1 "" "")) - (clobber (reg:DI 27)) - (clobber (reg:DI 26))])] - "" - " -{ if (GET_CODE (operands[0]) != MEM) - abort (); - - operands[0] = XEXP (operands[0], 0); - - if (GET_CODE (operands[0]) != SYMBOL_REF - && ! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 27)) - { - rtx tem = gen_rtx_REG (DImode, 27); - emit_move_insn (tem, operands[0]); - operands[0] = tem; - } -}") - -(define_expand "call_nt" - [(parallel [(call (mem:DI (match_operand 0 "" "")) - (match_operand 1 "" "")) - (clobber (reg:DI 26))])] - "" - " -{ if (GET_CODE (operands[0]) != MEM) - abort (); - - operands[0] = XEXP (operands[0], 0); - if (GET_CODE (operands[0]) != SYMBOL_REF && GET_CODE (operands[0]) != REG) - operands[0] = force_reg (DImode, operands[0]); -}") - -;; -;; call openvms/alpha -;; op 0: symbol ref for called function -;; op 1: next_arg_reg (argument information value for R25) -;; -(define_expand "call_vms" - [(parallel [(call (mem:DI (match_operand 0 "" "")) - (match_operand 1 "" "")) - (use (match_dup 2)) - (use (reg:DI 25)) - (use (reg:DI 26)) - (clobber (reg:DI 27))])] - "" - " -{ if (GET_CODE (operands[0]) != MEM) - abort (); - - operands[0] = XEXP (operands[0], 0); - - /* Always load AI with argument information, then handle symbolic and - indirect call differently. Load RA and set operands[2] to PV in - both cases. */ - - emit_move_insn (gen_rtx_REG (DImode, 25), operands[1]); - if (GET_CODE (operands[0]) == SYMBOL_REF) - { - extern char *savealloc (); - char *linksym, *symbol = XSTR (operands[0], 0); - rtx linkage; - - if (*symbol == '*') - symbol++; - linksym = savealloc (strlen (symbol) + 6); - - alpha_need_linkage (symbol, 0); - - linksym[0] = '$'; - strcpy (linksym+1, symbol); - strcat (linksym, \"..lk\"); - linkage = gen_rtx_SYMBOL_REF (Pmode, linksym); - - emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage)); - - operands[2] - = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8))); - } - else - { - emit_move_insn (gen_rtx_REG (Pmode, 26), - gen_rtx_MEM (Pmode, plus_constant (operands[0], 8))); - - operands[2] = operands[0]; - } - -}") - -(define_expand "call_value" - [(use (match_operand 0 "" "")) - (use (match_operand:DI 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" "")) - (use (match_operand 4 "" ""))] - "" - " -{ if (TARGET_WINDOWS_NT) - emit_call_insn (gen_call_value_nt (operands[0], operands[1], operands[2])); - else if (TARGET_OPEN_VMS) - emit_call_insn (gen_call_value_vms (operands[0], operands[1], - operands[3])); - else - emit_call_insn (gen_call_value_osf (operands[0], operands[1], - operands[2])); - DONE; -}") - -(define_expand "call_value_osf" - [(parallel [(set (match_operand 0 "" "") - (call (mem:DI (match_operand 1 "" "")) - (match_operand 2 "" ""))) - (clobber (reg:DI 27)) - (clobber (reg:DI 26))])] - "" - " -{ if (GET_CODE (operands[1]) != MEM) - abort (); - - operands[1] = XEXP (operands[1], 0); - - if (GET_CODE (operands[1]) != SYMBOL_REF - && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27)) - { - rtx tem = gen_rtx_REG (DImode, 27); - emit_move_insn (tem, operands[1]); - operands[1] = tem; - } -}") - -(define_expand "call_value_nt" - [(parallel [(set (match_operand 0 "" "") - (call (mem:DI (match_operand 1 "" "")) - (match_operand 2 "" ""))) - (clobber (reg:DI 26))])] - "" - " -{ if (GET_CODE (operands[1]) != MEM) - abort (); - - operands[1] = XEXP (operands[1], 0); - if (GET_CODE (operands[0]) != SYMBOL_REF && GET_CODE (operands[0]) != REG) - operands[1] = force_reg (DImode, operands[1]); -}") - -(define_expand "call_value_vms" - [(parallel [(set (match_operand 0 "" "") - (call (mem:DI (match_operand:DI 1 "" "")) - (match_operand 2 "" ""))) - (use (match_dup 3)) - (use (reg:DI 25)) - (use (reg:DI 26)) - (clobber (reg:DI 27))])] - "" - " -{ if (GET_CODE (operands[1]) != MEM) - abort (); - - operands[1] = XEXP (operands[1], 0); - - /* Always load AI with argument information, then handle symbolic and - indirect call differently. Load RA and set operands[3] to PV in - both cases. */ - - emit_move_insn (gen_rtx_REG (DImode, 25), operands[2]); - if (GET_CODE (operands[1]) == SYMBOL_REF) - { - extern char *savealloc (); - char *linksym, *symbol = XSTR (operands[1], 0); - rtx linkage; - - if (*symbol == '*') - symbol++; - linksym = savealloc (strlen (symbol) + 6); - - alpha_need_linkage (symbol, 0); - linksym[0] = '$'; - strcpy (linksym+1, symbol); - strcat (linksym, \"..lk\"); - linkage = gen_rtx_SYMBOL_REF (Pmode, linksym); - - emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage)); - - operands[3] - = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8))); - } - else - { - emit_move_insn (gen_rtx_REG (Pmode, 26), - gen_rtx_MEM (Pmode, plus_constant (operands[1], 8))); - - operands[3] = operands[1]; - } -}") - -(define_insn "" - [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i")) - (match_operand 1 "" "")) - (clobber (reg:DI 27)) - (clobber (reg:DI 26))] - "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS" - "@ - jsr $26,($27),0\;ldgp $29,0($26) - bsr $26,$%0..ng - jsr $26,%0\;ldgp $29,0($26)" - [(set_attr "type" "jsr") - (set_attr "length" "12,*,16")]) - -(define_insn "" - [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i")) - (match_operand 1 "" "")) - (clobber (reg:DI 26))] - "TARGET_WINDOWS_NT" - "@ - jsr $26,(%0) - bsr $26,%0 - jsr $26,%0" - [(set_attr "type" "jsr") - (set_attr "length" "*,*,12")]) - -(define_insn "" - [(call (mem:DI (match_operand:DI 0 "call_operand" "r,i")) - (match_operand 1 "" "")) - (use (match_operand:DI 2 "general_operand" "r,m")) - (use (reg:DI 25)) - (use (reg:DI 26)) - (clobber (reg:DI 27))] - "TARGET_OPEN_VMS" - "@ - bis %2,%2,$27\;jsr $26,0\;ldq $27,0($29) - ldq $27,%2\;jsr $26,%0\;ldq $27,0($29)" - [(set_attr "type" "jsr") - (set_attr "length" "12,16")]) - -(define_insn "" - [(set (match_operand 0 "register_operand" "=rf,rf,rf") - (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i")) - (match_operand 2 "" ""))) - (clobber (reg:DI 27)) - (clobber (reg:DI 26))] - "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS" - "@ - jsr $26,($27),0\;ldgp $29,0($26) - bsr $26,$%1..ng - jsr $26,%1\;ldgp $29,0($26)" - [(set_attr "type" "jsr") - (set_attr "length" "12,*,16")]) - -(define_insn "" - [(set (match_operand 0 "register_operand" "=rf,rf,rf") - (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i")) - (match_operand 2 "" ""))) - (clobber (reg:DI 26))] - "TARGET_WINDOWS_NT" - "@ - jsr $26,(%1) - bsr $26,%1 - jsr $26,%1" - [(set_attr "type" "jsr") - (set_attr "length" "*,*,12")]) - -(define_insn "" - [(set (match_operand 0 "register_operand" "") - (call (mem:DI (match_operand:DI 1 "call_operand" "r,i")) - (match_operand 2 "" ""))) - (use (match_operand:DI 3 "general_operand" "r,m")) - (use (reg:DI 25)) - (use (reg:DI 26)) - (clobber (reg:DI 27))] - "TARGET_OPEN_VMS" - "@ - bis %3,%3,$27\;jsr $26,0\;ldq $27,0($29) - ldq $27,%3\;jsr $26,%1\;ldq $27,0($29)" - [(set_attr "type" "jsr") - (set_attr "length" "12,16")]) - -;; 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)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 1)] - "" - "" - [(set_attr "length" "0")]) - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "br $31,%l0" - [(set_attr "type" "ibr")]) - -(define_insn "return" - [(return)] - "direct_return ()" - "ret $31,($26),1" - [(set_attr "type" "ibr")]) - -;; Use a different pattern for functions which have non-trivial -;; epilogues so as not to confuse jump and reorg. -(define_insn "return_internal" - [(use (reg:DI 26)) - (return)] - "" - "ret $31,($26),1" - [(set_attr "type" "ibr")]) - -(define_insn "indirect_jump" - [(set (pc) (match_operand:DI 0 "register_operand" "r"))] - "" - "jmp $31,(%0),0" - [(set_attr "type" "ibr")]) - -(define_expand "tablejump" - [(use (match_operand:SI 0 "register_operand" "")) - (use (match_operand:SI 1 "" ""))] - "" - " -{ - if (TARGET_WINDOWS_NT) - emit_jump_insn (gen_tablejump_nt (operands[0], operands[1])); - else if (TARGET_OPEN_VMS) - emit_jump_insn (gen_tablejump_vms (operands[0], operands[1])); - else - emit_jump_insn (gen_tablejump_osf (operands[0], operands[1])); - - DONE; -}") - -(define_expand "tablejump_osf" - [(set (match_dup 3) - (sign_extend:DI (match_operand:SI 0 "register_operand" ""))) - (parallel [(set (pc) - (plus:DI (match_dup 3) - (label_ref:DI (match_operand 1 "" "")))) - (clobber (match_scratch:DI 2 "=r"))])] - "" - " -{ operands[3] = gen_reg_rtx (DImode); }") - -(define_expand "tablejump_nt" - [(set (match_dup 3) - (sign_extend:DI (match_operand:SI 0 "register_operand" ""))) - (parallel [(set (pc) - (match_dup 3)) - (use (label_ref (match_operand 1 "" "")))])] - "" - " -{ operands[3] = gen_reg_rtx (DImode); }") - -;; -;; tablejump, openVMS way -;; op 0: offset -;; op 1: label preceding jump-table -;; -(define_expand "tablejump_vms" - [(set (match_dup 2) - (match_operand:DI 0 "register_operand" "")) - (set (pc) - (plus:DI (match_dup 2) - (label_ref:DI (match_operand 1 "" ""))))] - "" - " -{ operands[2] = gen_reg_rtx (DImode); }") - -(define_insn "" - [(set (pc) - (plus:DI (match_operand:DI 0 "register_operand" "r") - (label_ref:DI (match_operand 1 "" "")))) - (clobber (match_scratch:DI 2 "=r"))] - "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && next_active_insn (insn) != 0 - && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC - && PREV_INSN (next_active_insn (insn)) == operands[1]" - "* -{ rtx best_label = 0; - rtx jump_table_insn = next_active_insn (operands[1]); - - if (GET_CODE (jump_table_insn) == JUMP_INSN - && GET_CODE (PATTERN (jump_table_insn)) == ADDR_DIFF_VEC) - { - rtx jump_table = PATTERN (jump_table_insn); - int n_labels = XVECLEN (jump_table, 1); - int best_count = -1; - int i, j; - - for (i = 0; i < n_labels; i++) - { - int count = 1; - - for (j = i + 1; j < n_labels; j++) - if (XEXP (XVECEXP (jump_table, 1, i), 0) - == XEXP (XVECEXP (jump_table, 1, j), 0)) - count++; - - if (count > best_count) - best_count = count, best_label = XVECEXP (jump_table, 1, i); - } - } - - if (best_label) - { - operands[3] = best_label; - return \"addq %0,$29,%2\;jmp $31,(%2),%3\"; - } - else - return \"addq %0,$29,%2\;jmp $31,(%2),0\"; -}" - [(set_attr "type" "ibr") - (set_attr "length" "8")]) - -(define_insn "" - [(set (pc) - (match_operand:DI 0 "register_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "TARGET_WINDOWS_NT && next_active_insn (insn) != 0 - && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC - && PREV_INSN (next_active_insn (insn)) == operands[1]" - "* -{ rtx best_label = 0; - rtx jump_table_insn = next_active_insn (operands[1]); - - if (GET_CODE (jump_table_insn) == JUMP_INSN - && GET_CODE (PATTERN (jump_table_insn)) == ADDR_DIFF_VEC) - { - rtx jump_table = PATTERN (jump_table_insn); - int n_labels = XVECLEN (jump_table, 1); - int best_count = -1; - int i, j; - - for (i = 0; i < n_labels; i++) - { - int count = 1; - - for (j = i + 1; j < n_labels; j++) - if (XEXP (XVECEXP (jump_table, 1, i), 0) - == XEXP (XVECEXP (jump_table, 1, j), 0)) - count++; - - if (count > best_count) - best_count = count, best_label = XVECEXP (jump_table, 1, i); - } - } - - if (best_label) - { - operands[2] = best_label; - return \"jmp $31,(%0),%2\"; - } - else - return \"jmp $31,(%0),0\"; -}" - [(set_attr "type" "ibr")]) - -;; -;; op 0 is table offset -;; op 1 is table label -;; - -(define_insn "" - [(set (pc) - (plus:DI (match_operand 0 "register_operand" "r") - (label_ref (match_operand 1 "" ""))))] - "TARGET_OPEN_VMS" - "jmp $31,(%0),0" - [(set_attr "type" "ibr")]) - -;; Cache flush. Used by INITIALIZE_TRAMPOLINE. 0x86 is PAL_imb, but we don't -;; want to have to include pal.h in our .s file. -;; -;; Technically the type for call_pal is jsr, but we use that for determining -;; if we need a GP. Use ibr instead since it has the same EV5 scheduling -;; characteristics. -(define_insn "imb" - [(unspec_volatile [(const_int 0)] 0)] - "" - "call_pal 0x86" - [(set_attr "type" "ibr")]) - -;; Finally, we have the basic data motion insns. The byte and word insns -;; are done via define_expand. Start with the floating-point insns, since -;; they are simpler. - -(define_insn "" - [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m") - (match_operand:SF 1 "input_operand" "rG,m,rG,f,G,m,fG"))] - "! TARGET_CIX - && (register_operand (operands[0], SFmode) - || reg_or_fp0_operand (operands[1], SFmode))" - "@ - bis %r1,%r1,%0 - ldl %0,%1 - stl %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0 - ld%, %0,%1 - st%, %R1,%0" - [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst")]) - -(define_insn "" - [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m,f,*r") - (match_operand:SF 1 "input_operand" "rG,m,rG,f,G,m,fG,r,*f"))] - "TARGET_CIX - && (register_operand (operands[0], SFmode) - || reg_or_fp0_operand (operands[1], SFmode))" - "@ - bis %r1,%r1,%0 - ldl %0,%1 - stl %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0 - ld%, %0,%1 - st%, %R1,%0 - itofs %1,%0 - ftois %1,%0" - [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst,itof,ftoi")]) - -(define_insn "" - [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m") - (match_operand:DF 1 "input_operand" "rG,m,rG,f,G,m,fG"))] - "! TARGET_CIX - && (register_operand (operands[0], DFmode) - || reg_or_fp0_operand (operands[1], DFmode))" - "@ - bis %r1,%r1,%0 - ldq %0,%1 - stq %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0 - ld%- %0,%1 - st%- %R1,%0" - [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst")]) - -(define_insn "" - [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m,f,*r") - (match_operand:DF 1 "input_operand" "rG,m,rG,f,G,m,fG,r,*f"))] - "TARGET_CIX - && (register_operand (operands[0], DFmode) - || reg_or_fp0_operand (operands[1], DFmode))" - "@ - bis %r1,%r1,%0 - ldq %0,%1 - stq %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0 - ld%- %0,%1 - st%- %R1,%0 - itoft %1,%0 - ftoit %1,%0" - [(set_attr "type" "ilog,ild,ist,fcpys,fcpys,fld,fst,itof,ftoi")]) - -(define_expand "movsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! reg_or_fp0_operand (operands[1], SFmode)) - operands[1] = force_reg (SFmode, operands[1]); -}") - -(define_expand "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! reg_or_fp0_operand (operands[1], DFmode)) - operands[1] = force_reg (DFmode, operands[1]); -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,f,f,f,m") - (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,f,J,m,fG"))] - "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && ! TARGET_CIX - && (register_operand (operands[0], SImode) - || reg_or_0_operand (operands[1], SImode))" - "@ - bis %1,%1,%0 - bis $31,$31,%0 - bis $31,%1,%0 - lda %0,%1 - ldah %0,%h1 - ldl %0,%1 - stl %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0 - ld%, %0,%1 - st%, %R1,%0" - [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ild,ist,fcpys,fcpys,fld,fst")]) - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,f,f,f,m,r,*f") - (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,f,J,m,fG,f,*r"))] - "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && TARGET_CIX - && (register_operand (operands[0], SImode) - || reg_or_0_operand (operands[1], SImode))" - "@ - bis %1,%1,%0 - bis $31,$31,%0 - bis $31,%1,%0 - lda %0,%1 - ldah %0,%h1 - ldl %0,%1 - stl %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0 - ld%, %0,%1 - st%, %R1,%0 - ftois %1,%0 - itofs %1,%0" - [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ild,ist,fcpys,fcpys,fld,fst,ftoi,itof")]) - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,r,m,f,f,f,m") - (match_operand:SI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,m,fG"))] - "(TARGET_WINDOWS_NT || TARGET_OPEN_VMS) - && (register_operand (operands[0], SImode) - || reg_or_0_operand (operands[1], SImode))" - "@ - bis %1,%1,%0 - bis $31,$31,%0 - bis $31,%1,%0 - lda %0,%1 - ldah %0,%h1 - lda %0,%1 - ldl %0,%1 - stl %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0 - ld%, %0,%1 - st%, %R1,%0" - [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,fcpys,fld,fst")]) - -(define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,f,f") - (match_operand:HI 1 "input_operand" "r,J,I,n,f,J"))] - "! TARGET_BWX - && (register_operand (operands[0], HImode) - || register_operand (operands[1], HImode))" - "@ - bis %1,%1,%0 - bis $31,$31,%0 - bis $31,%1,%0 - lda %0,%L1 - cpys %1,%1,%0 - cpys $f31,$f31,%0" - [(set_attr "type" "ilog,ilog,ilog,iadd,fcpys,fcpys")]) - -(define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f") - (match_operand:HI 1 "input_operand" "r,J,I,n,m,rJ,f,J"))] - "TARGET_BWX - && (register_operand (operands[0], HImode) - || reg_or_0_operand (operands[1], HImode))" - "@ - bis %1,%1,%0 - bis $31,$31,%0 - bis $31,%1,%0 - lda %0,%L1 - ldwu %0,%1 - stw %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0" - [(set_attr "type" "ilog,ilog,ilog,iadd,ild,ist,fcpys,fcpys")]) - -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,r,f,f") - (match_operand:QI 1 "input_operand" "r,J,I,n,f,J"))] - "! TARGET_BWX - && (register_operand (operands[0], QImode) - || register_operand (operands[1], QImode))" - "@ - bis %1,%1,%0 - bis $31,$31,%0 - bis $31,%1,%0 - lda %0,%L1 - cpys %1,%1,%0 - cpys $f31,$f31,%0" - [(set_attr "type" "ilog,ilog,ilog,iadd,fcpys,fcpys")]) - -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,r,r,m,f,f") - (match_operand:QI 1 "input_operand" "r,J,I,n,m,rJ,f,J"))] - "TARGET_BWX - && (register_operand (operands[0], QImode) - || reg_or_0_operand (operands[1], QImode))" - "@ - bis %1,%1,%0 - bis $31,$31,%0 - bis $31,%1,%0 - lda %0,%L1 - ldbu %0,%1 - stb %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0" - [(set_attr "type" "ilog,ilog,ilog,iadd,ild,ist,fcpys,fcpys")]) - -;; We do two major things here: handle mem->mem and construct long -;; constants. - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! reg_or_0_operand (operands[1], SImode)) - operands[1] = force_reg (SImode, operands[1]); - - if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode)) - ; - else if (GET_CODE (operands[1]) == CONST_INT) - { - operands[1] - = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 3); - if (rtx_equal_p (operands[0], operands[1])) - DONE; - } -}") - -;; Split a load of a large constant into the appropriate two-insn -;; sequence. - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" ""))] - "! add_operand (operands[1], SImode)" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] - " -{ rtx tem - = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 2); - - if (tem == operands[0]) - DONE; - else - FAIL; -}") - -(define_insn "" - [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,r,r,m,f,f,f,Q") - (match_operand:DI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,Q,fG"))] - "! TARGET_CIX - && (register_operand (operands[0], DImode) - || reg_or_0_operand (operands[1], DImode))" - "@ - bis %1,%1,%0 - bis $31,$31,%0 - bis $31,%1,%0 - lda %0,%1 - ldah %0,%h1 - lda %0,%1 - ldq%A1 %0,%1 - stq%A0 %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0 - ldt %0,%1 - stt %R1,%0" - [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,fcpys,fld,fst")]) - -(define_insn "" - [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,r,r,m,f,f,f,Q,r,*f") - (match_operand:DI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,Q,fG,f,*r"))] - "TARGET_CIX - && (register_operand (operands[0], DImode) - || reg_or_0_operand (operands[1], DImode))" - "@ - bis %1,%1,%0 - bis $31,$31,%0 - bis $31,%1,%0 - lda %0,%1 - ldah %0,%h1 - lda %0,%1 - ldq%A1 %0,%1 - stq%A0 %r1,%0 - cpys %1,%1,%0 - cpys $f31,$f31,%0 - ldt %0,%1 - stt %R1,%0 - ftoit %1,%0 - itoft %1,%0" - [(set_attr "type" "ilog,ilog,ilog,iadd,iadd,ldsym,ild,ist,fcpys,fcpys,fld,fst,ftoi,itof")]) - -;; We do three major things here: handle mem->mem, put 64-bit constants in -;; memory, and construct long 32-bit constants. - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - rtx tem; - - if (GET_CODE (operands[0]) == MEM - && ! reg_or_0_operand (operands[1], DImode)) - operands[1] = force_reg (DImode, operands[1]); - - if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode)) - ; - else if (GET_CODE (operands[1]) == CONST_INT - && (tem = alpha_emit_set_const (operands[0], DImode, - INTVAL (operands[1]), 3)) != 0) - { - if (rtx_equal_p (tem, operands[0])) - DONE; - else - operands[1] = tem; - } - else if (CONSTANT_P (operands[1])) - { - if (TARGET_BUILD_CONSTANTS) - { - HOST_WIDE_INT i0, i1; - - if (GET_CODE (operands[1]) == CONST_INT) - { - i0 = INTVAL (operands[1]); - i1 = -(i0 < 0); - } - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - { -#if HOST_BITS_PER_WIDE_INT >= 64 - i0 = CONST_DOUBLE_LOW (operands[1]); - i1 = -(i0 < 0); -#else - i0 = CONST_DOUBLE_LOW (operands[1]); - i1 = CONST_DOUBLE_HIGH (operands[1]); -#endif - } - else - abort(); - - tem = alpha_emit_set_long_const (operands[0], i0, i1); - if (rtx_equal_p (tem, operands[0])) - DONE; - else - operands[1] = tem; - } - else - { - operands[1] = force_const_mem (DImode, operands[1]); - if (reload_in_progress) - { - emit_move_insn (operands[0], XEXP (operands[1], 0)); - operands[1] = copy_rtx (operands[1]); - XEXP (operands[1], 0) = operands[0]; - } - else - operands[1] = validize_mem (operands[1]); - } - } - else - abort (); -}") - -;; Split a load of a large constant into the appropriate two-insn -;; sequence. - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "const_int_operand" ""))] - "! add_operand (operands[1], DImode)" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] - " -{ rtx tem - = alpha_emit_set_const (operands[0], DImode, INTVAL (operands[1]), 2); - - if (tem == operands[0]) - DONE; - else - FAIL; -}") - -;; These are the partial-word cases. -;; -;; First we have the code to load an aligned word. Operand 0 is the register -;; in which to place the result. It's mode is QImode or HImode. Operand 1 -;; is an SImode MEM at the low-order byte of the proper word. Operand 2 is the -;; number of bits within the word that the value is. Operand 3 is an SImode -;; scratch register. If operand 0 is a hard register, operand 3 may be the -;; same register. It is allowed to conflict with operand 1 as well. - -(define_expand "aligned_loadqi" - [(set (match_operand:SI 3 "register_operand" "") - (match_operand:SI 1 "memory_operand" "")) - (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) - (zero_extract:DI (subreg:DI (match_dup 3) 0) - (const_int 8) - (match_operand:DI 2 "const_int_operand" "")))] - - "" - "") - -(define_expand "aligned_loadhi" - [(set (match_operand:SI 3 "register_operand" "") - (match_operand:SI 1 "memory_operand" "")) - (set (subreg:DI (match_operand:HI 0 "register_operand" "") 0) - (zero_extract:DI (subreg:DI (match_dup 3) 0) - (const_int 16) - (match_operand:DI 2 "const_int_operand" "")))] - - "" - "") - -;; Similar for unaligned loads, where we use the sequence from the -;; Alpha Architecture manual. -;; -;; Operand 1 is the address. Operands 2 and 3 are temporaries, where -;; operand 3 can overlap the input and output registers. - -(define_expand "unaligned_loadqi" - [(set (match_operand:DI 2 "register_operand" "") - (mem:DI (and:DI (match_operand:DI 1 "address_operand" "") - (const_int -8)))) - (set (match_operand:DI 3 "register_operand" "") - (match_dup 1)) - (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) - (zero_extract:DI (match_dup 2) - (const_int 8) - (ashift:DI (match_dup 3) (const_int 3))))] - "" - "") - -(define_expand "unaligned_loadhi" - [(set (match_operand:DI 2 "register_operand" "") - (mem:DI (and:DI (match_operand:DI 1 "address_operand" "") - (const_int -8)))) - (set (match_operand:DI 3 "register_operand" "") - (match_dup 1)) - (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0) - (zero_extract:DI (match_dup 2) - (const_int 16) - (ashift:DI (match_dup 3) (const_int 3))))] - "" - "") - -;; Storing an aligned byte or word requires two temporaries. Operand 0 is the -;; aligned SImode MEM. Operand 1 is the register containing the -;; byte or word to store. Operand 2 is the number of bits within the word that -;; the value should be placed. Operands 3 and 4 are SImode temporaries. - -(define_expand "aligned_store" - [(set (match_operand:SI 3 "register_operand" "") - (match_operand:SI 0 "memory_operand" "")) - (set (subreg:DI (match_dup 3) 0) - (and:DI (subreg:DI (match_dup 3) 0) (match_dup 5))) - (set (subreg:DI (match_operand:SI 4 "register_operand" "") 0) - (ashift:DI (zero_extend:DI (match_operand 1 "register_operand" "")) - (match_operand:DI 2 "const_int_operand" ""))) - (set (subreg:DI (match_dup 4) 0) - (ior:DI (subreg:DI (match_dup 4) 0) (subreg:DI (match_dup 3) 0))) - (set (match_dup 0) (match_dup 4))] - "" - " -{ operands[5] = GEN_INT (~ (GET_MODE_MASK (GET_MODE (operands[1])) - << INTVAL (operands[2]))); -}") - -;; For the unaligned byte and halfword cases, we use code similar to that -;; in the ;; Architecture book, but reordered to lower the number of registers -;; required. Operand 0 is the address. Operand 1 is the data to store. -;; Operands 2, 3, and 4 are DImode temporaries, where operands 2 and 4 may -;; be the same temporary, if desired. If the address is in a register, -;; operand 2 can be that register. - -(define_expand "unaligned_storeqi" - [(set (match_operand:DI 3 "register_operand" "") - (mem:DI (and:DI (match_operand:DI 0 "address_operand" "") - (const_int -8)))) - (set (match_operand:DI 2 "register_operand" "") - (match_dup 0)) - (set (match_dup 3) - (and:DI (not:DI (ashift:DI (const_int 255) - (ashift:DI (match_dup 2) (const_int 3)))) - (match_dup 3))) - (set (match_operand:DI 4 "register_operand" "") - (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "")) - (ashift:DI (match_dup 2) (const_int 3)))) - (set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3))) - (set (mem:DI (and:DI (match_dup 0) (const_int -8))) - (match_dup 4))] - "" - "") - -(define_expand "unaligned_storehi" - [(set (match_operand:DI 3 "register_operand" "") - (mem:DI (and:DI (match_operand:DI 0 "address_operand" "") - (const_int -8)))) - (set (match_operand:DI 2 "register_operand" "") - (match_dup 0)) - (set (match_dup 3) - (and:DI (not:DI (ashift:DI (const_int 65535) - (ashift:DI (match_dup 2) (const_int 3)))) - (match_dup 3))) - (set (match_operand:DI 4 "register_operand" "") - (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "")) - (ashift:DI (match_dup 2) (const_int 3)))) - (set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3))) - (set (mem:DI (and:DI (match_dup 0) (const_int -8))) - (match_dup 4))] - "" - "") - -;; Here are the define_expand's for QI and HI moves that use the above -;; patterns. We have the normal sets, plus the ones that need scratch -;; registers for reload. - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (TARGET_BWX) - { - if (GET_CODE (operands[0]) == MEM - && ! reg_or_0_operand (operands[1], QImode)) - operands[1] = force_reg (QImode, operands[1]); - - if (GET_CODE (operands[1]) == CONST_INT - && ! input_operand (operands[1], QImode)) - { - operands[1] = alpha_emit_set_const (operands[0], QImode, - INTVAL (operands[1]), 3); - - if (rtx_equal_p (operands[0], operands[1])) - DONE; - } - - goto def; - } - - /* If the output is not a register, the input must be. */ - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (QImode, operands[1]); - - /* Handle four memory cases, unaligned and aligned for either the input - or the output. The only case where we can be called during reload is - for aligned loads; all other cases require temporaries. */ - - if (GET_CODE (operands[1]) == MEM - || (GET_CODE (operands[1]) == SUBREG - && GET_CODE (SUBREG_REG (operands[1])) == MEM) - || (reload_in_progress && GET_CODE (operands[1]) == REG - && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) - || (reload_in_progress && GET_CODE (operands[1]) == SUBREG - && GET_CODE (SUBREG_REG (operands[1])) == REG - && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER)) - { - if (aligned_memory_operand (operands[1], QImode)) - { - rtx aligned_mem, bitnum; - rtx scratch = (reload_in_progress - ? gen_rtx_REG (SImode, REGNO (operands[0])) - : gen_reg_rtx (SImode)); - - get_aligned_mem (operands[1], &aligned_mem, &bitnum); - - emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum, - scratch)); - } - else - { - /* Don't pass these as parameters since that makes the generated - code depend on parameter evaluation order which will cause - bootstrap failures. */ - - rtx temp1 = gen_reg_rtx (DImode); - rtx temp2 = gen_reg_rtx (DImode); - rtx seq - = gen_unaligned_loadqi (operands[0], - get_unaligned_address (operands[1], 0), - temp1, temp2); - - alpha_set_memflags (seq, operands[1]); - emit_insn (seq); - } - - DONE; - } - - else if (GET_CODE (operands[0]) == MEM - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == MEM) - || (reload_in_progress && GET_CODE (operands[0]) == REG - && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) - || (reload_in_progress && GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)) - { - if (aligned_memory_operand (operands[0], QImode)) - { - rtx aligned_mem, bitnum; - rtx temp1 = gen_reg_rtx (SImode); - rtx temp2 = gen_reg_rtx (SImode); - - get_aligned_mem (operands[0], &aligned_mem, &bitnum); - - emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, - temp1, temp2)); - } - else - { - rtx temp1 = gen_reg_rtx (DImode); - rtx temp2 = gen_reg_rtx (DImode); - rtx temp3 = gen_reg_rtx (DImode); - rtx seq - = gen_unaligned_storeqi (get_unaligned_address (operands[0], 0), - operands[1], temp1, temp2, temp3); - - alpha_set_memflags (seq, operands[0]); - emit_insn (seq); - } - DONE; - } - def:; -}") - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (TARGET_BWX) - { - if (GET_CODE (operands[0]) == MEM - && ! reg_or_0_operand (operands[1], HImode)) - operands[1] = force_reg (HImode, operands[1]); - - if (GET_CODE (operands[1]) == CONST_INT - && ! input_operand (operands[1], HImode)) - { - operands[1] = alpha_emit_set_const (operands[0], HImode, - INTVAL (operands[1]), 3); - - if (rtx_equal_p (operands[0], operands[1])) - DONE; - } - - goto def; - } - - /* If the output is not a register, the input must be. */ - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (HImode, operands[1]); - - /* Handle four memory cases, unaligned and aligned for either the input - or the output. The only case where we can be called during reload is - for aligned loads; all other cases require temporaries. */ - - if (GET_CODE (operands[1]) == MEM - || (GET_CODE (operands[1]) == SUBREG - && GET_CODE (SUBREG_REG (operands[1])) == MEM) - || (reload_in_progress && GET_CODE (operands[1]) == REG - && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) - || (reload_in_progress && GET_CODE (operands[1]) == SUBREG - && GET_CODE (SUBREG_REG (operands[1])) == REG - && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER)) - { - if (aligned_memory_operand (operands[1], HImode)) - { - rtx aligned_mem, bitnum; - rtx scratch = (reload_in_progress - ? gen_rtx_REG (SImode, REGNO (operands[0])) - : gen_reg_rtx (SImode)); - - get_aligned_mem (operands[1], &aligned_mem, &bitnum); - - emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum, - scratch)); - } - else - { - /* Don't pass these as parameters since that makes the generated - code depend on parameter evaluation order which will cause - bootstrap failures. */ - - rtx temp1 = gen_reg_rtx (DImode); - rtx temp2 = gen_reg_rtx (DImode); - rtx seq - = gen_unaligned_loadhi (operands[0], - get_unaligned_address (operands[1], 0), - temp1, temp2); - - alpha_set_memflags (seq, operands[1]); - emit_insn (seq); - } - - DONE; - } - - else if (GET_CODE (operands[0]) == MEM - || (GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == MEM) - || (reload_in_progress && GET_CODE (operands[0]) == REG - && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) - || (reload_in_progress && GET_CODE (operands[0]) == SUBREG - && GET_CODE (SUBREG_REG (operands[0])) == REG - && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)) - { - if (aligned_memory_operand (operands[0], HImode)) - { - rtx aligned_mem, bitnum; - rtx temp1 = gen_reg_rtx (SImode); - rtx temp2 = gen_reg_rtx (SImode); - - get_aligned_mem (operands[0], &aligned_mem, &bitnum); - - emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, - temp1, temp2)); - } - else - { - rtx temp1 = gen_reg_rtx (DImode); - rtx temp2 = gen_reg_rtx (DImode); - rtx temp3 = gen_reg_rtx (DImode); - rtx seq - = gen_unaligned_storehi (get_unaligned_address (operands[0], 0), - operands[1], temp1, temp2, temp3); - - alpha_set_memflags (seq, operands[0]); - emit_insn (seq); - } - - DONE; - } - def:; -}") - -;; Here are the versions for reload. Note that in the unaligned cases -;; we know that the operand must not be a pseudo-register because stack -;; slots are always aligned references. - -(define_expand "reload_inqi" - [(parallel [(match_operand:QI 0 "register_operand" "=r") - (match_operand:QI 1 "unaligned_memory_operand" "m") - (match_operand:TI 2 "register_operand" "=&r")])] - "! TARGET_BWX" - " -{ - rtx addr = get_unaligned_address (operands[1], 0); - - /* It is possible that one of the registers we got for operands[2] - might coincide with that of operands[0] (which is why we made - it TImode). Pick the other one to use as our scratch. */ - rtx scratch = gen_rtx_REG (DImode, - REGNO (operands[0]) == REGNO (operands[2]) - ? REGNO (operands[2]) + 1 : REGNO (operands[2])); - - rtx seq = gen_unaligned_loadqi (operands[0], addr, scratch, - gen_rtx_REG (DImode, REGNO (operands[0]))); - - alpha_set_memflags (seq, operands[1]); - emit_insn (seq); - DONE; -}") - -(define_expand "reload_inhi" - [(parallel [(match_operand:HI 0 "register_operand" "=r") - (match_operand:HI 1 "unaligned_memory_operand" "m") - (match_operand:TI 2 "register_operand" "=&r")])] - "! TARGET_BWX" - " -{ - rtx addr = get_unaligned_address (operands[1], 0); - - /* It is possible that one of the registers we got for operands[2] - might coincide with that of operands[0] (which is why we made - it TImode). Pick the other one to use as our scratch. */ - rtx scratch = gen_rtx_REG (DImode, - REGNO (operands[0]) == REGNO (operands[2]) - ? REGNO (operands[2]) + 1 : REGNO (operands[2])); - - rtx seq = gen_unaligned_loadhi (operands[0], addr, scratch, - gen_rtx_REG (DImode, REGNO (operands[0]))); - - alpha_set_memflags (seq, operands[1]); - emit_insn (seq); - DONE; -}") - -(define_expand "reload_outqi" - [(parallel [(match_operand:QI 0 "any_memory_operand" "=m") - (match_operand:QI 1 "register_operand" "r") - (match_operand:TI 2 "register_operand" "=&r")])] - "! TARGET_BWX" - " -{ - if (aligned_memory_operand (operands[0], QImode)) - { - rtx aligned_mem, bitnum; - - get_aligned_mem (operands[0], &aligned_mem, &bitnum); - - emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, - gen_rtx_REG (SImode, REGNO (operands[2])), - gen_rtx_REG (SImode, - REGNO (operands[2]) + 1))); - } - else - { - rtx addr = get_unaligned_address (operands[0], 0); - rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2])); - rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); - rtx scratch3 = scratch1; - rtx seq; - - if (GET_CODE (addr) == REG) - scratch1 = addr; - - seq = gen_unaligned_storeqi (addr, operands[1], scratch1, - scratch2, scratch3); - alpha_set_memflags (seq, operands[0]); - emit_insn (seq); - } - - DONE; -}") - -(define_expand "reload_outhi" - [(parallel [(match_operand:HI 0 "any_memory_operand" "=m") - (match_operand:HI 1 "register_operand" "r") - (match_operand:TI 2 "register_operand" "=&r")])] - "! TARGET_BWX" - " -{ - if (aligned_memory_operand (operands[0], HImode)) - { - rtx aligned_mem, bitnum; - - get_aligned_mem (operands[0], &aligned_mem, &bitnum); - - emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum, - gen_rtx_REG (SImode, REGNO (operands[2])), - gen_rtx_REG (SImode, - REGNO (operands[2]) + 1))); - } - else - { - rtx addr = get_unaligned_address (operands[0], 0); - rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2])); - rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); - rtx scratch3 = scratch1; - rtx seq; - - if (GET_CODE (addr) == REG) - scratch1 = addr; - - seq = gen_unaligned_storehi (addr, operands[1], scratch1, - scratch2, scratch3); - alpha_set_memflags (seq, operands[0]); - emit_insn (seq); - } - - DONE; -}") - -;; Bit field extract patterns which use ext[wlq][lh] - -(define_expand "extv" - [(set (match_operand:DI 0 "register_operand" "") - (sign_extract:DI (match_operand:QI 1 "memory_operand" "") - (match_operand:DI 2 "immediate_operand" "") - (match_operand:DI 3 "immediate_operand" "")))] - "" - " -{ - /* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */ - if (INTVAL (operands[3]) % 8 != 0 - || (INTVAL (operands[2]) != 16 - && INTVAL (operands[2]) != 32 - && INTVAL (operands[2]) != 64)) - FAIL; - - /* From mips.md: extract_bit_field doesn't verify that our source - matches the predicate, so we force it to be a MEM here. */ - if (GET_CODE (operands[1]) != MEM) - FAIL; - - alpha_expand_unaligned_load (operands[0], operands[1], - INTVAL (operands[2]) / 8, - INTVAL (operands[3]) / 8, 1); - DONE; -}") - -(define_expand "extzv" - [(set (match_operand:DI 0 "register_operand" "") - (zero_extract:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "immediate_operand" "") - (match_operand:DI 3 "immediate_operand" "")))] - "" - " -{ - /* We can do 8, 16, 32 and 64 bit fields, if aligned on byte boundaries. */ - if (INTVAL (operands[3]) % 8 != 0 - || (INTVAL (operands[2]) != 8 - && INTVAL (operands[2]) != 16 - && INTVAL (operands[2]) != 32 - && INTVAL (operands[2]) != 64)) - FAIL; - - if (GET_CODE (operands[1]) == MEM) - { - /* Fail 8 bit fields, falling back on a simple byte load. */ - if (INTVAL (operands[2]) == 8) - FAIL; - - alpha_expand_unaligned_load (operands[0], operands[1], - INTVAL (operands[2]) / 8, - INTVAL (operands[3]) / 8, 0); - DONE; - } -}") - -(define_expand "insv" - [(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "") - (match_operand:DI 1 "immediate_operand" "") - (match_operand:DI 2 "immediate_operand" "")) - (match_operand:DI 3 "register_operand" ""))] - "" - " -{ - /* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */ - if (INTVAL (operands[2]) % 8 != 0 - || (INTVAL (operands[1]) != 16 - && INTVAL (operands[1]) != 32 - && INTVAL (operands[1]) != 64)) - FAIL; - - /* From mips.md: store_bit_field doesn't verify that our source - matches the predicate, so we force it to be a MEM here. */ - if (GET_CODE (operands[0]) != MEM) - FAIL; - - alpha_expand_unaligned_store (operands[0], operands[3], - INTVAL (operands[1]) / 8, - INTVAL (operands[2]) / 8); - DONE; -}") - - - -;; Block move/clear, see alpha.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 "movstrqi" - [(parallel [(set (match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "")) - (use (match_operand:DI 2 "immediate_operand" "")) - (use (match_operand:DI 3 "immediate_operand" ""))])] - "" - " -{ - if (alpha_expand_block_move (operands)) - DONE; - else - FAIL; -}") - -(define_expand "clrstrqi" - [(parallel [(set (match_operand:BLK 0 "general_operand" "") - (const_int 0)) - (use (match_operand:DI 1 "immediate_operand" "")) - (use (match_operand:DI 2 "immediate_operand" ""))])] - "" - " -{ - if (alpha_expand_block_clear (operands)) - DONE; - else - FAIL; -}") - -;; Subroutine of stack space allocation. Perform a stack probe. -(define_expand "probe_stack" - [(set (match_dup 1) (match_operand:DI 0 "const_int_operand" ""))] - "" - " -{ - operands[1] = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, - INTVAL (operands[0]))); - MEM_VOLATILE_P (operands[1]) = 1; - - operands[0] = const0_rtx; -}") - -;; This is how we allocate stack space. If we are allocating a -;; constant amount of space and we know it is less than 4096 -;; bytes, we need do nothing. -;; -;; If it is more than 4096 bytes, we need to probe the stack -;; periodically. -(define_expand "allocate_stack" - [(set (reg:DI 30) - (plus:DI (reg:DI 30) - (match_operand:DI 1 "reg_or_cint_operand" ""))) - (set (match_operand:DI 0 "register_operand" "=r") - (match_dup 2))] - "" - " -{ - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) < 32768) - { - if (INTVAL (operands[1]) >= 4096) - { - /* We do this the same way as in the prologue and generate explicit - probes. Then we update the stack by the constant. */ - - int probed = 4096; - - emit_insn (gen_probe_stack (GEN_INT (- probed))); - while (probed + 8192 < INTVAL (operands[1])) - emit_insn (gen_probe_stack (GEN_INT (- (probed += 8192)))); - - if (probed + 4096 < INTVAL (operands[1])) - emit_insn (gen_probe_stack (GEN_INT (- INTVAL(operands[1])))); - } - - operands[1] = GEN_INT (- INTVAL (operands[1])); - operands[2] = virtual_stack_dynamic_rtx; - } - else - { - rtx out_label = 0; - rtx loop_label = gen_label_rtx (); - rtx want = gen_reg_rtx (Pmode); - rtx tmp = gen_reg_rtx (Pmode); - rtx memref; - - emit_insn (gen_subdi3 (want, stack_pointer_rtx, - force_reg (Pmode, operands[1]))); - emit_insn (gen_adddi3 (tmp, stack_pointer_rtx, GEN_INT (-4096))); - - if (GET_CODE (operands[1]) != CONST_INT) - { - out_label = gen_label_rtx (); - emit_insn (gen_cmpdi (want, tmp)); - emit_jump_insn (gen_bgeu (out_label)); - } - - emit_label (loop_label); - memref = gen_rtx_MEM (DImode, tmp); - MEM_VOLATILE_P (memref) = 1; - emit_move_insn (memref, const0_rtx); - emit_insn (gen_adddi3 (tmp, tmp, GEN_INT(-8192))); - emit_insn (gen_cmpdi (tmp, want)); - emit_jump_insn (gen_bgtu (loop_label)); - if (obey_regdecls) - gen_rtx_USE (VOIDmode, tmp); - - memref = gen_rtx_MEM (DImode, want); - MEM_VOLATILE_P (memref) = 1; - emit_move_insn (memref, const0_rtx); - - if (out_label) - emit_label (out_label); - - emit_move_insn (stack_pointer_rtx, want); - emit_move_insn (operands[0], virtual_stack_dynamic_rtx); - DONE; - } -}") - -;; This is used by alpha_expand_prolog to do the same thing as above, -;; except we cannot at that time generate new basic blocks, so we hide -;; the loop in this one insn. - -(define_insn "prologue_stack_probe_loop" - [(unspec_volatile [(match_operand 0 "register_operand" "r") - (match_operand 1 "register_operand" "r")] 5)] - "" - "* -{ - operands[2] = gen_label_rtx (); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", - CODE_LABEL_NUMBER (operands[2])); - - return \"stq $31,-8192(%1)\;subq %0,1,%0\;lda %1,-8192(%1)\;bne %0,%l2\"; -}" - [(set_attr "length" "16") - (set_attr "type" "multi")]) - -(define_expand "prologue" - [(clobber (const_int 0))] - "" - "alpha_expand_prologue (); DONE;") - -(define_insn "init_fp" - [(set (match_operand:DI 0 "register_operand" "r") - (match_operand:DI 1 "register_operand" "r")) - (clobber (mem:BLK (match_operand:DI 2 "register_operand" "r")))] - "" - "bis %1,%1,%0") - -(define_expand "epilogue" - [(clobber (const_int 0))] - "" - "alpha_expand_epilogue (); DONE;") - -(define_expand "eh_epilogue" - [(use (match_operand:DI 0 "register_operand" "r")) - (use (match_operand:DI 1 "register_operand" "r")) - (use (match_operand:DI 2 "register_operand" "r"))] - "! TARGET_OPEN_VMS" - " -{ - alpha_eh_epilogue_sp_ofs = operands[1]; - if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 26) - { - rtx ra = gen_rtx_REG (Pmode, 26); - emit_move_insn (ra, operands[2]); - operands[2] = ra; - } -}") - -(define_expand "builtin_longjmp" - [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] - "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" - " -{ - /* The elements of the buffer are, in order: */ - rtx fp = gen_rtx_MEM (Pmode, operands[0]); - rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8)); - rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 16)); - rtx pv = gen_rtx_REG (Pmode, 27); - - /* This bit is the same as expand_builtin_longjmp. */ - emit_move_insn (hard_frame_pointer_rtx, fp); - emit_move_insn (pv, lab); - emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); - emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); - emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); - - /* Load the label we are jumping through into $27 so that we know - where to look for it when we get back to setjmp's function for - restoring the gp. */ - emit_indirect_jump (pv); - DONE; -}") - -(define_insn "builtin_setjmp_receiver" - [(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)] - "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT && TARGET_AS_CAN_SUBTRACT_LABELS" - "\\n$LSJ%=:\;ldgp $29,$LSJ%=-%l0($27)" - [(set_attr "length" "8") - (set_attr "type" "multi")]) - -(define_insn "" - [(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)] - "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" - "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)" - [(set_attr "length" "12") - (set_attr "type" "multi")]) - -(define_insn "exception_receiver" - [(unspec_volatile [(const_int 0)] 7)] - "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" - "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)" - [(set_attr "length" "12") - (set_attr "type" "multi")]) - -(define_expand "nonlocal_goto_receiver" - [(unspec_volatile [(const_int 0)] 1) - (set (reg:DI 27) (mem:DI (reg:DI 29))) - (unspec_volatile [(const_int 0)] 1) - (use (reg:DI 27))] - "TARGET_OPEN_VMS" - "") - -(define_insn "arg_home" - [(unspec [(const_int 0)] 0) - (use (reg:DI 1)) - (use (reg:DI 25)) - (use (reg:DI 16)) - (use (reg:DI 17)) - (use (reg:DI 18)) - (use (reg:DI 19)) - (use (reg:DI 20)) - (use (reg:DI 21)) - (use (reg:DI 48)) - (use (reg:DI 49)) - (use (reg:DI 50)) - (use (reg:DI 51)) - (use (reg:DI 52)) - (use (reg:DI 53)) - (clobber (mem:BLK (const_int 0))) - (clobber (reg:DI 24)) - (clobber (reg:DI 25)) - (clobber (reg:DI 0))] - "TARGET_OPEN_VMS" - "lda $0,OTS$HOME_ARGS\;ldq $0,8($0)\;jsr $0,OTS$HOME_ARGS" - [(set_attr "length" "16") - (set_attr "type" "multi")]) - -;; Close the trap shadow of preceeding instructions. This is generated -;; by alpha_reorg. - -(define_insn "trapb" - [(unspec_volatile [(const_int 0)] 4)] - "" - "trapb" - [(set_attr "type" "misc")]) - -;; No-op instructions used by machine-dependant reorg to preserve -;; alignment for instruction issue. - -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "type" "ilog")]) - -(define_insn "fnop" - [(const_int 1)] - "TARGET_FP" - "fnop" - [(set_attr "type" "fcpys")]) - -(define_insn "unop" - [(const_int 2)] - "" - "unop") - -(define_insn "realign" - [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 6)] - "" - ".align %0 #realign") - -;; Peepholes go at the end. - -;; Optimize sign-extension of SImode loads. This shows up in the wake of -;; reload when converting fp->int. -;; -;; ??? What to do now that we actually care about the packing and -;; alignment of instructions? Perhaps reload can be enlightened, or -;; the peephole pass moved up after reload but before sched2? -; -;(define_peephole -; [(set (match_operand:SI 0 "register_operand" "=r") -; (match_operand:SI 1 "memory_operand" "m")) -; (set (match_operand:DI 2 "register_operand" "=r") -; (sign_extend:DI (match_dup 0)))] -; "dead_or_set_p (insn, operands[0])" -; "ldl %2,%1") -; -;(define_peephole -; [(set (match_operand:SI 0 "register_operand" "=r") -; (match_operand:SI 1 "hard_fp_register_operand" "f")) -; (set (match_operand:DI 2 "register_operand" "=r") -; (sign_extend:DI (match_dup 0)))] -; "TARGET_CIX && dead_or_set_p (insn, operands[0])" -; "ftois %1,%2") diff --git a/gcc/config/alpha/config-nt.sed b/gcc/config/alpha/config-nt.sed deleted file mode 100755 index 62a85fb..0000000 --- a/gcc/config/alpha/config-nt.sed +++ /dev/null @@ -1,33 +0,0 @@ -/^Makefile/,/^ rm -f config.run/d -s/rm -f/del/ -s/|| cp/|| copy/ -/^config.status/,/ fi/d -s/config.status//g -s/\/dev\/null/NUL/g -s/$(srcdir)\/c-parse/c-parse/g -s/$(srcdir)\/c-gperf/c-gperf/g -/^multilib.h/ s/multilib/not-multilib/ -/^target=/ c\ -target=winnt3.5 -/^xmake_file=/ d -/^tmake_file=/ d -/^out_file/ c\ -out_file=config/alpha/alpha.c -/^out_object_file/ c\ -out_object_file=alpha.obj -/^md_file/ c\ -md_file=config/alpha/alpha.md -/^tm_file/ c\ -tm_file=config/alpha/alpha.h config/alpha/winnt.h -/^build_xm_file/ c\ -build_xm_file=config/alpha/xm-alpha.h config/winnt/xm-winnt.h config/alpha/xm-winnt.h -/^host_xm_file/ c\ -host_xm_file=config/alpha/xm-alpha.h config/winnt/xm-winnt.h config/alpha/xm-winnt.h -/^####target/ i\ -CC = cl \ -CLIB = libc.lib kernel32.lib \ -CFLAGS = -Dalpha -DWIN32 -D_WIN32 -D_ALPHA_ -D_M_ALPHA \\\ - -DALMOST_STDC \ -LDFLAGS = -subsystem:console -entry:mainCRTStartup \\\ - -stack:1000000,1000 \ - diff --git a/gcc/config/alpha/crtbegin.asm b/gcc/config/alpha/crtbegin.asm deleted file mode 100755 index f954f1a..0000000 --- a/gcc/config/alpha/crtbegin.asm +++ /dev/null @@ -1,192 +0,0 @@ - # Copyright (C) 1996, 1998 Free Software Foundation, Inc. - # Contributed by Richard Henderson (rth@tamu.edu) - # - # 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, 59 Temple Place - Suite 330, - # Boston, MA 02111-1307, 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. - - # - # Heads of the constructor/destructor lists. - # - - # The __*TOR_LIST__ symbols are not global because when this file is used - # in a shared library, we do not want the symbol to fall over to the - # application's lists. - -.section .ctors,"aw" - - .align 3 -__CTOR_LIST__: - .quad -1 - -.section .dtors,"aw" - - .align 3 -__DTOR_LIST__: - .quad -1 - -.section .eh_frame,"aw" -__EH_FRAME_BEGIN__: - - # - # Fragment of the ELF _fini routine that invokes our dtor cleanup. - # - -.section .fini,"ax" - - # Since the bits of the _fini function are spread across many - # object files, each potentially with its own GP, we must - # assume we need to load ours. Further, our .fini section - # can easily be more than 4MB away from our .text bits so we - # can't use bsr. - - br $29,1f -1: ldgp $29,0($29) - jsr $26,__do_global_dtors_aux - - # Ideally this call would go in crtend.o, except that we can't - # get hold of __EH_FRAME_BEGIN__ there. - - jsr $26,__do_frame_takedown - - # Must match the alignment we got from crti.o else we get - # zero-filled holes in our _fini function and then SIGILL. - .align 3 - - # - # Fragment of the ELF _init routine that sets up the frame info. - # - -.section .init,"ax" - br $29,1f -1: ldgp $29,0($29) - jsr $26,__do_frame_setup - .align 3 - - # - # Invoke our destructors in order. - # - -.data - - # Support recursive calls to exit. -$ptr: .quad __DTOR_LIST__ - -.text - - .align 3 - .ent __do_global_dtors_aux - -__do_global_dtors_aux: - lda $30,-16($30) - .frame $30,16,$26,0 - stq $9,8($30) - stq $26,0($30) - .mask 0x4000200,-16 - .prologue 0 - - lda $9,$ptr - br 1f -0: stq $1,0($9) - jsr $26,($27) -1: ldq $1,0($9) - ldq $27,8($1) - addq $1,8,$1 - bne $27,0b - - ldq $26,0($30) - ldq $9,8($30) - lda $30,16($30) - ret - - .end __do_global_dtors_aux - - # - # Install our frame info. - # - - # ??? How can we rationally keep this size correct? - -.section .bss - .type $object,@object - .align 3 -$object: - .zero 48 - .size $object, 48 - -.text - - .align 3 - .ent __do_frame_setup - -__do_frame_setup: - ldgp $29,0($27) - lda $30,-16($30) - .frame $30,16,$26,0 - stq $26,0($30) - .mask 0x4000000,-16 - .prologue 1 - - lda $1,__register_frame_info - beq $1,0f - lda $16,__EH_FRAME_BEGIN__ - lda $17,$object - jsr $26,__register_frame_info - ldq $26,0($30) -0: lda $30,16($30) - ret - - .end __do_frame_setup - - # - # Remove our frame info. - # - - .align 3 - .ent __do_frame_takedown - -__do_frame_takedown: - ldgp $29,0($27) - lda $30,-16($30) - .frame $30,16,$26,0 - stq $26,0($30) - .mask 0x4000000,-16 - .prologue 1 - - lda $1,__deregister_frame_info - beq $1,0f - lda $16,__EH_FRAME_BEGIN__ - jsr $26,__deregister_frame_info - ldq $26,0($30) -0: lda $30,16($30) - ret - - .end __do_frame_takedown - -.weak __register_frame_info -.weak __deregister_frame_info diff --git a/gcc/config/alpha/crtend.asm b/gcc/config/alpha/crtend.asm deleted file mode 100755 index 4a0cc5e..0000000 --- a/gcc/config/alpha/crtend.asm +++ /dev/null @@ -1,108 +0,0 @@ - # Copyright (C) 1996 Free Software Foundation, Inc. - # Contributed by Richard Henderson (rth@tamu.edu) - # - # 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, 59 Temple Place - Suite 330, - # Boston, MA 02111-1307, 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. - - # - # Tails of the constructor/destructor lists. - # - - # The __*TOR_END__ symbols are not global because when this file is used - # in a shared library, we do not want the symbol to fall over to the - # application's lists. - -.section .ctors,"aw" - - .align 3 -__CTOR_END__: - .quad 0 - -.section .dtors,"aw" - - .align 3 -__DTOR_END__: - .quad 0 - -.section .eh_frame,"aw" -__FRAME_END__: - .quad 0 - - # - # Fragment of the ELF _init routine that invokes our ctor startup - # - -.section .init,"ax" - - # Since the bits of the _init function are spread across many - # object files, each potentially with its own GP, we must - # assume we need to load ours. Further, our .init section - # can easily be more than 4MB away from our .text bits so we - # can't use bsr. - - br $29,1f -1: ldgp $29,0($29) - jsr $26,__do_global_ctors_aux - - # Must match the alignment we got from crti.o else we get - # zero-filled holes in our _init function and thense SIGILL. - .align 3 - - # - # Invoke our destructors in order. - # - -.text - - .align 3 - .ent __do_global_ctors_aux - -__do_global_ctors_aux: - ldgp $29,0($27) - lda $30,-16($30) - .frame $30,16,$26,0 - stq $9,8($30) - stq $26,0($30) - .mask 0x4000200,-16 - .prologue 1 - - lda $9,__CTOR_END__ - br 1f -0: jsr $26,($27) -1: ldq $27,-8($9) - subq $9,8,$9 - not $27,$0 - bne $0,0b - - ldq $26,0($30) - ldq $9,8($30) - lda $30,16($30) - ret - - .end __do_global_ctors_aux diff --git a/gcc/config/alpha/elf.h b/gcc/config/alpha/elf.h deleted file mode 100755 index d32ca41..0000000 --- a/gcc/config/alpha/elf.h +++ /dev/null @@ -1,527 +0,0 @@ -/* Definitions of target machine for GNU compiler, for DEC Alpha w/ELF. - Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. - Contributed by Richard Henderson (rth@tamu.edu). - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef OBJECT_FORMAT_COFF -#undef EXTENDED_COFF -#define OBJECT_FORMAT_ELF - -#define DBX_DEBUGGING_INFO -#define DWARF2_DEBUGGING_INFO - -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG - -#undef ASM_FINAL_SPEC - -#undef CC1_SPEC -#define CC1_SPEC "%{G*}" - -#undef ASM_SPEC -#define ASM_SPEC "%{G*} %{relax:-relax} %{gdwarf*:-no-mdebug}" - -#undef LINK_SPEC -#define LINK_SPEC "-m elf64alpha %{G*} %{relax:-relax} \ - %{O*:-O3} %{!O*:-O1} \ - %{shared:-shared} \ - %{!shared: \ - %{!static: \ - %{rdynamic:-export-dynamic} \ - %{!dynamic-linker:-dynamic-linker %(elf_dynamic_linker)}} \ - %{static:-static}}" - -/* Output at beginning of assembler file. */ -#undef ASM_FILE_START -#define ASM_FILE_START(FILE) \ -do { \ - if (write_symbols != DWARF2_DEBUG) \ - { \ - alpha_write_verstamp (FILE); \ - output_file_directive (FILE, main_input_filename); \ - } \ - fprintf (FILE, "\t.set noat\n"); \ - fprintf (FILE, "\t.set noreorder\n"); \ - if (TARGET_BWX | TARGET_MAX | TARGET_CIX) \ - { \ - fprintf (FILE, "\t.arch %s\n", \ - (alpha_cpu == PROCESSOR_EV6 ? "ev6" \ - : TARGET_MAX ? "pca56" : "ev56")); \ - } \ -} while (0) - -extern void output_file_directive (); - -/* Attach a special .ident directive to the end of the file to identify - the version of GCC which compiled this code. The format of the - .ident string is patterned after the ones produced by native svr4 - C compilers. */ - -#define IDENT_ASM_OP ".ident" - -#ifdef IDENTIFY_WITH_IDENT -#define ASM_IDENTIFY_GCC(FILE) /* nothing */ -#define ASM_IDENTIFY_LANGUAGE(FILE) \ - fprintf(FILE, "\t%s \"GCC (%s) %s\"\n", IDENT_ASM_OP, \ - lang_identify(), version_string) -#else -#define ASM_FILE_END(FILE) \ -do { \ - fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \ - IDENT_ASM_OP, version_string); \ - } while (0) -#endif - -/* Allow #sccs in preprocessor. */ -#define SCCS_DIRECTIVE - -/* Output #ident as a .ident. */ -#define ASM_OUTPUT_IDENT(FILE, NAME) \ - fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME); - -/* This is how to allocate empty space in some section. The .zero - pseudo-op is used for this on most svr4 assemblers. */ - -#define SKIP_ASM_OP ".zero" - -#undef ASM_OUTPUT_SKIP -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t%s\t%u\n", SKIP_ASM_OP, (SIZE)) - -/* Output the label which precedes a jumptable. Note that for all svr4 - systems where we actually generate jumptables (which is to say every - svr4 target except i386, where we use casesi instead) we put the jump- - tables into the .rodata section and since other stuff could have been - put into the .rodata section prior to any given jumptable, we have to - make sure that the location counter for the .rodata section gets pro- - perly re-aligned prior to the actual beginning of the jump table. */ - -#define ALIGN_ASM_OP ".align" - -#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL -#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ - ASM_OUTPUT_ALIGN ((FILE), 2); -#endif - -#undef ASM_OUTPUT_CASE_LABEL -#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \ - do { \ - ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE) \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \ - } while (0) - -/* The standard SVR4 assembler seems to require that certain builtin - library routines (e.g. .udiv) be explicitly declared as .globl - in each assembly file where they are referenced. */ - -#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ - ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0)) - -/* This says how to output assembler code to declare an - uninitialized external linkage data object. Under SVR4, - the linker seems to want the alignment of data objects - to depend on their types. We do exactly that here. */ - -#define COMMON_ASM_OP ".comm" - -#undef ASM_OUTPUT_ALIGNED_COMMON -#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ -do { \ - fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \ - assemble_name ((FILE), (NAME)); \ - fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ -} while (0) - -/* This says how to output assembler code to declare an - uninitialized internal linkage data object. Under SVR4, - the linker seems to want the alignment of data objects - to depend on their types. We do exactly that here. */ - -#undef ASM_OUTPUT_ALIGNED_LOCAL -#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ -do { \ - if ((SIZE) <= g_switch_value) \ - sbss_section(); \ - else \ - bss_section(); \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ - putc ('\n', FILE); \ - if (!flag_inhibit_size_directive) \ - { \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ",%d\n", (SIZE)); \ - } \ - ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - ASM_OUTPUT_SKIP((FILE), (SIZE)); \ -} while (0) - -/* This is the pseudo-op used to generate a 64-bit word of data with a - specific value in some section. */ - -#define INT_ASM_OP ".quad" - -/* 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'. - - This value is really 2^63. Since gcc figures the alignment in bits, - we could only potentially get to 2^60 on suitible hosts. Due to other - considerations in varasm, we must restrict this to what fits in an int. */ - -#define MAX_OFILE_ALIGNMENT \ - (1 << (HOST_BITS_PER_INT < 64 ? HOST_BITS_PER_INT - 2 : 62)) - -/* This is the pseudo-op used to generate a contiguous sequence of byte - values from a double-quoted string WITHOUT HAVING A TERMINATING NUL - AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */ - -#undef ASCII_DATA_ASM_OP -#define ASCII_DATA_ASM_OP ".ascii" - -/* Support const sections and the ctors and dtors sections for g++. - Note that there appears to be two different ways to support const - sections at the moment. You can either #define the symbol - READONLY_DATA_SECTION (giving it some code which switches to the - readonly data section) or else you can #define the symbols - EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and - SELECT_RTX_SECTION. We do both here just to be on the safe side. */ - -#define USE_CONST_SECTION 1 - -#define CONST_SECTION_ASM_OP ".section\t.rodata" - -/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. - - Note that we want to give these sections the SHF_WRITE attribute - because these sections will actually contain data (i.e. tables of - addresses of functions in the current root executable or shared library - file) and, in the case of a shared library, the relocatable addresses - will have to be properly resolved/relocated (and then written into) by - the dynamic linker when it actually attaches the given shared library - to the executing process. (Note that on SVR4, you may wish to use the - `-z text' option to the ELF linker, when building a shared library, as - an additional check that you are doing everything right. But if you do - use the `-z text' option when building a shared library, you will get - errors unless the .ctors and .dtors sections are marked as writable - via the SHF_WRITE attribute.) */ - -#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\"" -#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\"" - -/* Handle the small data sections. */ -#define BSS_SECTION_ASM_OP ".section\t.bss" -#define SBSS_SECTION_ASM_OP ".section\t.sbss,\"aw\"" -#define SDATA_SECTION_ASM_OP ".section\t.sdata,\"aw\"" - -/* On svr4, we *do* have support for the .init and .fini sections, and we - can put stuff in there to be executed before and after `main'. We let - crtstuff.c and other files know this by defining the following symbols. - The definitions say how to change sections to the .init and .fini - sections. This is the same for all known svr4 assemblers. */ - -#define INIT_SECTION_ASM_OP ".section\t.init" -#define FINI_SECTION_ASM_OP ".section\t.fini" - -/* A default list of other sections which we might be "in" at any given - time. For targets that use additional sections (e.g. .tdesc) you - should override this definition in the target-specific file which - includes this file. */ - -#undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_const, in_ctors, in_dtors, in_sbss, in_sdata - -/* A default list of extra section function definitions. For targets - that use additional sections (e.g. .tdesc) you should override this - definition in the target-specific file which includes this file. */ - -#undef EXTRA_SECTION_FUNCTIONS -#define EXTRA_SECTION_FUNCTIONS \ - CONST_SECTION_FUNCTION \ - SECTION_FUNCTION_TEMPLATE(ctors_section, in_ctors, CTORS_SECTION_ASM_OP) \ - SECTION_FUNCTION_TEMPLATE(dtors_section, in_dtors, DTORS_SECTION_ASM_OP) \ - SECTION_FUNCTION_TEMPLATE(sbss_section, in_sbss, SBSS_SECTION_ASM_OP) \ - SECTION_FUNCTION_TEMPLATE(sdata_section, in_sdata, SDATA_SECTION_ASM_OP) - -#undef READONLY_DATA_SECTION -#define READONLY_DATA_SECTION() const_section () - -extern void text_section (); - -#define CONST_SECTION_FUNCTION \ -void \ -const_section () \ -{ \ - if (!USE_CONST_SECTION) \ - text_section(); \ - else if (in_section != in_const) \ - { \ - fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \ - in_section = in_const; \ - } \ -} - -#define SECTION_FUNCTION_TEMPLATE(FN, ENUM, OP) \ -void FN () \ -{ \ - if (in_section != ENUM) \ - { \ - fprintf (asm_out_file, "%s\n", OP); \ - in_section = ENUM; \ - } \ -} - - -/* Switch into a generic section. - This is currently only used to support section attributes. - - We make the section read-only and executable for a function decl, - read-only for a const data decl, and writable for a non-const data decl. */ -#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ - fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \ - (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \ - (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw") - - -/* A C statement (sans semicolon) to output an element in the table of - global constructors. */ -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - ctors_section (); \ - fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - dtors_section (); \ - fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* 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. */ - -#define SELECT_SECTION(DECL,RELOC) \ -{ \ - if (TREE_CODE (DECL) == STRING_CST) \ - { \ - if (! flag_writable_strings) \ - const_section (); \ - else \ - data_section (); \ - } \ - else if (TREE_CODE (DECL) == VAR_DECL) \ - { \ - if ((flag_pic && RELOC) \ - || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ - || !DECL_INITIAL (DECL) \ - || (DECL_INITIAL (DECL) != error_mark_node \ - && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \ - { \ - int size = int_size_in_bytes (TREE_TYPE (DECL)); \ - if (size >= 0 && size <= g_switch_value) \ - sdata_section (); \ - else \ - data_section (); \ - } \ - else \ - const_section (); \ - } \ - else \ - const_section (); \ -} - -/* A C statement or statements to switch to the appropriate - section for output of RTX in mode MODE. RTX is some kind - of constant in RTL. The argument MODE is redundant except - in the case of a `const_int' rtx. Currently, these always - go into the const section. */ - -#undef SELECT_RTX_SECTION -#define SELECT_RTX_SECTION(MODE,RTX) const_section() - -/* Define the strings used for the special svr4 .type and .size directives. - These strings generally do not vary from one system running svr4 to - another, but if a given system (e.g. m88k running svr) needs to use - different pseudo-op names for these, they may be overridden in the - file which includes this one. */ - -#define TYPE_ASM_OP ".type" -#define SIZE_ASM_OP ".size" - -/* This is how we tell the assembler that a symbol is weak. */ - -#define ASM_WEAKEN_LABEL(FILE,NAME) \ - do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \ - fputc ('\n', FILE); } while (0) - -/* This is how we tell the assembler that two symbols have the same value. */ - -#define ASM_OUTPUT_DEF(FILE,NAME1,NAME2) \ - do { assemble_name(FILE, NAME1); \ - fputs(" = ", FILE); \ - assemble_name(FILE, NAME2); \ - fputc('\n', FILE); } while (0) - -/* The following macro defines the format used to output the second - operand of the .type assembler directive. Different svr4 assemblers - expect various different forms for this operand. The one given here - is just a default. You may need to override it in your machine- - specific tm.h file (depending upon the particulars of your assembler). */ - -#define TYPE_OPERAND_FMT "@%s" - -/* Write the extra assembler code needed to declare a function's result. - Most svr4 assemblers don't require any special declaration of the - result value, but there are exceptions. */ - -#ifndef ASM_DECLARE_RESULT -#define ASM_DECLARE_RESULT(FILE, RESULT) -#endif - -/* These macros generate the special .type and .size directives which - are used to set the corresponding fields of the linker symbol table - entries in an ELF object file under SVR4. These macros also output - the starting labels for the relevant functions/objects. */ - -/* Write the extra assembler code needed to declare an object properly. */ - -#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ - do { \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ - putc ('\n', FILE); \ - size_directive_output = 0; \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ - { \ - size_directive_output = 1; \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ - } \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -/* Output the size directive for a decl in rest_of_decl_compilation - in the case where we did not do so before the initializer. - Once we find the error_mark_node, we know that the value of - size_directive_output was set - by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ - -#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ -do { \ - char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ - && ! AT_END && TOP_LEVEL \ - && DECL_INITIAL (DECL) == error_mark_node \ - && !size_directive_output) \ - { \ - size_directive_output = 1; \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, name); \ - putc (',', FILE); \ - fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \ - int_size_in_bytes (TREE_TYPE (DECL))); \ - putc ('\n', FILE); \ - } \ -} while (0) - -/* A table of bytes codes used by the ASM_OUTPUT_ASCII and - ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table - corresponds to a particular byte value [0..255]. For any - given byte value, if the value in the corresponding table - position is zero, the given character can be output directly. - If the table value is 1, the byte must be output as a \ooo - octal escape. If the tables value is anything else, then the - byte value should be output as a \ followed by the value - in the table. Note that we can use standard UN*X escape - sequences for many control characters, but we don't use - \a to represent BEL because some svr4 assemblers (e.g. on - the i386) don't know about that. Also, we don't use \v - since some versions of gas, such as 2.2 did not accept it. */ - -#define ESCAPES \ -"\1\1\1\1\1\1\1\1btn\1fr\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\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\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\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" - -/* Some svr4 assemblers have a limit on the number of characters which - can appear in the operand of a .string directive. If your assembler - has such a limitation, you should define STRING_LIMIT to reflect that - limit. Note that at least some svr4 assemblers have a limit on the - actual number of bytes in the double-quoted string, and that they - count each character in an escape sequence as one byte. Thus, an - escape sequence like \377 would count as four bytes. - - If your target assembler doesn't support the .string directive, you - should define this to zero. */ - -#define STRING_LIMIT ((unsigned) 256) -#define STRING_ASM_OP ".string" - -/* GAS is the only Alpha/ELF assembler. */ -#undef TARGET_GAS -#define TARGET_GAS (1) - -/* Provide a STARTFILE_SPEC appropriate for ELF. Here we add the - (even more) magical crtbegin.o file which provides part of the - support for getting C++ file-scope static object constructed before - entering `main'. - - Don't bother seeing crtstuff.c -- there is absolutely no hope of - getting that file to understand multiple GPs. GNU Libc provides a - hand-coded version that is used on Linux; it could be copied here - if there is ever a need. */ - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{!shared: \ - %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\ - crti.o%s crtbegin.o%s" - -/* Provide a ENDFILE_SPEC appropriate for ELF. Here we tack on the - magical crtend.o file which provides part of the support for - getting C++ file-scope static object constructed before entering - `main', followed by a normal ELF "finalizer" file, `crtn.o'. */ - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC \ - "crtend.o%s crtn.o%s" - -/* We support #pragma. */ -#define HANDLE_SYSV_PRAGMA diff --git a/gcc/config/alpha/lib1funcs.asm b/gcc/config/alpha/lib1funcs.asm deleted file mode 100755 index 355c610..0000000 --- a/gcc/config/alpha/lib1funcs.asm +++ /dev/null @@ -1,327 +0,0 @@ -/* This file is CYGNUS LOCAL. */ - -/* DEC Alpha division and remainder support. - Copyright (C) 1994 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, 675 Mass Ave, Cambridge, MA 02139, 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 had to be written in assembler because the division functions - use a non-standard calling convention. - - This file provides an implementation of __divqu, __divq, __divlu, - __divl, __remqu, __remq, __remlu and __reml. CPP macros control - the exact operation. - - Operation performed: $27 := $24 o $25, clobber $28, return address to - caller in $23, where o one of the operations. - - The following macros need to be defined: - - SIZE, the number of bits, 32 or 64. - - TYPE, either UNSIGNED or SIGNED - - OPERATION, either DIVISION or REMAINDER - - SPECIAL_CALLING_CONVENTION, 0 or 1. It is useful for debugging to - define this to 0. That removes the `__' prefix to make the function - name not collide with the existing libc.a names, and uses the - standard Alpha procedure calling convention. -*/ - -#ifndef SPECIAL_CALLING_CONVENTION -#define SPECIAL_CALLING_CONVENTION 1 -#endif - -#ifdef L_divl -#if SPECIAL_CALLING_CONVENTION -#define FUNCTION_NAME __divl -#else -#define FUNCTION_NAME divl -#endif -#define SIZE 32 -#define TYPE SIGNED -#define OPERATION DIVISION -#endif - -#ifdef L_divlu -#if SPECIAL_CALLING_CONVENTION -#define FUNCTION_NAME __divlu -#else -#define FUNCTION_NAME divlu -#endif -#define SIZE 32 -#define TYPE UNSIGNED -#define OPERATION DIVISION -#endif - -#ifdef L_divq -#if SPECIAL_CALLING_CONVENTION -#define FUNCTION_NAME __divq -#else -#define FUNCTION_NAME divq -#endif -#define SIZE 64 -#define TYPE SIGNED -#define OPERATION DIVISION -#endif - -#ifdef L_divqu -#if SPECIAL_CALLING_CONVENTION -#define FUNCTION_NAME __divqu -#else -#define FUNCTION_NAME divqu -#endif -#define SIZE 64 -#define TYPE UNSIGNED -#define OPERATION DIVISION -#endif - -#ifdef L_reml -#if SPECIAL_CALLING_CONVENTION -#define FUNCTION_NAME __reml -#else -#define FUNCTION_NAME reml -#endif -#define SIZE 32 -#define TYPE SIGNED -#define OPERATION REMAINDER -#endif - -#ifdef L_remlu -#if SPECIAL_CALLING_CONVENTION -#define FUNCTION_NAME __remlu -#else -#define FUNCTION_NAME remlu -#endif -#define SIZE 32 -#define TYPE UNSIGNED -#define OPERATION REMAINDER -#endif - -#ifdef L_remq -#if SPECIAL_CALLING_CONVENTION -#define FUNCTION_NAME __remq -#else -#define FUNCTION_NAME remq -#endif -#define SIZE 64 -#define TYPE SIGNED -#define OPERATION REMAINDER -#endif - -#ifdef L_remqu -#if SPECIAL_CALLING_CONVENTION -#define FUNCTION_NAME __remqu -#else -#define FUNCTION_NAME remqu -#endif -#define SIZE 64 -#define TYPE UNSIGNED -#define OPERATION REMAINDER -#endif - -#define tmp0 $3 -#define tmp1 $28 -#define cnt $1 -#define result_sign $2 - -#if SPECIAL_CALLING_CONVENTION -#define N $24 -#define D $25 -#define Q RETREG -#define RETREG $27 -#else -#define N $16 -#define D $17 -#define Q RETREG -#define RETREG $0 -#endif - -/* Misc symbols to make alpha assembler easier to read. */ -#define zero $31 -#define sp $30 - -/* Symbols to make interface nicer. */ -#define UNSIGNED 0 -#define SIGNED 1 -#define DIVISION 0 -#define REMAINDER 1 - - .set noreorder - .set noat -.text - .align 3 - .globl FUNCTION_NAME - .ent FUNCTION_NAME -FUNCTION_NAME: - - .frame $30,0,$26,0 - .prologue 0 - -/* Under the special calling convention, we have to preserve all register - values but $23 and $28. */ -#if SPECIAL_CALLING_CONVENTION - lda sp,-64(sp) -#if OPERATION == DIVISION - stq N,0(sp) -#endif - stq D,8(sp) - stq cnt,16(sp) - stq result_sign,24(sp) - stq tmp0,32(sp) -#endif - -/* If we are computing the remainder, move N to the register that is used - for the return value, and redefine what register is used for N. */ -#if OPERATION == REMAINDER - bis N,N,RETREG -#undef N -#define N RETREG -#endif - -/* Perform conversion from 32 bit types to 64 bit types. */ -#if SIZE == 32 -#if TYPE == SIGNED - /* If there are problems with the signed case, add these instructions. - The caller should already have done this. - addl N,0,N # sign extend N - addl D,0,D # sign extend D - */ -#else /* UNSIGNED */ - zap N,0xf0,N # zero extend N (caller required to sign extend) - zap D,0xf0,D # zero extend D -#endif -#endif - -/* Check for divide by zero. */ - bne D,$34 - lda $16,-2(zero) - call_pal 0xaa -$34: - -#if TYPE == SIGNED -#if OPERATION == DIVISION - xor N,D,result_sign -#else - bis N,N,result_sign -#endif -/* Get the absolute values of N and D. */ - subq zero,N,tmp0 - cmovlt N,tmp0,N - subq zero,D,tmp0 - cmovlt D,tmp0,D -#endif - -/* Compute CNT = ceil(log2(N)) - ceil(log2(D)). This is the number of - divide iterations we will have to perform. Should you wish to optimize - this, check a few bits at a time, preferably using zap/zapnot. Be - careful though, this code runs fast fro the most common cases, when the - quotient is small. */ - bge N,$35 - bis zero,1,cnt - blt D,$40 - .align 3 -$39: addq D,D,D - addl cnt,1,cnt - bge D,$39 - br zero,$40 -$35: cmpult N,D,tmp0 - bis zero,zero,cnt - bne tmp0,$42 - .align 3 -$44: addq D,D,D - cmpult N,D,tmp0 - addl cnt,1,cnt - beq tmp0,$44 -$42: srl D,1,D -$40: - subl cnt,1,cnt - - -/* Actual divide. Could be optimized with unrolling. */ -#if OPERATION == DIVISION - bis zero,zero,Q -#endif - blt cnt,$46 - .align 3 -$49: cmpule D,N,tmp1 - subq N,D,tmp0 - srl D,1,D - subl cnt,1,cnt - cmovne tmp1,tmp0,N -#if OPERATION == DIVISION - addq Q,Q,Q - bis Q,tmp1,Q -#endif - bge cnt,$49 -$46: - - -/* The result is now in RETREG. NOTE! It was written to RETREG using - either N or Q as a synonym! */ - - -/* Change the sign of the result as needed. */ -#if TYPE == SIGNED - subq zero,RETREG,tmp0 - cmovlt result_sign,tmp0,RETREG -#endif - - -/* Restore clobbered registers. */ -#if SPECIAL_CALLING_CONVENTION -#if OPERATION == DIVISION - ldq N,0(sp) -#endif - ldq D,8(sp) - ldq cnt,16(sp) - ldq result_sign,24(sp) - ldq tmp0,32(sp) - - lda sp,64(sp) -#endif - - -/* Sign extend an *unsigned* 32 bit result, as required by the Alpha - conventions. */ -#if TYPE == UNSIGNED && SIZE == 32 - /* This could be avoided by adding some CPP hair to the divide loop. - It is probably not worth the added complexity. */ - addl RETREG,0,RETREG -#endif - - -#if SPECIAL_CALLING_CONVENTION - ret zero,($23),1 -#else - ret zero,($26),1 -#endif - .end FUNCTION_NAME diff --git a/gcc/config/alpha/linux-ecoff.h b/gcc/config/alpha/linux-ecoff.h deleted file mode 100755 index 824d028..0000000 --- a/gcc/config/alpha/linux-ecoff.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Definitions of target machine for GNU compiler - for Alpha Linux-based GNU systems using ECOFF. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. - Contributed by Bob Manson. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux for ECOFF)"); - -#undef CPP_SUBTARGET_SPEC -#define CPP_SUBTARGET_SPEC "-D__ECOFF__" - -#undef LINK_SPEC -#define LINK_SPEC "-G 8 %{O*:-O3} %{!O*:-O1}" - -/* stabs get slurped by the assembler into a queer ecoff format. */ -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG - -/* We support #pragma. */ -#define HANDLE_SYSV_PRAGMA diff --git a/gcc/config/alpha/linux-elf.h b/gcc/config/alpha/linux-elf.h deleted file mode 100755 index fc07127..0000000 --- a/gcc/config/alpha/linux-elf.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Definitions of target machine for GNU compiler - for Alpha Linux-based GNU systems using ELF. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. - Contributed by Richard Henderson. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux for ELF)"); - -#undef SUBTARGET_EXTRA_SPECS -#define SUBTARGET_EXTRA_SPECS \ -{ "elf_dynamic_linker", ELF_DYNAMIC_LINKER }, - -#undef SUB_CPP_PREDEFINES -#define SUB_CPP_PREDEFINES "-D__ELF__" - -#ifdef USE_GNULIBC_1 -#define ELF_DYNAMIC_LINKER "/lib/ld.so.1" -#else -#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2" -#endif - -#ifndef USE_GNULIBC_1 -#undef DEFAULT_VTABLE_THUNKS -#define DEFAULT_VTABLE_THUNKS 1 -#endif - -#ifndef USE_GNULIBC_1 -#undef LIB_SPEC -#define LIB_SPEC \ -"%{shared:-lc}%{!shared:%{pthread:-lpthread }%{profile:-lc_p}%{!profile:-lc}} " -#endif diff --git a/gcc/config/alpha/linux.h b/gcc/config/alpha/linux.h deleted file mode 100755 index b8eb9e9..0000000 --- a/gcc/config/alpha/linux.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Definitions of target machine for GNU compiler, - for Alpha Linux-based GNU systems. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. - Contributed by Richard Henderson. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS) - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES \ -"-Dlinux -Dunix -Asystem(linux) -D_LONGLONG -D__alpha__ " \ -SUB_CPP_PREDEFINES - -#undef LIB_SPEC -#define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}" - -/* Generate calls to memcpy, etc., not bcopy, etc. */ -#define TARGET_MEM_FUNCTIONS 1 - -#undef FUNCTION_PROFILER -#define FUNCTION_PROFILER(FILE, LABELNO) \ - fputs ("\tlda $28,_mcount\n\tjsr $28,($28),_mcount\n", (FILE)) - -/* Show that we need a GP when profiling. */ -#define TARGET_PROFILING_NEEDS_GP 1 - -/* Don't care about faults in the prologue. */ -#undef TARGET_CAN_FAULT_IN_PROLOGUE -#define TARGET_CAN_FAULT_IN_PROLOGUE 1 diff --git a/gcc/config/alpha/netbsd-elf.h b/gcc/config/alpha/netbsd-elf.h deleted file mode 100755 index 6e4f4da..0000000 --- a/gcc/config/alpha/netbsd-elf.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Definitions of target machine for GNU compiler - for Alpha NetBSD systems using ELF. - Copyright (C) 1998 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (Alpha NetBSD/ELF)"); - -#undef SUB_CPP_PREDEFINES -#define SUB_CPP_PREDEFINES "-D__ELF__" - -#undef SUBTARGET_EXTRA_SPECS -#define SUBTARGET_EXTRA_SPECS \ -{ "elf_dynamic_linker", ELF_DYNAMIC_LINKER }, - -#define ELF_DYNAMIC_LINKER "/usr/libexec/ld.elf_so" diff --git a/gcc/config/alpha/netbsd.h b/gcc/config/alpha/netbsd.h deleted file mode 100755 index 5189064..0000000 --- a/gcc/config/alpha/netbsd.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Definitions of target machine for GNU compiler, - for Alpha NetBSD systems. - Copyright (C) 1998 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS) - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-D_LONGLONG -Dnetbsd -Dunix " SUB_CPP_PREDEFINES - -#undef LIB_SPEC -#define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}" - -/* Generate calls to memcpy, etc., not bcopy, etc. */ -#define TARGET_MEM_FUNCTIONS - -#undef FUNCTION_PROFILER -#define FUNCTION_PROFILER(FILE, LABELNO) \ - fputs ("\tlda $28,_mcount\n\tjsr $28,($28),_mcount\n", (FILE)) - -/* Show that we need a GP when profiling. */ -#define TARGET_PROFILING_NEEDS_GP diff --git a/gcc/config/alpha/osf.h b/gcc/config/alpha/osf.h deleted file mode 100755 index 956961f..0000000 --- a/gcc/config/alpha/osf.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Definitions of target machine for GNU compiler, for DEC Alpha on OSF/1. - Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* As of OSF 4.0, as can subtract adjacent labels. */ - -#undef TARGET_AS_CAN_SUBTRACT_LABELS -#define TARGET_AS_CAN_SUBTRACT_LABELS 1 - -/* Names to predefine in the preprocessor for this target machine. */ - -#define CPP_PREDEFINES "\ --Dunix -D__osf__ -D_LONGLONG -DSYSTYPE_BSD \ --D_SYSTYPE_BSD -Asystem(unix) -Asystem(xpg4)" - -/* Under OSF4, -p and -pg require -lprof1, and -lprof1 requires -lpdf. */ - -#define LIB_SPEC "%{p:-lprof1 -lpdf} %{pg:-lprof1 -lpdf} %{a:-lprof2} -lc" - -/* Pass "-G 8" to ld because Alpha's CC does. Pass -O3 if we are - optimizing, -O1 if we are not. Pass -shared, -non_shared or - -call_shared as appropriate. Also pass -pg. */ -#define LINK_SPEC \ - "-G 8 %{O*:-O3} %{!O*:-O1} %{static:-non_shared} \ - %{!static:%{shared:-shared} %{!shared:-call_shared}} %{pg} %{taso} \ - %{rpath*}" - -#define STARTFILE_SPEC \ - "%{!shared:%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}" - -#define MD_STARTFILE_PREFIX "/usr/lib/cmplrs/cc/" - -#define ASM_FILE_START(FILE) \ -{ \ - alpha_write_verstamp (FILE); \ - fprintf (FILE, "\t.set noreorder\n"); \ - fprintf (FILE, "\t.set volatile\n"); \ - fprintf (FILE, "\t.set noat\n"); \ - if (TARGET_SUPPORT_ARCH) \ - fprintf (FILE, "\t.arch %s\n", \ - alpha_cpu == PROCESSOR_EV6 ? "ev6" \ - : (alpha_cpu == PROCESSOR_EV5 \ - ? (TARGET_MAX ? "pca56" : TARGET_BWX ? "ev56" : "ev5") \ - : "ev4")); \ - \ - ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ -} - -/* No point in running CPP on our assembler output. */ -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GAS) != 0 -/* Don't pass -g to GNU as, because some versions don't accept this option. */ -#define ASM_SPEC "%{malpha-as:-g} -nocpp %{pg}" -#else -/* In OSF/1 v3.2c, the assembler by default does not output file names which - causes mips-tfile to fail. Passing -g to the assembler fixes this problem. - ??? Strictly speaking, we need -g only if the user specifies -g. Passing - it always means that we get slightly larger than necessary object files - if the user does not specify -g. If we don't pass -g, then mips-tfile - will need to be fixed to work in this case. Pass -O0 since some - optimization are broken and don't help us anyway. */ -#define ASM_SPEC "%{!mgas:-g} -nocpp %{pg} -O0" -#endif - -/* Specify to run a post-processor, mips-tfile after the assembler - has run to stuff the ecoff debug information into the object file. - This is needed because the Alpha assembler provides no way - of specifying such information in the assembly file. */ - -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GAS) != 0 - -#define ASM_FINAL_SPEC "\ -%{malpha-as: %{!mno-mips-tfile: \ - \n mips-tfile %{v*: -v} \ - %{K: -I %b.o~} \ - %{!K: %{save-temps: -I %b.o~}} \ - %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ - %{.s:%i} %{!.s:%g.s}}}" - -#else -#define ASM_FINAL_SPEC "\ -%{!mgas: %{!mno-mips-tfile: \ - \n mips-tfile %{v*: -v} \ - %{K: -I %b.o~} \ - %{!K: %{save-temps: -I %b.o~}} \ - %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ - %{.s:%i} %{!.s:%g.s}}}" - -#endif - -/* Indicate that we have a stamp.h to use. */ -#ifndef CROSS_COMPILE -#define HAVE_STAMP_H 1 -#endif - -/* Attempt to turn on access permissions for the stack. */ - -#define TRANSFER_FROM_TRAMPOLINE \ -void \ -__enable_execute_stack (addr) \ - void *addr; \ -{ \ - long size = getpagesize (); \ - long mask = ~(size-1); \ - char *page = (char *) (((long) addr) & mask); \ - char *end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \ - \ - /* 7 is PROT_READ | PROT_WRITE | PROT_EXEC */ \ - if (mprotect (page, end - page, 7) < 0) \ - perror ("mprotect of trampoline code"); \ -} diff --git a/gcc/config/alpha/osf12.h b/gcc/config/alpha/osf12.h deleted file mode 100755 index 87e2111..0000000 --- a/gcc/config/alpha/osf12.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Definitions of target machine for GNU compiler, for DEC Alpha. - Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@nyu.edu) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* In OSF 1.2, there is a linker bug that prevents use of -O3 to - the linker. */ - -#undef LINK_SPEC -#define LINK_SPEC \ - "-G 8 -O1 %{static:-non_shared} %{rpath*} \ - %{!static:%{shared:-shared} %{!shared:-call_shared}} %{taso}" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "short unsigned int" -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 diff --git a/gcc/config/alpha/osf2or3.h b/gcc/config/alpha/osf2or3.h deleted file mode 100755 index 5abdb0e..0000000 --- a/gcc/config/alpha/osf2or3.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Definitions of target machine for GNU compiler, for DEC Alpha, osf[23]. - Copyright (C) 1997 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* In OSF 2 or 3, linking with -lprof1 doesn't require -lpdf. */ - -#undef LIB_SPEC -#define LIB_SPEC "%{p:-lprof1} %{pg:-lprof1} %{a:-lprof2} -lc" - -/* As of OSF 3.2, as still can't subtract adjacent labels. */ - -#undef TARGET_AS_CAN_SUBTRACT_LABELS -#define TARGET_AS_CAN_SUBTRACT_LABELS 0 - diff --git a/gcc/config/alpha/t-crtbe b/gcc/config/alpha/t-crtbe deleted file mode 100755 index 5e82b92..0000000 --- a/gcc/config/alpha/t-crtbe +++ /dev/null @@ -1,9 +0,0 @@ -# Effectively disable the crtbegin/end rules using crtstuff.c -T = disable - -# Assemble startup files. -crtbegin.o: $(srcdir)/config/alpha/crtbegin.asm $(GCC_PASSES) - $(GCC_FOR_TARGET) -c -o crtbegin.o -x assembler $(srcdir)/config/alpha/crtbegin.asm - -crtend.o: $(srcdir)/config/alpha/crtend.asm $(GCC_PASSES) - $(GCC_FOR_TARGET) -c -o crtend.o -x assembler $(srcdir)/config/alpha/crtend.asm diff --git a/gcc/config/alpha/t-linux b/gcc/config/alpha/t-linux deleted file mode 100755 index f488477..0000000 --- a/gcc/config/alpha/t-linux +++ /dev/null @@ -1,5 +0,0 @@ -# Do not build libgcc1. Let gcc generate those functions. The GNU/Linux -# C library can handle them. -LIBGCC1 = -CROSS_LIBGCC1 = -LIBGCC1_TEST = diff --git a/gcc/config/alpha/t-vms b/gcc/config/alpha/t-vms deleted file mode 100755 index 12ac240..0000000 --- a/gcc/config/alpha/t-vms +++ /dev/null @@ -1,6 +0,0 @@ -# Do not build libgcc1. -LIBGCC1 = -CROSS_LIBGCC1 = - -LIB2FUNCS_EXTRA = tramp.s - diff --git a/gcc/config/alpha/va_list.h b/gcc/config/alpha/va_list.h deleted file mode 100755 index c9ab2b0..0000000 --- a/gcc/config/alpha/va_list.h +++ /dev/null @@ -1,16 +0,0 @@ -/* A replacement for Digital Unix's . */ - -#include - -#if !defined(_VA_LIST) && !defined(_HIDDEN_VA_LIST) -#define _VA_LIST -typedef __gnuc_va_list va_list; - -#elif defined(_HIDDEN_VA_LIST) && !defined(_HIDDEN_VA_LIST_DONE) -#define _HIDDEN_VA_LIST_DONE -typedef __gnuc_va_list __va_list; - -#elif defined(_HIDDEN_VA_LIST) && defined(_VA_LIST) -#undef _HIDDEN_VA_LIST - -#endif diff --git a/gcc/config/alpha/vms-tramp.asm b/gcc/config/alpha/vms-tramp.asm deleted file mode 100755 index fce9ec5..0000000 --- a/gcc/config/alpha/vms-tramp.asm +++ /dev/null @@ -1,22 +0,0 @@ -;# New Alpha OpenVMS trampoline -;# - .set noreorder - .set volatile - .set noat - .file 1 "tramp.s" -.text - .align 3 - .globl __tramp - .ent __tramp -__tramp..en: - -.link - .align 3 -__tramp: - .pdesc __tramp..en,null -.text - ldq $1,24($27) - ldq $27,16($27) - ldq $28,8($27) - jmp $31,($28),0 - .end __tramp diff --git a/gcc/config/alpha/vms.h b/gcc/config/alpha/vms.h deleted file mode 100755 index 44cf5bf..0000000 --- a/gcc/config/alpha/vms.h +++ /dev/null @@ -1,510 +0,0 @@ -/* Output variables, constants and external declarations, for GNU compiler. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define OPEN_VMS 1 - -/* This enables certain macros in alpha.h, which will make an indirect - reference to an external symbol an invalid address. This needs to be - defined before we include alpha.h, since it determines which macros - are used for GO_IF_*. */ - -#define NO_EXTERNAL_INDIRECT_ADDRESS - -#include "alpha/alpha.h" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES \ -"-D__ALPHA -Dvms -DVMS -D__vms__ -D__VMS__ -Asystem(vms)" - -#undef CPP_SUBTARGET_SPEC -#define CPP_SUBTARGET_SPEC "\ -%{mfloat-ieee:-D__IEEE_FLOAT} \ -%{mfloat-vax:-D__G_FLOAT} \ -%{!mfloat-vax:-D__IEEE_FLOAT}" - -/* Under OSF4, -p and -pg require -lprof1, and -lprof1 requires -lpdf. */ - -#define LIB_SPEC "%{p:-lprof1 -lpdf} %{pg:-lprof1 -lpdf} %{a:-lprof2} -lc" - -/* Pass "-G 8" to ld because Alpha's CC does. Pass -O3 if we are - optimizing, -O1 if we are not. Pass -shared, -non_shared or - -call_shared as appropriate. Also pass -pg. */ -#define LINK_SPEC \ - "-G 8 %{O*:-O3} %{!O*:-O1} %{static:-non_shared} \ - %{!static:%{shared:-shared} %{!shared:-call_shared}} %{pg} %{taso} \ - %{rpath*}" - -/* We allow $'s in identifiers unless -ansi is used .. */ - -#define DOLLARS_IN_IDENTIFIERS 2 - -/* These match the definitions used in DECCRTL, the VMS C run-time library - -#define SIZE_TYPE "unsigned int" -#define PTRDIFF_TYPE "int" -*/ - -/* Use memcpy for structure copying, and so forth. */ -#define TARGET_MEM_FUNCTIONS - -/* By default, allow $ to be part of an identifier. */ -#define DOLLARS_IN_IDENTIFIERS 2 - -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_FP|MASK_FPREGS|MASK_GAS) -#undef TARGET_OPEN_VMS -#define TARGET_OPEN_VMS 1 - -#undef TARGET_NAME -#define TARGET_NAME "OpenVMS/Alpha" -#undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (%s)", TARGET_NAME); - -/* The structure return address arrives as an "argument" on VMS. */ -#undef STRUCT_VALUE_REGNUM -#define STRUCT_VALUE 0 -#undef PCC_STATIC_STRUCT_RETURN - -/* no floating emulation. */ -#undef REAL_ARITHMETIC - -/* "long" is 32 bits. */ -#undef LONG_TYPE_SIZE -#define LONG_TYPE_SIZE 32 - -/* Pointer is 32 bits but the hardware has 64-bit addresses, sign extended. */ -#undef POINTER_SIZE -#define POINTER_SIZE 32 -#define POINTERS_EXTEND_UNSIGNED 0 - -#define MAX_OFILE_ALIGNMENT 524288 /* 8 x 2^16 by DEC Ada Test CD40VRA */ - -#undef FIXED_REGISTERS -#define FIXED_REGISTERS \ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1 } - -#undef CALL_USED_REGISTERS -#define CALL_USED_REGISTERS \ - {1, 1, 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, 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 } - -#undef HARD_FRAME_POINTER_REGNUM -#define HARD_FRAME_POINTER_REGNUM 29 - -#undef CAN_ELIMINATE -#define CAN_ELIMINATE(FROM, TO) \ -((TO) != STACK_POINTER_REGNUM || ! alpha_using_fp ()) - -#undef INITIAL_ELIMINATION_OFFSET -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ if ((FROM) == FRAME_POINTER_REGNUM) \ - (OFFSET) = alpha_sa_size () + alpha_pv_save_size (); \ - else if ((FROM) == ARG_POINTER_REGNUM) \ - (OFFSET) = (ALPHA_ROUND (alpha_sa_size () + alpha_pv_save_size () \ - + get_frame_size () \ - + current_function_pretend_args_size) \ - - current_function_pretend_args_size); \ - if ((TO) == STACK_POINTER_REGNUM) \ - (OFFSET) += ALPHA_ROUND (current_function_outgoing_args_size); \ -} - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. - - On Alpha/VMS, this is a structure that contains the number of - arguments and, for each argument, the datatype of that argument. - - The number of arguments is a number of words of arguments scanned so far. - Thus 6 or more means all following args should go on the stack. */ - -enum avms_arg_type {I64, FF, FD, FG, FS, FT}; -typedef struct {char num_args; enum avms_arg_type atypes[6];} avms_arg_info; - -#undef CUMULATIVE_ARGS -#define CUMULATIVE_ARGS avms_arg_info - -/* 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. */ - -#undef INIT_CUMULATIVE_ARGS -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ - (CUM).num_args = 0; \ - (CUM).atypes[0] = (CUM).atypes[1] = (CUM).atypes[2] = I64; \ - (CUM).atypes[3] = (CUM).atypes[4] = (CUM).atypes[5] = I64; - -/* 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.) */ - -extern enum avms_arg_type alpha_arg_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. - - MODE is the argument's machine mode (or VOIDmode for no more args). - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). - - On Alpha the first 6 words of args are normally in registers - and the rest are pushed. */ - -extern struct rtx_def *alpha_arg_info_reg_val (); -#undef FUNCTION_ARG -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ -((MODE) == VOIDmode ? alpha_arg_info_reg_val (CUM) \ - : ((CUM.num_args) < 6 && ! MUST_PASS_IN_STACK (MODE, TYPE) \ - ? gen_rtx(REG, (MODE), \ - ((CUM).num_args + 16 \ - + ((TARGET_FPREGS \ - && (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \ - || GET_MODE_CLASS (MODE) == MODE_FLOAT)) \ - * 32))) \ - : 0)) - -#undef FUNCTION_ARG_ADVANCE -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - if (MUST_PASS_IN_STACK (MODE, TYPE)) \ - (CUM).num_args += 6; \ - else \ - { \ - if ((CUM).num_args < 6) \ - (CUM).atypes[(CUM).num_args] = alpha_arg_type (MODE); \ - \ - (CUM).num_args += ALPHA_ARG_SIZE (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. */ - -#undef FUNCTION_ARG_PARTIAL_NREGS -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ -((CUM).num_args < 6 && 6 < (CUM).num_args \ - + ALPHA_ARG_SIZE (MODE, TYPE, NAMED) \ - ? 6 - (CUM).num_args : 0) - -/* Perform any needed actions needed for a function that is receiving a - variable number of arguments. - - CUM is as for INIT_CUMULATIVE_ARGS. - - 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. - - For VMS, we allocate space for all 6 arg registers plus a count. - - However, if NO registers need to be saved, don't allocate any space. - This is not only because we won't need the space, but because AP includes - the current_pretend_args_size and we don't want to mess up any - ap-relative addresses already made. */ - -#undef SETUP_INCOMING_VARARGS -#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \ -{ if ((CUM).num_args < 6) \ - { \ - if (! (NO_RTL)) \ - { \ - emit_move_insn (gen_rtx (REG, DImode, 1), \ - virtual_incoming_args_rtx); \ - emit_insn (gen_arg_home ()); \ - } \ - \ - PRETEND_SIZE = 7 * UNITS_PER_WORD; \ - } \ -} - -#undef ASM_FILE_START -#define ASM_FILE_START(FILE) \ -{ \ - alpha_write_verstamp (FILE); \ - fprintf (FILE, "\t.set noreorder\n"); \ - fprintf (FILE, "\t.set volatile\n"); \ - ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ -} - -#undef ASM_OUTPUT_FLOAT -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ - { \ - if (REAL_VALUE_ISINF (VALUE) \ - || REAL_VALUE_ISNAN (VALUE) \ - || REAL_VALUE_MINUS_ZERO (VALUE)) \ - { \ - long t; \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ - } \ - else \ - { \ - char str[30]; \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ - fprintf (FILE, "\t.%c_floating %s\n", (TARGET_FLOAT_VAX)?'f':'s', str); \ - } \ - } - -#define LINK_SECTION_ASM_OP ".link" -#define READONLY_SECTION_ASM_OP ".rdata" -#define LITERALS_SECTION_ASM_OP ".literals" -#define CTORS_SECTION_ASM_OP ".ctors" -#define DTORS_SECTION_ASM_OP ".dtors" - -#undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_link, in_rdata, in_literals, in_ctors, in_dtors - -#undef EXTRA_SECTION_FUNCTIONS -#define EXTRA_SECTION_FUNCTIONS \ -void \ -readonly_section () \ -{ \ - if (in_section != in_rdata) \ - { \ - fprintf (asm_out_file, "%s\n", READONLY_SECTION_ASM_OP); \ - in_section = in_rdata; \ - } \ -} \ -void \ -link_section () \ -{ \ - if (in_section != in_link) \ - { \ - fprintf (asm_out_file, "%s\n", LINK_SECTION_ASM_OP); \ - in_section = in_link; \ - } \ -} \ -void \ -literals_section () \ -{ \ - if (in_section != in_literals) \ - { \ - fprintf (asm_out_file, "%s\n", LITERALS_SECTION_ASM_OP); \ - in_section = in_literals; \ - } \ -} \ -void \ -ctors_section () \ -{ \ - if (in_section != in_ctors) \ - { \ - fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ - in_section = in_ctors; \ - } \ -} \ -void \ -dtors_section () \ -{ \ - if (in_section != in_dtors) \ - { \ - fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ - in_section = in_dtors; \ - } \ -} - -#undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) abort () - -#undef ASM_OUTPUT_ADDR_VEC_ELT -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.quad $L%d\n", (VALUE)) - -#undef READONLY_DATA_SECTION -#define READONLY_DATA_SECTION readonly_section - -#define ASM_FILE_END(FILE) alpha_write_linkage (FILE); - -#undef CASE_VECTOR_MODE -#define CASE_VECTOR_MODE DImode -#undef CASE_VECTOR_PC_RELATIVE - -#undef ASM_OUTPUT_CASE_LABEL -#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \ -{ ASM_OUTPUT_ALIGN (FILE, 3); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); } - -/* This says how to output assembler code to declare an - uninitialized external linkage data object. */ - -#define COMMON_ASM_OP ".comm" - -#undef ASM_OUTPUT_ALIGNED_COMMON -#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ -do { \ - fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \ - assemble_name ((FILE), (NAME)); \ - fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ -} while (0) - -#define NO_MD_PROTOTYPES - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. - - The trampoline should set the static chain pointer to value placed - into the trampoline and should branch to the specified routine. - Note that $27 has been set to the address of the trampoline, so we can - use it for addressability of the two data items. Trampolines are always - aligned to FUNCTION_BOUNDARY, which is 64 bits. */ - -#undef TRAMPOLINE_TEMPLATE -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - fprintf (FILE, "\t.quad 0\n"); \ - fprintf (FILE, "\t.linkage __tramp\n"); \ - fprintf (FILE, "\t.quad 0\n"); \ -} - -/* Length in units of the trampoline for entering a nested function. */ - -#undef TRAMPOLINE_SIZE -#define TRAMPOLINE_SIZE 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. */ - -#undef INITIALIZE_TRAMPOLINE -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ - alpha_initialize_trampoline (TRAMP, FNADDR, CXT, 16, 24, -1) - -/* A C statement (sans semicolon) to output an element in the table of - global constructors. */ -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - ctors_section (); \ - fprintf (FILE, "\t.quad "); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - dtors_section (); \ - fprintf (FILE, "\t.quad "); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, NAME, ARGS) \ - (vms_valid_decl_attribute_p (DECL, ATTRIBUTES, NAME, ARGS)) -extern int vms_valid_decl_attribute_p (); - -#undef SDB_DEBUGGING_INFO -#undef MIPS_DEBUGGING_INFO -#undef DBX_DEBUGGING_INFO - -#define DWARF2_DEBUGGING_INFO - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#undef ASM_OUTPUT_ALIGN -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - fprintf (FILE, "\t.align %d\n", LOG); - -#define UNALIGNED_SHORT_ASM_OP ".word" -#define UNALIGNED_INT_ASM_OP ".long" -#define UNALIGNED_DOUBLE_INT_ASM_OP ".quad" - -#define ASM_OUTPUT_SECTION(FILE,SECTION) \ - (strcmp (SECTION, ".text") == 0) \ - ? text_section () \ - : named_section (NULL_TREE, SECTION, 0), \ - ASM_OUTPUT_ALIGN (FILE, 0) \ - -#define ASM_OUTPUT_SECTION_NAME(FILE,DECL,NAME,RELOC) \ - do \ - { \ - char *flags; \ - int ovr = 0; \ - if (DECL && DECL_MACHINE_ATTRIBUTES (DECL) \ - && lookup_attribute \ - ("overlaid", DECL_MACHINE_ATTRIBUTES (DECL))) \ - flags = ",OVR", ovr = 1; \ - else if (strncmp (NAME,".debug", 6) == 0) \ - flags = ",NOWRT"; \ - else \ - flags = ""; \ - fputc ('\n', (FILE)); \ - fprintf (FILE, ".section\t%s%s\n", NAME, flags); \ - if (ovr) \ - (NAME) = ""; \ - } while (0) - -#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \ - do { literals_section(); \ - fprintf ((FILE), "\t"); \ - assemble_name (FILE, LABEL1); \ - fprintf (FILE, " = "); \ - assemble_name (FILE, LABEL2); \ - fprintf (FILE, "\n"); \ - } while (0) - -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG - -#undef ASM_FORMAT_PRIVATE_NAME -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \ - sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO))) - -/* ??? VMS uses different linkage. */ -#undef ASM_OUTPUT_MI_THUNK - -#undef ASM_SPEC -#undef ASM_FINAL_SPEC -#undef LINK_SPEC -#undef STARTFILE_SPEC -#define ASM_SPEC "-nocpp %{pg}" -#define LINK_SPEC "%{g3:-g3} %{g0:-g0} %{shared:-shared} %{v:-v}" - -/* Define the names of the division and modulus functions. */ -#define DIVSI3_LIBCALL "OTS$DIV_I" -#define DIVDI3_LIBCALL "OTS$DIV_L" -#define UDIVSI3_LIBCALL "OTS$DIV_UI" -#define UDIVDI3_LIBCALL "OTS$DIV_UL" -#define MODSI3_LIBCALL "OTS$REM_I" -#define MODDI3_LIBCALL "OTS$REM_L" -#define UMODSI3_LIBCALL "OTS$REM_UI" -#define UMODDI3_LIBCALL "OTS$REM_UL" - -#define DIR_SEPARATOR ']' - -#define PREFIX "GNU_ROOT:" diff --git a/gcc/config/alpha/vxworks.h b/gcc/config/alpha/vxworks.h deleted file mode 100755 index 6dee4b3..0000000 --- a/gcc/config/alpha/vxworks.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Definitions of target machine for GNU compiler. Vxworks Alpha version. - Copyright (C) 1998 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* This file just exists to give specs for the Alpha running on VxWorks. */ - -#undef CPP_SUBTARGET_SPEC -#define CPP_SUBTARGET_SPEC "\ -%{mvxsim:-DCPU=SIMALPHADUNIX} \ -%{!mvxsim: %{!mcpu*|mcpu=21064:-DCPU=21064} %{mcpu=21164:-DCPU=21164}} \ -%{posix: -D_POSIX_SOURCE}" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "\ --D__vxworks -D__alpha_vxworks -Asystem(vxworks) \ --Asystem(embedded) -D_LONGLONG" - -/* VxWorks does all the library stuff itself. */ - -#undef LIB_SPEC -#define LIB_SPEC "" - -/* VxWorks uses object files, not loadable images. make linker just - combine objects. */ - -#undef LINK_SPEC -#define LINK_SPEC "-r" - -/* VxWorks provides the functionality of crt0.o and friends itself. */ - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "" - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "" diff --git a/gcc/config/alpha/win-nt.h b/gcc/config/alpha/win-nt.h deleted file mode 100755 index a3aa275..0000000 --- a/gcc/config/alpha/win-nt.h +++ /dev/null @@ -1,129 +0,0 @@ -/* Definitions of target machine for GNU compiler, for DEC Alpha - running Windows/NT. - Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS) - -#undef TARGET_WINDOWS_NT -#define TARGET_WINDOWS_NT 1 - -/* Names to predefine in the preprocessor for this target machine. */ - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-DWIN32 -D_WIN32 -DWINNT -D__STDC__=0 -DALMOST_STDC \ --D_M_ALPHA -D_ALPHA_ -D_LONGLONG -D__unaligned= -D__stdcall= -Asystem(winnt)" - -#undef ASM_SPEC -#undef ASM_FINAL_SPEC -#define ASM_SPEC "-nopp -nologo %{g:-Zi}" - -/* Pointer is 32 bits but the hardware has 64-bit addresses, sign extended. */ -#undef POINTER_SIZE -#define POINTER_SIZE 32 -#define POINTERS_EXTEND_UNSIGNED 0 - -/* "long" is 32 bits. */ -#undef LONG_TYPE_SIZE -#define LONG_TYPE_SIZE 32 - -#undef WCHAR_TYPE -#define WCHAR_TYPE "short unsigned int" -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 - -/* We can't do any debugging. */ -#undef SDB_DEBUGGING_INFO -#undef DBX_DEBUGGING_INFO -#undef MIPS_DEBUGGING_INFO - -#include "winnt/win-nt.h" - -#undef ASM_FILE_START -#define ASM_FILE_START(FILE) \ -{ \ - alpha_write_verstamp (FILE); \ - fprintf (FILE, "\t.set noreorder\n"); \ - fprintf (FILE, "\t.set volatile\n"); \ - fprintf (FILE, "\t.set noat\n"); \ - fprintf (FILE, "\t.globl\t__fltused\n"); \ - ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \ -} - -#undef LIB_SPEC -#define LIB_SPEC "%{mwindows:-subsystem windows -e _WinMainCRTStartup \ - USER32.LIB%s GDI32.LIB%s COMDLG32.LIB%s WINSPOOL.LIB%s} \ - %{!mwindows:-subsystem console -e _mainCRTStartup} \ - %{mcrtmt:LIBCMT.LIB%s KERNEL32.LIB%s} %{!mcrtmt:LIBC.LIB%s KERNEL32.LIB%s} \ - %{v}" - - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. - - The trampoline should set the static chain pointer to value placed - into the trampoline and should branch to the specified routine. */ - -#undef TRAMPOLINE_TEMPLATE -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - fprintf (FILE, "\tbr $27,$LTRAMPP\n"); \ - fprintf (FILE, "$LTRAMPP:\n\tldl $1,12($27)\n"); \ - fprintf (FILE, "\tldl $27,16($27)\n"); \ - fprintf (FILE, "\tjmp $31,($27),0\n"); \ - fprintf (FILE, "\t.long 0,0\n"); \ -} - -/* Length in units of the trampoline for entering a nested function. */ - -#undef TRAMPOLINE_SIZE -#define TRAMPOLINE_SIZE 24 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -#undef INITIALIZE_TRAMPOLINE -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ - alpha_initialize_trampoline (TRAMP, FNADDR, CXT, 16, 20, 12) - -/* Output code to add DELTA to the first argument, and then jump to FUNCTION. - Used for C++ multiple inheritance. */ - -#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \ -do { \ - char *op, *fn_name = XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0); \ - int reg; \ - \ - /* Mark end of prologue. */ \ - output_end_prologue (FILE); \ - \ - /* Rely on the assembler to macro expand a large delta. */ \ - reg = aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) ? 17 : 16; \ - fprintf (FILE, "\tlda $%d,%ld($%d)\n", reg, (long)(DELTA), reg); \ - \ - op = "jsr"; \ - if (current_file_function_operand (XEXP (DECL_RTL (FUNCTION), 0))) \ - op = "br"; \ - fprintf (FILE, "\t%s $31,", op); \ - assemble_name (FILE, fn_name); \ - fputc ('\n', FILE); \ -} while (0) diff --git a/gcc/config/alpha/x-alpha b/gcc/config/alpha/x-alpha deleted file mode 100755 index 9686ab9..0000000 --- a/gcc/config/alpha/x-alpha +++ /dev/null @@ -1,2 +0,0 @@ -CLIB=-lmld -EXTRA_HEADERS = $(srcdir)/config/alpha/va_list.h diff --git a/gcc/config/alpha/xm-alpha.h b/gcc/config/alpha/xm-alpha.h deleted file mode 100755 index 7665127..0000000 --- a/gcc/config/alpha/xm-alpha.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Configuration for GNU C-compiler for DEC Alpha. - Copyright (C) 1990, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu). - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 8 -#define HOST_BITS_PER_SHORT 16 -#define HOST_BITS_PER_INT 32 -#define HOST_BITS_PER_LONG 64 -#define HOST_BITS_PER_LONGLONG 64 - -/* #define HOST_WORDS_BIG_ENDIAN */ - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* If compiled with GNU C, use the builtin alloca. */ -#ifndef alloca -#if defined(__GNUC__) && !defined(USE_C_ALLOCA) -#define alloca __builtin_alloca -#else -#if !defined(_WIN32) && !defined(USE_C_ALLOCA) && !defined(OPEN_VMS) -#include -#else -extern void *alloca (); -#endif -#endif -#endif - -/* The host compiler has problems with enum bitfields since it makes - them signed so we can't fit all our codes in. */ - -#ifndef __GNUC__ -#define ONLY_INT_FIELDS -#endif - -/* Declare some functions needed for this machine. We don't want to - include these in the sources since other machines might define them - differently. */ - -extern void *malloc (), *realloc (), *calloc (); - -#ifndef inhibit_libc -#include "string.h" -#endif - -/* OSF/1 is POSIX.1 compliant. */ - -#define POSIX diff --git a/gcc/config/alpha/xm-linux.h b/gcc/config/alpha/xm-linux.h deleted file mode 100755 index b85269b..0000000 --- a/gcc/config/alpha/xm-linux.h +++ /dev/null @@ -1,2 +0,0 @@ -#undef USE_BFD -#define USE_BFD diff --git a/gcc/config/alpha/xm-vms.h b/gcc/config/alpha/xm-vms.h deleted file mode 100755 index 472a225..0000000 --- a/gcc/config/alpha/xm-vms.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Configuration for GNU C-compiler for openVMS/Alpha. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. - Contributed by Klaus Kaempf (kkaempf@progis.de). - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* If compiling with DECC, need to fix problem with - which defines a macro called FILE_TYPE that breaks "tree.h". - Fortunately it uses #ifndef to suppress multiple inclusions. - Three possible cases: - 1) has already been included -- ours will be no-op; - 2) will be included after us -- "theirs" will be no-op; - 3) isn't needed -- including it here shouldn't hurt. - In all three cases, the problem macro will be removed here. */ - -#include -#include -#include -#ifdef __DECC -#undef FILE_TYPE -#endif - -#undef HOST_BITS_PER_LONG -#define HOST_BITS_PER_LONG 32 - -#define HOST_WIDE_INT long long -#define HOST_BITS_PER_WIDE_INT 64 - -#undef SUCCESS_EXIT_CODE -#define SUCCESS_EXIT_CODE 1 -#undef FATAL_EXIT_CODE -#define FATAL_EXIT_CODE (44 | 0x10000000) /* Abort, and no DCL message. */ - -/* A couple of conditionals for execution machine are controlled here. */ -#ifndef VMS -#define VMS -#endif - -#define GCC_INCLUDE_DIR "" -/* Specify the list of include file directories. */ -#define INCLUDE_DEFAULTS \ -{ \ - { "GNU_GXX_INCLUDE:", "G++", 1, 1 }, \ - { "GNU_CC_INCLUDE:", "GCC", 0, 0 }, \ - { ".", 0, 0, 1 }, \ - { 0, 0, 0, 0 } \ -} - -/* Define a local equivalent (sort of) for unlink */ -#define unlink remove - -#define NEED_ATEXIT -#define HAVE_VPRINTF -#define HAVE_PUTENV -#define HAVE_STRERROR -#define HAVE_ATOLL - -#define NO_SYS_PARAMS_H /* Don't have */ -#define USE_C_ALLOCA /* Using alloca.c */ - -#define HAVE_FCNTL_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_UNISTD_H 1 -#define HAVE_STRING_H 1 -#define HAVE_LIMITS_H 1 -#define HAVE_STDDEF_H 1 -#define HAVE_TIME_H 1 -#define STDC_HEADERS 1 -#define HAVE_CPP_STRINGIFY 1 - -#if __STDC__ -extern void *alloca (size_t); -#else -extern char *alloca (unsigned int); -#endif - -#define OBJECT_SUFFIX ".obj" -#define EXECUTABLE_SUFFIX ".exe" diff --git a/gcc/config/alpha/xm-winnt.h b/gcc/config/alpha/xm-winnt.h deleted file mode 100755 index f84be8d..0000000 --- a/gcc/config/alpha/xm-winnt.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Configuration for GNU compiler for an Alpha running Windows NT 3.x. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - Contributed by Douglas B. Rupp (drupp@cs.washington.edu) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef HOST_BITS_PER_LONG -#define HOST_BITS_PER_LONG 32 - -#undef POSIX - -#define access _access -#define close _close -#define mktemp _mktemp -#define open _open -#define read _read -#define write _write - -#undef HAS_INIT_SECTION diff --git a/gcc/config/aoutos.h b/gcc/config/aoutos.h deleted file mode 100755 index e9caa71..0000000 --- a/gcc/config/aoutos.h +++ /dev/null @@ -1,88 +0,0 @@ -/* aoutos.h -- operating system specific defines to be used when - targeting GCC for some system that uses a.out file format. - Copyright (C) 1992 Free Software Foundation, Inc. - - Written by Ron Guilmette (rfg@netcom.com). - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* To use this file, make up a file with a name like: - - ?????aout.h - - where ????? is replaced by the name of the basic hardware that you - are targeting for. Then, in the file ?????aout.h, put something - like: - - #include "?????.h" - #include "aoutos.h" - - followed by any really system-specific defines (or overrides of - defines) which you find that you need. Now, modify the configure - or configure.in script to properly use the new ?????aout.h file - when configuring for the system. */ - -/* Define a symbol indicating that we are using aoutos.h. */ -#define USING_AOUTOS_H - -/* A C statement (sans semicolon) to output an element in the table of - global constructors. - If using GNU LD, tell it that this is part of the static destructor set. - This code works for any machine provided you use GNU as/ld. - If not using GNU LD, rely on a "collect" program to look for names defined - in the particular form we choose as global constructor function names. */ - -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - if (flag_gnu_linker) \ - { \ - /* Output an N_SETT (0x16, 22.) for the name. */ \ - fprintf (FILE, "%s \"___CTOR_LIST__\",22,0,0,", ASM_STABS_OP); \ - assemble_name (FILE, NAME); \ - fputc ('\n', FILE); \ - } \ - } while (0) - - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ - -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - if (flag_gnu_linker) \ - { \ - /* Output an N_SETT (0x16, 22.) for the name. */ \ - fprintf (FILE, "%s \"___DTOR_LIST__\",22,0,0,", ASM_STABS_OP); \ - assemble_name (FILE, NAME); \ - fputc ('\n', FILE); \ - } \ - } while (0) - -/* Likewise for entries we want to record for garbage collection. - Garbage collection is still under development. */ - -#define ASM_OUTPUT_GC_ENTRY(FILE,NAME) \ - do { \ - if (flag_gnu_linker) \ - { \ - /* Output an N_SETT (0x16, 22.) for the name. */ \ - fprintf (FILE, "%s \"___PTR_LIST__\",22,0,0,", ASM_STABS_OP); \ - assemble_name (FILE, NAME); \ - fputc ('\n', FILE); \ - } \ - } while (0) diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c deleted file mode 100755 index 64aec44..0000000 --- a/gcc/config/arc/arc.c +++ /dev/null @@ -1,2203 +0,0 @@ -/* Subroutines used for code generation on the Argonaut ARC cpu. - Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* ??? This is an old port, and is undoubtedly suffering from bit rot. */ - -#include -#include "config.h" -#include "tree.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "expr.h" -#include "recog.h" - -/* Which cpu we're compiling for (NULL(=base), ???). */ -char *arc_cpu_string; -int arc_cpu_type; - -/* Name of mangle string to add to symbols to separate code compiled for each - cpu (or NULL). */ -char *arc_mangle_cpu; - -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ -rtx arc_compare_op0, arc_compare_op1; - -/* Name of text, data, and rodata sections, as specified on command line. - Selected by -m{text,data,rodata} flags. */ -char *arc_text_string = ARC_DEFAULT_TEXT_SECTION; -char *arc_data_string = ARC_DEFAULT_DATA_SECTION; -char *arc_rodata_string = ARC_DEFAULT_RODATA_SECTION; - -/* Name of text, data, and rodata sections used in varasm.c. */ -char *arc_text_section; -char *arc_data_section; -char *arc_rodata_section; - -/* Array of valid operand punctuation characters. */ -char arc_punct_chars[256]; - -/* Variables used by arc_final_prescan_insn to implement conditional - execution. */ -static int arc_ccfsm_state; -static int arc_ccfsm_current_cc; -static rtx arc_ccfsm_target_insn; -static int arc_ccfsm_target_label; - -/* The maximum number of insns skipped which will be conditionalised if - possible. */ -#define MAX_INSNS_SKIPPED 3 - -/* A nop is needed between a 4 byte insn that sets the condition codes and - a branch that uses them (the same isn't true for an 8 byte insn that sets - the condition codes). Set by arc_final_prescan_insn. Used by - arc_print_operand. */ -static int last_insn_set_cc_p; -static int current_insn_set_cc_p; -static void record_cc_ref (); - -void arc_init_reg_tables (); - -/* Called by OVERRIDE_OPTIONS to initialize various things. */ - -void -arc_init (void) -{ - if (arc_cpu_string == 0 - || !strcmp (arc_cpu_string, "base")) - { - /* Ensure we have a printable value for the .cpu pseudo-op. */ - arc_cpu_string = "base"; - arc_cpu_type = 0; - arc_mangle_cpu = NULL; - } - else if (ARC_EXTENSION_CPU (arc_cpu_string)) - ; /* nothing to do */ - else - { - error ("bad value (%s) for -mcpu switch", arc_cpu_string); - arc_cpu_string = "base"; - arc_cpu_type = 0; - arc_mangle_cpu = NULL; - } - - /* Set the pseudo-ops for the various standard sections. */ - arc_text_section = xmalloc (strlen (arc_text_string) + sizeof (ARC_SECTION_FORMAT) + 1); - sprintf (arc_text_section, ARC_SECTION_FORMAT, arc_text_string); - arc_data_section = xmalloc (strlen (arc_data_string) + sizeof (ARC_SECTION_FORMAT) + 1); - sprintf (arc_data_section, ARC_SECTION_FORMAT, arc_data_string); - arc_rodata_section = xmalloc (strlen (arc_rodata_string) + sizeof (ARC_SECTION_FORMAT) + 1); - sprintf (arc_rodata_section, ARC_SECTION_FORMAT, arc_rodata_string); - - arc_init_reg_tables (); - - /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */ - memset (arc_punct_chars, 0, sizeof (arc_punct_chars)); - arc_punct_chars['#'] = 1; - arc_punct_chars['*'] = 1; - arc_punct_chars['?'] = 1; - arc_punct_chars['!'] = 1; - arc_punct_chars['~'] = 1; -} - -/* The condition codes of the ARC, and the inverse function. */ -static char *arc_condition_codes[] = -{ - "al", 0, "eq", "ne", "p", "n", "c", "nc", "v", "nv", - "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0 -}; - -#define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1) - -/* Returns the index of the ARC condition code string in - `arc_condition_codes'. COMPARISON should be an rtx like - `(eq (...) (...))'. */ - -static int -get_arc_condition_code (comparison) - rtx comparison; -{ - switch (GET_CODE (comparison)) - { - case EQ : return 2; - case NE : return 3; - case GT : return 10; - case LE : return 11; - case GE : return 12; - case LT : return 13; - case GTU : return 14; - case LEU : return 15; - case LTU : return 6; - case GEU : return 7; - default : abort (); - } - /*NOTREACHED*/ - return (42); -} - -/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, - return the mode to be used for the comparison. */ - -enum machine_mode -arc_select_cc_mode (op, x, y) - enum rtx_code op; - rtx x, y; -{ - switch (op) - { - case EQ : - case NE : - return CCZNmode; - default : - switch (GET_CODE (x)) - { - case AND : - case IOR : - case XOR : - case SIGN_EXTEND : - case ZERO_EXTEND : - return CCZNmode; - case ASHIFT : - case ASHIFTRT : - case LSHIFTRT : - return CCZNCmode; - } - } - return CCmode; -} - -/* Vectors to keep interesting information about registers where it can easily - be got. We use to use the actual mode value as the bit number, but there - is (or may be) more than 32 modes now. Instead we use two tables: one - indexed by hard register number, and one indexed by mode. */ - -/* The purpose of arc_mode_class is to shrink the range of modes so that - they all fit (as bit numbers) in a 32 bit word (again). Each real mode is - mapped into one arc_mode_class mode. */ - -enum arc_mode_class { - C_MODE, - S_MODE, D_MODE, T_MODE, O_MODE, - SF_MODE, DF_MODE, TF_MODE, OF_MODE -}; - -/* Modes for condition codes. */ -#define C_MODES (1 << (int) C_MODE) - -/* Modes for single-word and smaller quantities. */ -#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE)) - -/* Modes for double-word and smaller quantities. */ -#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE)) - -/* Modes for quad-word and smaller quantities. */ -#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE)) - -/* Value is 1 if register/mode pair is acceptable on arc. */ - -unsigned int arc_hard_regno_mode_ok[] = { - T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, - T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, - T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES, - D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, - - /* ??? Leave these as S_MODES for now. */ - S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, - S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, - S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, - S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES -}; - -unsigned int arc_mode_class [NUM_MACHINE_MODES]; - -enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER]; - -void -arc_init_reg_tables () -{ - int i; - - for (i = 0; i < NUM_MACHINE_MODES; i++) - { - switch (GET_MODE_CLASS (i)) - { - case MODE_INT: - case MODE_PARTIAL_INT: - case MODE_COMPLEX_INT: - if (GET_MODE_SIZE (i) <= 4) - arc_mode_class[i] = 1 << (int) S_MODE; - else if (GET_MODE_SIZE (i) == 8) - arc_mode_class[i] = 1 << (int) D_MODE; - else if (GET_MODE_SIZE (i) == 16) - arc_mode_class[i] = 1 << (int) T_MODE; - else if (GET_MODE_SIZE (i) == 32) - arc_mode_class[i] = 1 << (int) O_MODE; - else - arc_mode_class[i] = 0; - break; - case MODE_FLOAT: - case MODE_COMPLEX_FLOAT: - if (GET_MODE_SIZE (i) <= 4) - arc_mode_class[i] = 1 << (int) SF_MODE; - else if (GET_MODE_SIZE (i) == 8) - arc_mode_class[i] = 1 << (int) DF_MODE; - else if (GET_MODE_SIZE (i) == 16) - arc_mode_class[i] = 1 << (int) TF_MODE; - else if (GET_MODE_SIZE (i) == 32) - arc_mode_class[i] = 1 << (int) OF_MODE; - else - arc_mode_class[i] = 0; - break; - case MODE_CC: - default: - /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so - we must explicitly check for them here. */ - if (i == (int) CCmode || i == (int) CCZNmode || i == (int) CCZNCmode) - arc_mode_class[i] = 1 << (int) C_MODE; - else - arc_mode_class[i] = 0; - break; - } - } - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - { - if (i < 60) - arc_regno_reg_class[i] = GENERAL_REGS; - else if (i == 60) - arc_regno_reg_class[i] = LPCOUNT_REG; - else if (i == 61) - arc_regno_reg_class[i] = NO_REGS /* CC_REG: must be NO_REGS */; - else - arc_regno_reg_class[i] = NO_REGS; - } -} - -/* ARC specific attribute support. - - The ARC has these attributes: - interrupt - for interrupt functions -*/ - -/* Return nonzero if IDENTIFIER is a valid decl attribute. */ - -int -arc_valid_machine_decl_attribute (type, attributes, identifier, args) - tree type; - tree attributes; - tree identifier; - tree args; -{ - if (identifier == get_identifier ("__interrupt__") - && list_length (args) == 1 - && TREE_CODE (TREE_VALUE (args)) == STRING_CST) - { - tree value = TREE_VALUE (args); - - if (!strcmp (TREE_STRING_POINTER (value), "ilink1") - || !strcmp (TREE_STRING_POINTER (value), "ilink2")) - return 1; - } - return 0; -} - -/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible, - and two if they are nearly compatible (which causes a warning to be - generated). */ - -int -arc_comp_type_attributes (type1, type2) - tree type1, type2; -{ - return 1; -} - -/* Set the default attributes for TYPE. */ - -void -arc_set_default_type_attributes (type) - tree type; -{ -} - -/* Acceptable arguments to the call insn. */ - -int -call_address_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (symbolic_operand (op, mode) - || (GET_CODE (op) == CONST_INT && LEGITIMATE_CONSTANT_P (op)) - || (GET_CODE (op) == REG)); -} - -int -call_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - return call_address_operand (op, mode); -} - -/* Returns 1 if OP is a symbol reference. */ - -int -symbolic_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF: - case LABEL_REF: - case CONST : - return 1; - default: - return 0; - } -} - -/* Return truth value of statement that OP is a symbolic memory - operand of mode MODE. */ - -int -symbolic_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST - || GET_CODE (op) == LABEL_REF); -} - -/* Return true if OP is a short immediate (shimm) value. */ - -int -short_immediate_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != CONST_INT) - return 0; - return SMALL_INT (INTVAL (op)); -} - -/* Return true if OP will require a long immediate (limm) value. - This is currently only used when calculating length attributes. */ - -int -long_immediate_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF : - case LABEL_REF : - case CONST : - return 1; - case CONST_INT : - return !SMALL_INT (INTVAL (op)); - case CONST_DOUBLE : - /* These can happen because large unsigned 32 bit constants are - represented this way (the multiplication patterns can cause these - to be generated). They also occur for SFmode values. */ - return 1; - } - return 0; -} - -/* Return true if OP is a MEM that when used as a load or store address will - require an 8 byte insn. - Load and store instructions don't allow the same possibilities but they're - similar enough that this one function will do. - This is currently only used when calculating length attributes. */ - -int -long_immediate_loadstore_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case SYMBOL_REF : - case LABEL_REF : - case CONST : - return 1; - case CONST_INT : - /* This must be handled as "st c,[limm]". Ditto for load. - Technically, the assembler could translate some possibilities to - "st c,[limm/2 + limm/2]" if limm/2 will fit in a shimm, but we don't - assume that it does. */ - return 1; - case CONST_DOUBLE : - /* These can happen because large unsigned 32 bit constants are - represented this way (the multiplication patterns can cause these - to be generated). They also occur for SFmode values. */ - return 1; - case REG : - return 0; - case PLUS : - if (GET_CODE (XEXP (op, 1)) == CONST_INT - && !SMALL_INT (INTVAL (XEXP (op, 1)))) - return 1; - return 0; - } - return 0; -} - -/* Return true if OP is an acceptable argument for a single word - move source. */ - -int -move_src_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF : - case LABEL_REF : - case CONST : - return 1; - case CONST_INT : - return (LARGE_INT (INTVAL (op))); - case CONST_DOUBLE : - /* We can handle DImode integer constants in SImode if the value - (signed or unsigned) will fit in 32 bits. This is needed because - large unsigned 32 bit constants are represented as CONST_DOUBLEs. */ - if (mode == SImode) - return arc_double_limm_p (op); - /* We can handle 32 bit floating point constants. */ - if (mode == SFmode) - return GET_MODE (op) == SFmode; - return 0; - case REG : - return register_operand (op, mode); - case SUBREG : - /* (subreg (mem ...) ...) can occur here if the inner part was once a - pseudo-reg and is now a stack slot. */ - if (GET_CODE (SUBREG_REG (op)) == MEM) - return address_operand (XEXP (SUBREG_REG (op), 0), mode); - else - return register_operand (op, mode); - case MEM : - return address_operand (XEXP (op, 0), mode); - default : - return 0; - } -} - -/* Return true if OP is an acceptable argument for a double word - move source. */ - -int -move_double_src_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case REG : - return register_operand (op, mode); - case SUBREG : - /* (subreg (mem ...) ...) can occur here if the inner part was once a - pseudo-reg and is now a stack slot. */ - if (GET_CODE (SUBREG_REG (op)) == MEM) - return move_double_src_operand (SUBREG_REG (op), mode); - else - return register_operand (op, mode); - case MEM : - /* Disallow auto inc/dec for now. */ - if (GET_CODE (XEXP (op, 0)) == PRE_DEC - || GET_CODE (XEXP (op, 0)) == PRE_INC) - return 0; - return address_operand (XEXP (op, 0), mode); - case CONST_INT : - case CONST_DOUBLE : - return 1; - default : - return 0; - } -} - -/* Return true if OP is an acceptable argument for a move destination. */ - -int -move_dest_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case REG : - return register_operand (op, mode); - case SUBREG : - /* (subreg (mem ...) ...) can occur here if the inner part was once a - pseudo-reg and is now a stack slot. */ - if (GET_CODE (SUBREG_REG (op)) == MEM) - return address_operand (XEXP (SUBREG_REG (op), 0), mode); - else - return register_operand (op, mode); - case MEM : - return address_operand (XEXP (op, 0), mode); - default : - return 0; - } -} - -/* Return true if OP is valid load with update operand. */ - -int -load_update_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM - || GET_MODE (op) != mode) - return 0; - op = XEXP (op, 0); - if (GET_CODE (op) != PLUS - || GET_MODE (op) != Pmode - || !register_operand (XEXP (op, 0), Pmode) - || !nonmemory_operand (XEXP (op, 1), Pmode)) - return 0; - return 1; -} - -/* Return true if OP is valid store with update operand. */ - -int -store_update_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM - || GET_MODE (op) != mode) - return 0; - op = XEXP (op, 0); - if (GET_CODE (op) != PLUS - || GET_MODE (op) != Pmode - || !register_operand (XEXP (op, 0), Pmode) - || !(GET_CODE (XEXP (op, 1)) == CONST_INT - && SMALL_INT (INTVAL (XEXP (op, 1))))) - return 0; - return 1; -} - -/* Return true if OP is a non-volatile non-immediate operand. - Volatile memory refs require a special "cache-bypass" instruction - and only the standard movXX patterns are set up to handle them. */ - -int -nonvol_nonimm_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == MEM && MEM_VOLATILE_P (op)) - return 0; - return nonimmediate_operand (op, mode); -} - -/* Accept integer operands in the range -0x80000000..0x7fffffff. We have - to check the range carefully since this predicate is used in DImode - contexts. */ - -int -const_sint32_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - /* All allowed constants will fit a CONST_INT. */ - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff)); -} - -/* Accept integer operands in the range 0..0xffffffff. We have to check the - range carefully since this predicate is used in DImode contexts. Also, we - need some extra crud to make it work when hosted on 64-bit machines. */ - -int -const_uint32_operand (op, mode) - rtx op; - enum machine_mode mode; -{ -#if HOST_BITS_PER_WIDE_INT > 32 - /* All allowed constants will fit a CONST_INT. */ - return (GET_CODE (op) == CONST_INT - && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL)); -#else - return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0) - || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0)); -#endif -} - -/* Return 1 if OP is a comparison operator valid for the mode of CC. - This allows the use of MATCH_OPERATOR to recognize all the branch insns. - - Some insns only set a few bits in the condition code. So only allow those - comparisons that use the bits that are valid. */ - -int -proper_comparison_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum rtx_code code = GET_CODE (op); - - if (GET_RTX_CLASS (code) != '<') - return 0; - - if (GET_MODE (XEXP (op, 0)) == CCZNmode) - return (code == EQ || code == NE); - if (GET_MODE (XEXP (op, 0)) == CCZNCmode) - return (code == EQ || code == NE - || code == LTU || code == GEU || code == GTU || code == LEU); - return 1; -} - -/* Misc. utilities. */ - -/* X and Y are two things to compare using CODE. Emit the compare insn and - return the rtx for the cc reg in the proper mode. */ - -rtx -gen_compare_reg (code, x, y) - enum rtx_code code; - rtx x, y; -{ - enum machine_mode mode = SELECT_CC_MODE (code, x, y); - rtx cc_reg; - - cc_reg = gen_rtx (REG, mode, 61); - - emit_insn (gen_rtx (SET, VOIDmode, cc_reg, - gen_rtx (COMPARE, mode, x, y))); - - return cc_reg; -} - -/* Return 1 if VALUE, a const_double, will fit in a limm (4 byte number). - We assume the value can be either signed or unsigned. */ - -int -arc_double_limm_p (value) - rtx value; -{ - HOST_WIDE_INT low, high; - - if (GET_CODE (value) != CONST_DOUBLE) - abort (); - - low = CONST_DOUBLE_LOW (value); - high = CONST_DOUBLE_HIGH (value); - - if (low & 0x80000000) - { - return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0) - || (((low & - (unsigned HOST_WIDE_INT) 0x80000000) - == - (unsigned HOST_WIDE_INT) 0x80000000) - && high == -1)); - } - else - { - return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0; - } -} - -/* Do any needed setup for a variadic function. For the ARC, we must - create a register parameter block, and then copy any anonymous arguments - in registers to memory. - - CUM has not been updated for the last named argument which has type TYPE - and mode MODE, and we rely on this fact. - - We do things a little weird here. We're supposed to only allocate space - for the anonymous arguments. However we need to keep the stack eight byte - aligned. So we round the space up if necessary, and leave it to va-arc.h - to compensate. */ - -void -arc_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int *pretend_size; - int no_rtl; -{ - int first_anon_arg; - - /* All BLKmode values are passed by reference. */ - if (mode == BLKmode) - abort (); - - /* We must treat `__builtin_va_alist' as an anonymous arg. */ - if (current_function_varargs) - first_anon_arg = *cum; - else - first_anon_arg = *cum + ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) - / UNITS_PER_WORD); - - if (first_anon_arg < MAX_ARC_PARM_REGS && !no_rtl) - { - /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */ - int first_reg_offset = first_anon_arg; - /* Size in words to "pretend" allocate. */ - int size = MAX_ARC_PARM_REGS - first_reg_offset; - /* Extra slop to keep stack eight byte aligned. */ - int align_slop = size & 1; - rtx regblock; - - regblock = gen_rtx (MEM, BLKmode, - plus_constant (arg_pointer_rtx, - FIRST_PARM_OFFSET (0) - + align_slop * UNITS_PER_WORD)); - move_block_from_reg (first_reg_offset, regblock, - MAX_ARC_PARM_REGS - first_reg_offset, - ((MAX_ARC_PARM_REGS - first_reg_offset) - * UNITS_PER_WORD)); - - *pretend_size = ((MAX_ARC_PARM_REGS - first_reg_offset + align_slop) - * UNITS_PER_WORD); - } -} - -/* Cost functions. */ - -/* Provide the costs of an addressing mode that contains ADDR. - If ADDR is not a valid address, its cost is irrelevant. */ - -int -arc_address_cost (addr) - rtx addr; -{ - switch (GET_CODE (addr)) - { - case REG : - /* This is handled in the macro that calls us. - It's here for documentation. */ - return 1; - - case LABEL_REF : - case SYMBOL_REF : - case CONST : - return 2; - - case PLUS : - { - register rtx plus0 = XEXP (addr, 0); - register rtx plus1 = XEXP (addr, 1); - - if (GET_CODE (plus0) != REG) - break; - - switch (GET_CODE (plus1)) - { - case CONST_INT : - return SMALL_INT (plus1) ? 1 : 2; - case CONST : - case SYMBOL_REF : - case LABEL_REF : - return 2; - default: - break; - } - break; - } - } - - return 4; -} - -/* Function prologue/epilogue handlers. */ - -/* ARC stack frames look like: - - Before call After call - +-----------------------+ +-----------------------+ - | | | | - high | local variables, | | local variables, | - mem | reg save area, etc. | | reg save area, etc. | - | | | | - +-----------------------+ +-----------------------+ - | | | | - | arguments on stack. | | arguments on stack. | - | | | | - SP+16->+-----------------------+FP+48->+-----------------------+ - | 4 word save area for | | reg parm save area, | - | return addr, prev %fp | | only created for | - SP+0->+-----------------------+ | variable argument | - | functions | - FP+16->+-----------------------+ - | 4 word save area for | - | return addr, prev %fp | - FP+0->+-----------------------+ - | | - | local variables | - | | - +-----------------------+ - | | - | register save area | - | | - +-----------------------+ - | | - | alloca allocations | - | | - +-----------------------+ - | | - | arguments on stack | - | | - SP+16->+-----------------------+ - low | 4 word save area for | - memory | return addr, prev %fp | - SP+0->+-----------------------+ - -Notes: -1) The "reg parm save area" does not exist for non variable argument fns. - The "reg parm save area" can be eliminated completely if we created our - own va-arc.h, but that has tradeoffs as well (so it's not done). */ - -/* Structure to be filled in by arc_compute_frame_size with register - save masks, and offsets for the current function. */ -struct arc_frame_info -{ - unsigned int total_size; /* # bytes that the entire frame takes up. */ - unsigned int extra_size; /* # bytes of extra stuff. */ - unsigned int pretend_size; /* # bytes we push and pretend caller did. */ - unsigned int args_size; /* # bytes that outgoing arguments take up. */ - unsigned int reg_size; /* # bytes needed to store regs. */ - unsigned int var_size; /* # bytes that variables take up. */ - unsigned int reg_offset; /* Offset from new sp to store regs. */ - unsigned int gmask; /* Mask of saved gp registers. */ - int initialized; /* Nonzero if frame size already calculated. */ -}; - -/* Current frame information calculated by arc_compute_frame_size. */ -static struct arc_frame_info current_frame_info; - -/* Zero structure to initialize current_frame_info. */ -static struct arc_frame_info zero_frame_info; - -/* Type of function DECL. - - The result is cached. To reset the cache at the end of a function, - call with DECL = NULL_TREE. */ - -enum arc_function_type -arc_compute_function_type (decl) - tree decl; -{ - tree a; - /* Cached value. */ - static enum arc_function_type fn_type = ARC_FUNCTION_UNKNOWN; - /* Last function we were called for. */ - static tree last_fn = NULL_TREE; - - /* Resetting the cached value? */ - if (decl == NULL_TREE) - { - fn_type = ARC_FUNCTION_UNKNOWN; - last_fn = NULL_TREE; - return fn_type; - } - - if (decl == last_fn && fn_type != ARC_FUNCTION_UNKNOWN) - return fn_type; - - /* Assume we have a normal function (not an interrupt handler). */ - fn_type = ARC_FUNCTION_NORMAL; - - /* Now see if this is an interrupt handler. */ - for (a = DECL_MACHINE_ATTRIBUTES (current_function_decl); - a; - a = TREE_CHAIN (a)) - { - tree name = TREE_PURPOSE (a), args = TREE_VALUE (a); - - if (name == get_identifier ("__interrupt__") - && list_length (args) == 1 - && TREE_CODE (TREE_VALUE (args)) == STRING_CST) - { - tree value = TREE_VALUE (args); - - if (!strcmp (TREE_STRING_POINTER (value), "ilink1")) - fn_type = ARC_FUNCTION_ILINK1; - else if (!strcmp (TREE_STRING_POINTER (value), "ilink2")) - fn_type = ARC_FUNCTION_ILINK2; - else - abort (); - break; - } - } - - last_fn = decl; - return fn_type; -} - -#define ILINK1_REGNUM 29 -#define ILINK2_REGNUM 30 -#define RETURN_ADDR_REGNUM 31 -#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) -#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) - -/* Tell prologue and epilogue if register REGNO should be saved / restored. - The return address and frame pointer are treated separately. - Don't consider them here. */ -#define MUST_SAVE_REGISTER(regno, interrupt_p) \ -((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \ - && (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_p))) - -#define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM]) - -/* Return the bytes needed to compute the frame pointer from the current - stack pointer. - - SIZE is the size needed for local variables. */ - -unsigned int -arc_compute_frame_size (size) - int size; /* # of var. bytes allocated. */ -{ - int regno; - unsigned int total_size, var_size, args_size, pretend_size, extra_size; - unsigned int reg_size, reg_offset; - unsigned int gmask; - enum arc_function_type fn_type; - int interrupt_p; - - var_size = size; - args_size = current_function_outgoing_args_size; - pretend_size = current_function_pretend_args_size; - extra_size = FIRST_PARM_OFFSET (0); - total_size = extra_size + pretend_size + args_size + var_size; - reg_offset = FIRST_PARM_OFFSET(0) + current_function_outgoing_args_size; - reg_size = 0; - gmask = 0; - - /* See if this is an interrupt handler. Call used registers must be saved - for them too. */ - fn_type = arc_compute_function_type (current_function_decl); - interrupt_p = ARC_INTERRUPT_P (fn_type); - - /* Calculate space needed for registers. - ??? We ignore the extension registers for now. */ - - for (regno = 0; regno <= 31; regno++) - { - if (MUST_SAVE_REGISTER (regno, interrupt_p)) - { - reg_size += UNITS_PER_WORD; - gmask |= 1 << regno; - } - } - - total_size += reg_size; - - /* If the only space to allocate is the fp/blink save area this is an - empty frame. However, if we'll be making a function call we need to - allocate a stack frame for our callee's fp/blink save area. */ - if (total_size == extra_size - && !MUST_SAVE_RETURN_ADDR) - total_size = extra_size = 0; - - total_size = ARC_STACK_ALIGN (total_size); - - /* Save computed information. */ - current_frame_info.total_size = total_size; - current_frame_info.extra_size = extra_size; - current_frame_info.pretend_size = pretend_size; - current_frame_info.var_size = var_size; - current_frame_info.args_size = args_size; - current_frame_info.reg_size = reg_size; - current_frame_info.reg_offset = reg_offset; - current_frame_info.gmask = gmask; - current_frame_info.initialized = reload_completed; - - /* Ok, we're done. */ - return total_size; -} - -/* Common code to save/restore registers. */ - -void -arc_save_restore (file, base_reg, offset, gmask, op) - FILE *file; - char *base_reg; - unsigned int offset; - unsigned int gmask; - char *op; -{ - int regno; - - if (gmask == 0) - return; - - for (regno = 0; regno <= 31; regno++) - { - if ((gmask & (1L << regno)) != 0) - { - fprintf (file, "\t%s %s,[%s,%d]\n", - op, reg_names[regno], base_reg, offset); - offset += UNITS_PER_WORD; - } - } -} - -/* Set up the stack and frame pointer (if desired) for the function. */ - -void -arc_output_function_prologue (file, size) - FILE *file; - int size; -{ - char *sp_str = reg_names[STACK_POINTER_REGNUM]; - char *fp_str = reg_names[FRAME_POINTER_REGNUM]; - unsigned int gmask = current_frame_info.gmask; - enum arc_function_type fn_type = arc_compute_function_type (current_function_decl); - - /* If this is an interrupt handler, set up our stack frame. - ??? Optimize later. */ - if (ARC_INTERRUPT_P (fn_type)) - { - fprintf (file, "\t%s interrupt handler\n", - ASM_COMMENT_START); - fprintf (file, "\tsub %s,%s,16\n", sp_str, sp_str); - } - - /* This is only for the human reader. */ - fprintf (file, "\t%s BEGIN PROLOGUE %s vars= %d, regs= %d, args= %d, extra= %d\n", - ASM_COMMENT_START, ASM_COMMENT_START, - current_frame_info.var_size, - current_frame_info.reg_size / 4, - current_frame_info.args_size, - current_frame_info.extra_size); - - size = ARC_STACK_ALIGN (size); - size = (! current_frame_info.initialized - ? arc_compute_frame_size (size) - : current_frame_info.total_size); - - /* These cases shouldn't happen. Catch them now. */ - if (size == 0 && gmask) - abort (); - - /* Allocate space for register arguments if this is a variadic function. */ - if (current_frame_info.pretend_size != 0) - fprintf (file, "\tsub %s,%s,%d\n", - sp_str, sp_str, current_frame_info.pretend_size); - - /* The home-grown ABI says link register is saved first. */ - if (MUST_SAVE_RETURN_ADDR) - fprintf (file, "\tst %s,[%s,%d]\n", - reg_names[RETURN_ADDR_REGNUM], sp_str, UNITS_PER_WORD); - - /* Set up the previous frame pointer next (if we need to). */ - if (frame_pointer_needed) - { - fprintf (file, "\tst %s,[%s]\n", fp_str, sp_str); - fprintf (file, "\tmov %s,%s\n", fp_str, sp_str); - } - - /* ??? We don't handle the case where the saved regs are more than 252 - bytes away from sp. This can be handled by decrementing sp once, saving - the regs, and then decrementing it again. The epilogue doesn't have this - problem as the `ld' insn takes reg+limm values (though it would be more - efficient to avoid reg+limm). */ - - /* Allocate the stack frame. */ - if (size - current_frame_info.pretend_size > 0) - fprintf (file, "\tsub %s,%s,%d\n", - sp_str, sp_str, size - current_frame_info.pretend_size); - - /* Save any needed call-saved regs (and call-used if this is an - interrupt handler). */ - arc_save_restore (file, sp_str, current_frame_info.reg_offset, - /* The zeroing of these two bits is unnecessary, - but leave this in for clarity. */ - gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), - "st"); - - fprintf (file, "\t%s END PROLOGUE\n", ASM_COMMENT_START); -} - -/* Do any necessary cleanup after a function to restore stack, frame, - and regs. */ - -void -arc_output_function_epilogue (file, size) - FILE *file; - int size; -{ - rtx epilogue_delay = current_function_epilogue_delay_list; - int noepilogue = FALSE; - enum arc_function_type fn_type = arc_compute_function_type (current_function_decl); - - /* This is only for the human reader. */ - fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START); - - size = ARC_STACK_ALIGN (size); - size = (!current_frame_info.initialized - ? arc_compute_frame_size (size) - : current_frame_info.total_size); - - if (size == 0 && epilogue_delay == 0) - { - rtx insn = get_last_insn (); - - /* If the last insn was a BARRIER, we don't have to write any code - because a jump (aka return) was put there. */ - if (GET_CODE (insn) == NOTE) - insn = prev_nonnote_insn (insn); - if (insn && GET_CODE (insn) == BARRIER) - noepilogue = TRUE; - } - - if (!noepilogue) - { - unsigned int pretend_size = current_frame_info.pretend_size; - unsigned int frame_size = size - pretend_size; - int restored, fp_restored_p; - int can_trust_sp_p = !current_function_calls_alloca; - char *sp_str = reg_names[STACK_POINTER_REGNUM]; - char *fp_str = reg_names[FRAME_POINTER_REGNUM]; - - /* ??? There are lots of optimizations that can be done here. - EG: Use fp to restore regs if it's closer. - Maybe in time we'll do them all. For now, always restore regs from - sp, but don't restore sp if we don't have to. */ - - if (!can_trust_sp_p) - { - if (!frame_pointer_needed) - abort (); - fprintf (file,"\tsub %s,%s,%d\t\t%s sp not trusted here\n", - sp_str, fp_str, frame_size, ASM_COMMENT_START); - } - - /* Restore any saved registers. */ - arc_save_restore (file, sp_str, current_frame_info.reg_offset, - /* The zeroing of these two bits is unnecessary, - but leave this in for clarity. */ - current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), - "ld"); - - if (MUST_SAVE_RETURN_ADDR) - fprintf (file, "\tld %s,[%s,%d]\n", - reg_names[RETURN_ADDR_REGNUM], - frame_pointer_needed ? fp_str : sp_str, - UNITS_PER_WORD + (frame_pointer_needed ? 0 : frame_size)); - - /* Keep track of how much of the stack pointer we've restored. - It makes the following a lot more readable. */ - restored = 0; - fp_restored_p = 0; - - /* We try to emit the epilogue delay slot insn right after the load - of the return address register so that it can execute with the - stack intact. Secondly, loads are delayed. */ - /* ??? If stack intactness is important, always emit now. */ - if (MUST_SAVE_RETURN_ADDR && epilogue_delay != NULL_RTX) - { - final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1); - epilogue_delay = NULL_RTX; - } - - if (frame_pointer_needed) - { - /* Try to restore the frame pointer in the delay slot. We can't, - however, if any of these is true. */ - if (epilogue_delay != NULL_RTX - || !SMALL_INT (frame_size) - || pretend_size - || ARC_INTERRUPT_P (fn_type)) - { - /* Note that we restore fp and sp here! */ - fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size); - restored += frame_size; - fp_restored_p = 1; - } - } - else if (!SMALL_INT (size /* frame_size + pretend_size */) - || ARC_INTERRUPT_P (fn_type)) - { - fprintf (file, "\tadd %s,%s,%d\n", sp_str, sp_str, frame_size); - restored += frame_size; - } - - /* These must be done before the return insn because the delay slot - does the final stack restore. */ - if (ARC_INTERRUPT_P (fn_type)) - { - if (epilogue_delay) - { - final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1); - } - } - - /* Emit the return instruction. */ - { - static int regs[4] = { - 0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM - }; - fprintf (file, "\tj.d %s\n", reg_names[regs[fn_type]]); - } - - /* If the only register saved is the return address, we need a - nop, unless we have an instruction to put into it. Otherwise - we don't since reloading multiple registers doesn't reference - the register being loaded. */ - - if (ARC_INTERRUPT_P (fn_type)) - fprintf (file, "\tadd %s,%s,16\n", sp_str, sp_str); - else if (epilogue_delay != NULL_RTX) - { - if (frame_pointer_needed && !fp_restored_p) - abort (); - if (restored < size) - abort (); - final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1); - } - else if (frame_pointer_needed && !fp_restored_p) - { - if (!SMALL_INT (frame_size)) - abort (); - /* Note that we restore fp and sp here! */ - fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size); - } - else if (restored < size) - { - if (!SMALL_INT (size - restored)) - abort (); - fprintf (file, "\tadd %s,%s,%d\n", - sp_str, sp_str, size - restored); - } - else - fprintf (file, "\tnop\n"); - } - - /* Reset state info for each function. */ - current_frame_info = zero_frame_info; - arc_compute_function_type (NULL_TREE); -} - -/* Define the number of delay slots needed for the function epilogue. - - Interrupt handlers can't have any epilogue delay slots (it's always needed - for something else, I think). For normal functions, we have to worry about - using call-saved regs as they'll be restored before the delay slot insn. - Functions with non-empty frames already have enough choices for the epilogue - delay slot so for now we only consider functions with empty frames. */ - -int -arc_delay_slots_for_epilogue () -{ - if (arc_compute_function_type (current_function_decl) != ARC_FUNCTION_NORMAL) - return 0; - if (!current_frame_info.initialized) - (void) arc_compute_frame_size (get_frame_size ()); - if (current_frame_info.total_size == 0) - return 1; - return 0; -} - -/* Return true if TRIAL is a valid insn for the epilogue delay slot. - Any single length instruction which doesn't reference the stack or frame - pointer or any call-saved register is OK. SLOT will always be 0. */ - -int -arc_eligible_for_epilogue_delay (trial, slot) - rtx trial; - int slot; -{ - if (slot != 0) - abort (); - - if (get_attr_length (trial) == 1 - /* If registers where saved, presumably there's more than enough - possibilities for the delay slot. The alternative is something - more complicated (of course, if we expanded the epilogue as rtl - this problem would go away). */ - /* ??? Note that this will always be true since only functions with - empty frames have epilogue delay slots. See - arc_delay_slots_for_epilogue. */ - && current_frame_info.gmask == 0 - && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial)) - && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial))) - return 1; - return 0; -} - -/* PIC */ - -/* Emit special PIC prologues and epilogues. */ - -void -arc_finalize_pic () -{ - /* nothing to do */ -} - -/* Return true if OP is a shift operator. */ - -int -shift_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case ASHIFTRT: - case LSHIFTRT: - case ASHIFT: - return 1; - default: - return 0; - } -} - -/* Output the assembler code for doing a shift. - We go to a bit of trouble to generate efficient code as the ARC only has - single bit shifts. This is taken from the h8300 port. We only have one - mode of shifting and can't access individual bytes like the h8300 can, so - this is greatly simplified (at the expense of not generating hyper- - efficient code). - - This function is not used if the variable shift insns are present. */ - -/* ??? We assume the output operand is the same as operand 1. - This can be optimized (deleted) in the case of 1 bit shifts. */ -/* ??? We use the loop register here. We don't use it elsewhere (yet) and - using it here will give us a chance to play with it. */ - -char * -output_shift (operands) - rtx *operands; -{ - static int loopend_lab; - rtx shift = operands[3]; - enum machine_mode mode = GET_MODE (shift); - enum rtx_code code = GET_CODE (shift); - char *shift_one; - - if (mode != SImode) - abort (); - - switch (code) - { - case ASHIFT: shift_one = "asl %0,%0"; break; - case ASHIFTRT: shift_one = "asr %0,%0"; break; - case LSHIFTRT: shift_one = "lsr %0,%0"; break; - default: abort (); - } - - if (GET_CODE (operands[2]) != CONST_INT) - { - if (optimize) - output_asm_insn ("mov lp_count,%2", operands); - else - output_asm_insn ("mov %4,%2", operands); - goto shiftloop; - } - else - { - int n = INTVAL (operands[2]); - - /* If the count is negative, make it 0. */ - if (n < 0) - n = 0; - /* If the count is too big, truncate it. - ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to - do the intuitive thing. */ - else if (n > GET_MODE_BITSIZE (mode)) - n = GET_MODE_BITSIZE (mode); - - /* First see if we can do them inline. */ - if (n <= 8) - { - while (--n >= 0) - output_asm_insn (shift_one, operands); - } - /* See if we can use a rotate/and. */ - else if (n == BITS_PER_WORD - 1) - { - switch (code) - { - case ASHIFT : - output_asm_insn ("and %0,%0,1\n\tror %0,%0", operands); - break; - case ASHIFTRT : - /* The ARC doesn't have a rol insn. Use something else. */ - output_asm_insn ("asl.f 0,%0\n\tsbc %0,0,0", operands); - break; - case LSHIFTRT : - /* The ARC doesn't have a rol insn. Use something else. */ - output_asm_insn ("asl.f 0,%0\n\tadc %0,0,0", operands); - break; - } - } - /* Must loop. */ - else - { - char buf[100]; - - if (optimize) - output_asm_insn ("mov lp_count,%c2", operands); - else - output_asm_insn ("mov %4,%c2", operands); - shiftloop: - if (optimize) - { - if (flag_pic) - sprintf ("lr %%4,[status]\n\tadd %%4,%%4,6\t%s single insn loop start", - ASM_COMMENT_START); - else - sprintf (buf, "mov %%4,%%%%st(1f)\t%s (single insn loop start) >> 2", - ASM_COMMENT_START); - output_asm_insn (buf, operands); - output_asm_insn ("sr %4,[lp_start]", operands); - output_asm_insn ("add %4,%4,1", operands); - output_asm_insn ("sr %4,[lp_end]", operands); - output_asm_insn ("nop\n\tnop", operands); - if (flag_pic) - asm_fprintf (asm_out_file, "\t%s single insn loop\n", - ASM_COMMENT_START); - else - asm_fprintf (asm_out_file, "1:\t%s single insn loop\n", - ASM_COMMENT_START); - output_asm_insn (shift_one, operands); - } - else - { - asm_fprintf (asm_out_file, "1:\t%s begin shift loop\n", - ASM_COMMENT_START); - output_asm_insn ("sub.f %4,%4,1", operands); - output_asm_insn ("nop", operands); - output_asm_insn ("bn.nd 2f", operands); - output_asm_insn (shift_one, operands); - output_asm_insn ("b.nd 1b", operands); - asm_fprintf (asm_out_file, "2:\t%s end shift loop\n", - ASM_COMMENT_START); - } - } - } - - return ""; -} - -/* Nested function support. */ - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -void -arc_initialize_trampoline (tramp, fnaddr, cxt) - rtx tramp, fnaddr, cxt; -{ -} - -/* Set the cpu type and print out other fancy things, - at the top of the file. */ - -void -arc_asm_file_start (file) - FILE *file; -{ - fprintf (file, "\t.cpu %s\n", arc_cpu_string); -} - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. */ - -void -arc_print_operand (file, x, code) - FILE *file; - rtx x; - int code; -{ - switch (code) - { - case '#' : - /* Conditional branches. For now these are equivalent. */ - case '*' : - /* Unconditional branches. Output the appropriate delay slot suffix. */ - if (!final_sequence || XVECLEN (final_sequence, 0) == 1) - { - /* There's nothing in the delay slot. */ - fputs (".nd", file); - } - else - { - rtx jump = XVECEXP (final_sequence, 0, 0); - rtx delay = XVECEXP (final_sequence, 0, 1); - if (INSN_ANNULLED_BRANCH_P (jump)) - fputs (INSN_FROM_TARGET_P (delay) ? ".jd" : ".nd", file); - else - fputs (".d", file); - } - return; - case '?' : /* with leading "." */ - case '!' : /* without leading "." */ - /* This insn can be conditionally executed. See if the ccfsm machinery - says it should be conditionalized. */ - if (arc_ccfsm_state == 3 || arc_ccfsm_state == 4) - { - /* Is this insn in a delay slot? */ - if (final_sequence && XVECLEN (final_sequence, 0) == 2) - { - rtx insn = XVECEXP (final_sequence, 0, 1); - - /* If the insn is annulled and is from the target path, we need - to inverse the condition test. */ - if (INSN_ANNULLED_BRANCH_P (insn)) - { - if (INSN_FROM_TARGET_P (insn)) - fprintf (file, "%s%s", - code == '?' ? "." : "", - arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc)]); - else - fprintf (file, "%s%s", - code == '?' ? "." : "", - arc_condition_codes[arc_ccfsm_current_cc]); - } - else - /* This insn is executed for either path, so don't - conditionalize it at all. */ - ; /* nothing to do */ - } - else - { - /* This insn isn't in a delay slot. */ - fprintf (file, "%s%s", - code == '?' ? "." : "", - arc_condition_codes[arc_ccfsm_current_cc]); - } - } - return; - case '~' : - /* Output a nop if we're between a set of the condition codes, - and a conditional branch. */ - if (last_insn_set_cc_p) - fputs ("nop\n\t", file); - return; - case 'd' : - fputs (arc_condition_codes[get_arc_condition_code (x)], file); - return; - case 'D' : - fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE - (get_arc_condition_code (x))], - file); - return; - case 'R' : - /* Write second word of DImode or DFmode reference, - register or memory. */ - if (GET_CODE (x) == REG) - fputs (reg_names[REGNO (x)+1], file); - else if (GET_CODE (x) == MEM) - { - fputc ('[', file); - /* Handle possible auto-increment. Since it is pre-increment and - we have already done it, we can just use an offset of four. */ - /* ??? This is taken from rs6000.c I think. I don't think it is - currently necessary, but keep it around. */ - if (GET_CODE (XEXP (x, 0)) == PRE_INC - || GET_CODE (XEXP (x, 0)) == PRE_DEC) - output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4)); - else - output_address (plus_constant (XEXP (x, 0), 4)); - fputc (']', file); - } - else - output_operand_lossage ("invalid operand to %R code"); - return; - case 'S' : - if ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x)) - || GET_CODE (x) == LABEL_REF) - { - fprintf (file, "%%st("); - output_addr_const (file, x); - fprintf (file, ")"); - return; - } - break; - case 'H' : - case 'L' : - if (GET_CODE (x) == REG) - { - /* L = least significant word, H = most significant word */ - if ((TARGET_BIG_ENDIAN != 0) ^ (code == 'L')) - fputs (reg_names[REGNO (x)], file); - else - fputs (reg_names[REGNO (x)+1], file); - } - else if (GET_CODE (x) == CONST_INT - || GET_CODE (x) == CONST_DOUBLE) - { - rtx first, second; - - split_double (x, &first, &second); - fprintf (file, "0x%08lx", - code == 'L' ? INTVAL (first) : INTVAL (second)); - } - else - output_operand_lossage ("invalid operand to %H/%L code"); - return; - case 'A' : - { - REAL_VALUE_TYPE d; - char str[30]; - - if (GET_CODE (x) != CONST_DOUBLE - || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT) - abort (); - REAL_VALUE_FROM_CONST_DOUBLE (d, x); - REAL_VALUE_TO_DECIMAL (d, "%.20e", str); - fprintf (file, "%s", str); - return; - } - case 'U' : - /* Output a load/store with update indicator if appropriate. */ - if (GET_CODE (x) == MEM) - { - if (GET_CODE (XEXP (x, 0)) == PRE_INC - || GET_CODE (XEXP (x, 0)) == PRE_DEC) - fputs (".a", file); - } - else - output_operand_lossage ("invalid operand to %U code"); - return; - case 'V' : - /* Output cache bypass indicator for a load/store insn. Volatile memory - refs are defined to use the cache bypass mechanism. */ - if (GET_CODE (x) == MEM) - { - if (MEM_VOLATILE_P (x)) - fputs (".di", file); - } - else - output_operand_lossage ("invalid operand to %V code"); - return; - case 0 : - /* Do nothing special. */ - break; - default : - /* Unknown flag. */ - output_operand_lossage ("invalid operand output code"); - } - - switch (GET_CODE (x)) - { - case REG : - fputs (reg_names[REGNO (x)], file); - break; - case MEM : - fputc ('[', file); - if (GET_CODE (XEXP (x, 0)) == PRE_INC) - output_address (plus_constant (XEXP (XEXP (x, 0), 0), - GET_MODE_SIZE (GET_MODE (x)))); - else if (GET_CODE (XEXP (x, 0)) == PRE_DEC) - output_address (plus_constant (XEXP (XEXP (x, 0), 0), - - GET_MODE_SIZE (GET_MODE (x)))); - else - output_address (XEXP (x, 0)); - fputc (']', file); - break; - case CONST_DOUBLE : - /* We handle SFmode constants here as output_addr_const doesn't. */ - if (GET_MODE (x) == SFmode) - { - REAL_VALUE_TYPE d; - long l; - - REAL_VALUE_FROM_CONST_DOUBLE (d, x); - REAL_VALUE_TO_TARGET_SINGLE (d, l); - fprintf (file, "0x%08lx", l); - break; - } - /* Fall through. Let output_addr_const deal with it. */ - default : - output_addr_const (file, x); - break; - } -} - -/* Print a memory address as an operand to reference that memory location. */ - -void -arc_print_operand_address (file, addr) - FILE *file; - rtx addr; -{ - register rtx base, index = 0; - int offset = 0; - - switch (GET_CODE (addr)) - { - case REG : - fputs (reg_names[REGNO (addr)], file); - break; - case SYMBOL_REF : - if (/*???*/ 0 && SYMBOL_REF_FLAG (addr)) - { - fprintf (file, "%%st("); - output_addr_const (file, addr); - fprintf (file, ")"); - } - else - output_addr_const (file, addr); - break; - case PLUS : - if (GET_CODE (XEXP (addr, 0)) == CONST_INT) - offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1); - else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) - offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0); - else - base = XEXP (addr, 0), index = XEXP (addr, 1); - if (GET_CODE (base) != REG) - abort (); - fputs (reg_names[REGNO (base)], file); - if (index == 0) - { - if (offset != 0) - fprintf (file, ",%d", offset); - } - else if (GET_CODE (index) == REG) - fprintf (file, ",%s", reg_names[REGNO (index)]); - else if (GET_CODE (index) == SYMBOL_REF) - fputc (',', file), output_addr_const (file, index); - else - abort (); - break; - case PRE_INC : - case PRE_DEC : - /* We shouldn't get here as we've lost the mode of the memory object - (which says how much to inc/dec by. */ - abort (); - break; - default : - output_addr_const (file, addr); - break; - } -} - -/* Update compare/branch separation marker. */ - -static void -record_cc_ref (insn) - rtx insn; -{ - last_insn_set_cc_p = current_insn_set_cc_p; - - switch (get_attr_cond (insn)) - { - case COND_SET : - case COND_SET_ZN : - case COND_SET_ZNC : - if (get_attr_length (insn) == 1) - current_insn_set_cc_p = 1; - else - current_insn_set_cc_p = 0; - break; - default : - current_insn_set_cc_p = 0; - break; - } -} - -/* Conditional execution support. - - This is based on the ARM port but for now is much simpler. - - A finite state machine takes care of noticing whether or not instructions - can be conditionally executed, and thus decrease execution time and code - size by deleting branch instructions. The fsm is controlled by - final_prescan_insn, and controls the actions of PRINT_OPERAND. The patterns - in the .md file for the branch insns also have a hand in this. */ - -/* The state of the fsm controlling condition codes are: - 0: normal, do nothing special - 1: don't output this insn - 2: don't output this insn - 3: make insns conditional - 4: make insns conditional - - State transitions (state->state by whom, under what condition): - 0 -> 1 final_prescan_insn, if insn is conditional branch - 0 -> 2 final_prescan_insn, if the `target' is an unconditional branch - 1 -> 3 branch patterns, after having not output the conditional branch - 2 -> 4 branch patterns, after having not output the conditional branch - 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached - (the target label has CODE_LABEL_NUMBER equal to - arc_ccfsm_target_label). - 4 -> 0 final_prescan_insn, if `target' unconditional branch is reached - - If the jump clobbers the conditions then we use states 2 and 4. - - A similar thing can be done with conditional return insns. - - We also handle separating branches from sets of the condition code. - This is done here because knowledge of the ccfsm state is required, - we may not be outputting the branch. */ - -void -arc_final_prescan_insn (insn, opvec, noperands) - rtx insn; - rtx *opvec; - int noperands; -{ - /* BODY will hold the body of INSN. */ - register rtx body = PATTERN (insn); - - /* This will be 1 if trying to repeat the trick (ie: do the `else' part of - an if/then/else), and things need to be reversed. */ - int reverse = 0; - - /* If we start with a return insn, we only succeed if we find another one. */ - int seeking_return = 0; - - /* START_INSN will hold the insn from where we start looking. This is the - first insn after the following code_label if REVERSE is true. */ - rtx start_insn = insn; - - /* Update compare/branch separation marker. */ - record_cc_ref (insn); - - /* Allow -mdebug-ccfsm to turn this off so we can see how well it does. - We can't do this in macro FINAL_PRESCAN_INSN because its called from - final_scan_insn which has `optimize' as a local. */ - if (optimize < 2 || TARGET_NO_COND_EXEC) - return; - - /* If in state 4, check if the target branch is reached, in order to - change back to state 0. */ - if (arc_ccfsm_state == 4) - { - if (insn == arc_ccfsm_target_insn) - { - arc_ccfsm_target_insn = NULL; - arc_ccfsm_state = 0; - } - return; - } - - /* If in state 3, it is possible to repeat the trick, if this insn is an - unconditional branch to a label, and immediately following this branch - is the previous target label which is only used once, and the label this - branch jumps to is not too far off. Or in other words "we've done the - `then' part, see if we can do the `else' part." */ - if (arc_ccfsm_state == 3) - { - if (simplejump_p (insn)) - { - start_insn = next_nonnote_insn (start_insn); - if (GET_CODE (start_insn) == BARRIER) - { - /* ??? Isn't this always a barrier? */ - start_insn = next_nonnote_insn (start_insn); - } - if (GET_CODE (start_insn) == CODE_LABEL - && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label - && LABEL_NUSES (start_insn) == 1) - reverse = TRUE; - else - return; - } - else if (GET_CODE (body) == RETURN) - { - start_insn = next_nonnote_insn (start_insn); - if (GET_CODE (start_insn) == BARRIER) - start_insn = next_nonnote_insn (start_insn); - if (GET_CODE (start_insn) == CODE_LABEL - && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label - && LABEL_NUSES (start_insn) == 1) - { - reverse = TRUE; - seeking_return = 1; - } - else - return; - } - else - return; - } - - if (GET_CODE (insn) != JUMP_INSN) - return; - - /* This jump might be paralleled with a clobber of the condition codes, - the jump should always come first. */ - if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0) - body = XVECEXP (body, 0, 0); - - if (reverse - || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC - && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE)) - { - int insns_skipped = 0, fail = FALSE, succeed = FALSE; - /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */ - int then_not_else = TRUE; - /* Nonzero if next insn must be the target label. */ - int next_must_be_target_label_p; - rtx this_insn = start_insn, label = 0; - - /* Register the insn jumped to. */ - if (reverse) - { - if (!seeking_return) - label = XEXP (SET_SRC (body), 0); - } - else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF) - label = XEXP (XEXP (SET_SRC (body), 1), 0); - else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF) - { - label = XEXP (XEXP (SET_SRC (body), 2), 0); - then_not_else = FALSE; - } - else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN) - seeking_return = 1; - else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN) - { - seeking_return = 1; - then_not_else = FALSE; - } - else - abort (); - - /* See how many insns this branch skips, and what kind of insns. If all - insns are okay, and the label or unconditional branch to the same - label is not too far away, succeed. */ - for (insns_skipped = 0, next_must_be_target_label_p = FALSE; - !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED; - insns_skipped++) - { - rtx scanbody; - - this_insn = next_nonnote_insn (this_insn); - if (!this_insn) - break; - - if (next_must_be_target_label_p) - { - if (GET_CODE (this_insn) == BARRIER) - continue; - if (GET_CODE (this_insn) == CODE_LABEL - && this_insn == label) - { - arc_ccfsm_state = 1; - succeed = TRUE; - } - else - fail = TRUE; - break; - } - - scanbody = PATTERN (this_insn); - - switch (GET_CODE (this_insn)) - { - case CODE_LABEL: - /* Succeed if it is the target label, otherwise fail since - control falls in from somewhere else. */ - if (this_insn == label) - { - arc_ccfsm_state = 1; - succeed = TRUE; - } - else - fail = TRUE; - break; - - case BARRIER: - /* Succeed if the following insn is the target label. - Otherwise fail. - If return insns are used then the last insn in a function - will be a barrier. */ - next_must_be_target_label_p = TRUE; - break; - - case CALL_INSN: - /* Can handle a call insn if there are no insns after it. - IE: The next "insn" is the target label. We don't have to - worry about delay slots as such insns are SEQUENCE's inside - INSN's. ??? It is possible to handle such insns though. */ - if (get_attr_cond (this_insn) == COND_CANUSE) - next_must_be_target_label_p = TRUE; - else - fail = TRUE; - break; - - case JUMP_INSN: - /* If this is an unconditional branch to the same label, succeed. - If it is to another label, do nothing. If it is conditional, - fail. */ - /* ??? Probably, the test for the SET and the PC are unnecessary. */ - - if (GET_CODE (scanbody) == SET - && GET_CODE (SET_DEST (scanbody)) == PC) - { - if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF - && XEXP (SET_SRC (scanbody), 0) == label && !reverse) - { - arc_ccfsm_state = 2; - succeed = TRUE; - } - else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE) - fail = TRUE; - } - else if (GET_CODE (scanbody) == RETURN - && seeking_return) - { - arc_ccfsm_state = 2; - succeed = TRUE; - } - else if (GET_CODE (scanbody) == PARALLEL) - { - if (get_attr_cond (this_insn) != COND_CANUSE) - fail = TRUE; - } - break; - - case INSN: - /* We can only do this with insns that can use the condition - codes (and don't set them). */ - if (GET_CODE (scanbody) == SET - || GET_CODE (scanbody) == PARALLEL) - { - if (get_attr_cond (this_insn) != COND_CANUSE) - fail = TRUE; - } - /* We can't handle other insns like sequences. */ - else - fail = TRUE; - break; - - default: - break; - } - } - - if (succeed) - { - if ((!seeking_return) && (arc_ccfsm_state == 1 || reverse)) - arc_ccfsm_target_label = CODE_LABEL_NUMBER (label); - else if (seeking_return || arc_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 (); - } - if (!this_insn) - { - /* Oh dear! we ran off the end, give up. */ - insn_extract (insn); - arc_ccfsm_state = 0; - arc_ccfsm_target_insn = NULL; - return; - } - arc_ccfsm_target_insn = this_insn; - } - else - abort (); - - /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from - what it was. */ - if (!reverse) - arc_ccfsm_current_cc = get_arc_condition_code (XEXP (SET_SRC (body), - 0)); - - if (reverse || then_not_else) - arc_ccfsm_current_cc = ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc); - } - - /* Restore recog_operand. 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 - call insn_extract direct. */ - insn_extract (insn); - } -} - -/* Record that we are currently outputting label NUM with prefix PREFIX. - It it's the label we're looking for, reset the ccfsm machinery. - - Called from ASM_OUTPUT_INTERNAL_LABEL. */ - -void -arc_ccfsm_at_label (prefix, num) - char *prefix; - int num; -{ - if (arc_ccfsm_state == 3 && arc_ccfsm_target_label == num - && !strcmp (prefix, "L")) - { - arc_ccfsm_state = 0; - arc_ccfsm_target_insn = NULL_RTX; - } -} - -/* See if the current insn, which is a conditional branch, is to be - deleted. */ - -int -arc_ccfsm_branch_deleted_p () -{ - if (arc_ccfsm_state == 1 || arc_ccfsm_state == 2) - return 1; - return 0; -} - -/* Record a branch isn't output because subsequent insns can be - conditionalized. */ - -void -arc_ccfsm_record_branch_deleted () -{ - /* Indicate we're conditionalizing insns now. */ - arc_ccfsm_state += 2; - - /* If the next insn is a subroutine call, we still need a nop between the - cc setter and user. We need to undo the effect of calling record_cc_ref - for the just deleted branch. */ - current_insn_set_cc_p = last_insn_set_cc_p; -} diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h deleted file mode 100755 index 49d9fe2..0000000 --- a/gcc/config/arc/arc.h +++ /dev/null @@ -1,1642 +0,0 @@ -/* Definitions of target machine for GNU compiler, Argonaut ARC cpu. - Copyright (C) 1994, 1995, 1997, 1998 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* ??? This is an old port, and is undoubtedly suffering from bit rot. */ - -/* Things to do: - - - PREDICATE_CODES - - incscc, decscc? - - print active compiler options in assembler output -*/ - -/* ??? Create elf.h and have svr4.h include it. */ -#include "svr4.h" - -#undef ASM_SPEC -#undef LINK_SPEC -#undef STARTFILE_SPEC -#undef ENDFILE_SPEC -#undef SIZE_TYPE -#undef PTRDIFF_TYPE -#undef WCHAR_TYPE -#undef WCHAR_TYPE_SIZE - -/* Print subsidiary information on the compiler version in use. */ -#define TARGET_VERSION fprintf (stderr, " (arc)") - -/* Names to predefine in the preprocessor for this target machine. */ -#define CPP_PREDEFINES "-Acpu(arc) -Amachine(arc) -D__arc__" - -/* Additional flags for the preprocessor. */ -#define CPP_SPEC "\ -%{!mcpu=*:-D__base__} %{mcpu=base:-D__base__} \ -%{EB:-D__big_endian__} \ -" - -/* Pass -mmangle-cpu if we get -mcpu=*. - Doing it this way lets one have it on as default with -mcpu=*, - but also lets one turn it off with -mno-mangle-cpu. */ -#define CC1_SPEC "\ -%{mcpu=*:-mmangle-cpu} \ -%{EB:%{EL:%emay not use both -EB and -EL}} \ -%{EB:-mbig-endian} %{EL:-mlittle-endian} \ -" - -#define ASM_SPEC "%{v} %{EB} %{EL}" - -#define LINK_SPEC "%{v} %{EB} %{EL}" - -#define STARTFILE_SPEC "%{!shared:crt0.o%s} crtinit.o%s" - -#define ENDFILE_SPEC "crtfini.o%s" - -/* Run-time compilation parameters selecting different hardware subsets. */ - -extern int target_flags; - -/* Mangle all user symbols for the specified cpu. - ARC's can be shipped in which a collection of cpus are coupled together. - Each CPU may be different in some way, and thus we may need to distinguish - code compiled for one to ensure it isn't linked with code compiled for - another. */ -#define TARGET_MASK_MANGLE_CPU 1 -#define TARGET_MANGLE_CPU (target_flags & TARGET_MASK_MANGLE_CPU) - -#if 0 -/* Mangle libgcc symbols by adding a suffix for the specified cpu. */ -#define TARGET_MASK_MANGLE_CPU_LIBGCC 2 -#define TARGET_MANGLE_CPU_LIBGCC (target_flags & TARGET_MASK_MANGLE_CPU_LIBGCC) -#endif - -/* Align loops to 32 byte boundaries (cache line size). */ -#define TARGET_MASK_ALIGN_LOOPS 4 -#define TARGET_ALIGN_LOOPS (target_flags & TARGET_MASK_ALIGN_LOOPS) - -/* Big Endian. */ -#define TARGET_MASK_BIG_ENDIAN 8 -#define TARGET_BIG_ENDIAN (target_flags & TARGET_MASK_BIG_ENDIAN) - -/* Turn off conditional execution optimization, - so we can see how well it does, or in case it's buggy. */ -#define TARGET_MASK_NO_COND_EXEC 0x10 -#define TARGET_NO_COND_EXEC (target_flags & TARGET_MASK_NO_COND_EXEC) - -/* 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 \ -{ \ - { "mangle-cpu", TARGET_MASK_MANGLE_CPU }, \ - { "no-mangle-cpu", -TARGET_MASK_MANGLE_CPU }, \ -/* { "mangle-cpu-libgcc", TARGET_MASK_MANGLE_CPU_LIBGCC }, */ \ -/* { "no-mangle-cpu-libgcc", -TARGET_MASK_MANGLE_CPU_LIBGCC }, */ \ - { "align-loops", TARGET_MASK_ALIGN_LOOPS }, \ - { "no-align-loops", -TARGET_MASK_ALIGN_LOOPS }, \ - { "big-endian", TARGET_MASK_BIG_ENDIAN }, \ - { "little-endian", -TARGET_MASK_BIG_ENDIAN }, \ - { "no-cond-exec", TARGET_MASK_NO_COND_EXEC }, \ - SUBTARGET_SWITCHES \ - { "", TARGET_DEFAULT } \ -} - -#define TARGET_DEFAULT (0) - -#define SUBTARGET_SWITCHES - -/* Instruction set characteristics. - These are internal macros, set by the appropriate -mcpu= option. */ - -/* Non-zero means the cpu has a barrel shifter. */ -#define TARGET_SHIFTER 0 - -/* 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. - - Each subgrouping contains a string constant, that defines the - fixed part of the option name, and the address of a variable. - The variable, type `char *', is set to the variable part of the - given option if the fixed part matches. The actual option name - is made by appending `-m' to the specified name. - - Here is an example which defines `-mshort-data-NUMBER'. If the - given option is `-mshort-data-512', the variable `m88k_short_data' - will be set to the string `"512"'. - - extern char *m88k_short_data; - #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ - -extern char *arc_cpu_string; -extern char *arc_text_string,*arc_data_string,*arc_rodata_string; - -#define TARGET_OPTIONS \ -{ \ - { "cpu=", &arc_cpu_string }, \ - { "text=", &arc_text_string }, \ - { "data=", &arc_data_string }, \ - { "rodata=", &arc_rodata_string }, \ -} - -/* Which cpu we're compiling for. */ -extern int arc_cpu_type; - -/* Check if CPU is an extension and set `arc_cpu_type' and `arc_mangle_cpu' - appropriately. The result should be non-zero if the cpu is recognized, - otherwise zero. This is intended to be redefined in a cover file. - This is used by arc_init. */ -#define ARC_EXTENSION_CPU(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 all the command options have - been parsed. - - Don't use this macro to turn on various extra optimizations for - `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ - -extern void arc_init (); - -#define OVERRIDE_OPTIONS \ -do { \ - /* These need to be done at start up. It's convenient to do them here. */ \ - arc_init (); \ -} while (0) - -/* Target machine storage layout. */ - -/* Define to use software floating point emulator for REAL_ARITHMETIC and - decimal <-> binary conversion. */ -#define REAL_ARITHMETIC - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. */ -#define BITS_BIG_ENDIAN 1 - -/* Define this if most significant byte of a word is the lowest numbered. */ -#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN) - -/* Define this if most significant word of a multiword number is the lowest - numbered. */ -#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN) - -/* Define this to set the endianness to use in libgcc2.c, which can - not depend on target_flags. */ -#ifdef __big_endian__ -#define LIBGCC2_WORDS_BIG_ENDIAN 1 -#else -#define LIBGCC2_WORDS_BIG_ENDIAN 0 -#endif - -/* Number of bits in an addressable storage unit. */ -#define BITS_PER_UNIT 8 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; - if using 16-bit ints on a 68000, this would still be 32. - But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 32 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 4 - -/* Define this macro if it is advisable to hold scalars in registers - in a wider mode than that declared by the program. In such cases, - the value is constrained to be within the bounds of the declared - type, but kept valid in the wider mode. The signedness of the - extension may differ from that of the type. */ -#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ -if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ -{ \ - (MODE) = SImode; \ -} - -/* Define this macro if the promotion described by `PROMOTE_MODE' - should also be done for outgoing function arguments. */ -#define PROMOTE_FUNCTION_ARGS - -/* Likewise, if the function return value is promoted. */ -#define PROMOTE_FUNCTION_RETURN - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 32 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 64 - -/* ALIGN FRAMES on word boundaries */ -#define ARC_STACK_ALIGN(LOC) (((LOC)+7) & ~7) - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 32 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 32 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* A bitfield declared as `int' forces `int' alignment for the struct. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* No data type wants to be aligned rounder than this. */ -/* This is bigger than currently necessary for the ARC. If 8 byte floats are - ever added it's not clear whether they'll need such alignment or not. For - now we assume they will. We can always relax it if necessary but the - reverse isn't true. */ -#define BIGGEST_ALIGNMENT 64 - -/* The best alignment to use in cases where we have a choice. */ -#define FASTEST_ALIGNMENT 32 - -/* Make strings word-aligned so strcpy from constants will be faster. */ -#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ - ((TREE_CODE (EXP) == STRING_CST \ - && (ALIGN) < FASTEST_ALIGNMENT) \ - ? FASTEST_ALIGNMENT : (ALIGN)) - -/* Make arrays of chars word-aligned for the same reasons. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN)) - -/* Set this nonzero if move instructions will actually fail to work - when given unaligned data. */ -/* On the ARC the lower address bits are masked to 0 as necessary. The chip - won't croak when given an unaligned address, but the insn will still fail - to produce the correct result. */ -#define STRICT_ALIGNMENT 1 - -/* Layout of source language data types. */ - -#define SHORT_TYPE_SIZE 16 -#define INT_TYPE_SIZE 32 -#define LONG_TYPE_SIZE 32 -#define LONG_LONG_TYPE_SIZE 64 -#define FLOAT_TYPE_SIZE 32 -#define DOUBLE_TYPE_SIZE 64 -#define LONG_DOUBLE_TYPE_SIZE 64 - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -#define SIZE_TYPE "long unsigned int" -#define PTRDIFF_TYPE "long int" -#define WCHAR_TYPE "short unsigned int" -#define WCHAR_TYPE_SIZE 16 - -/* Define results of standard character escape sequences. */ -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. */ -/* Registers 61, 62, and 63 are not really registers and we needn't treat - them as such. We still need a register for the condition code. */ -#define FIRST_PSEUDO_REGISTER 62 - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - - 0-28 - general purpose registers - 29 - ilink1 (interrupt link register) - 30 - ilink2 (interrupt link register) - 31 - blink (branch link register) - 32-59 - reserved for extensions - 60 - LP_COUNT - 61 - condition code - - For doc purposes: - 61 - short immediate data indicator (setting flags) - 62 - long immediate data indicator - 63 - short immediate data indicator (not setting flags). - - The general purpose registers are further broken down into: - 0-7 - arguments/results - 8-15 - call used - 16-23 - call saved - 24 - call used, static chain pointer - 25 - call used, gptmp - 26 - global pointer - 27 - frame pointer - 28 - stack pointer - - By default, the extension registers are not available. */ - -#define FIXED_REGISTERS \ -{ 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 1, 1, 1, 1, 0, \ - \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1 } - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. */ - -#define CALL_USED_REGISTERS \ -{ 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 1 } - -/* If defined, an initializer for a vector of integers, containing the - numbers of hard registers in the order in which GNU CC should - prefer to use them (from most preferred to least). */ -#define REG_ALLOC_ORDER \ -{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, \ - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 31, \ - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, \ - 27, 28, 29, 30 } - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. */ -#define HARD_REGNO_NREGS(REGNO, MODE) \ -((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ -extern unsigned int arc_hard_regno_mode_ok[]; -extern unsigned int arc_mode_class[]; -#define HARD_REGNO_MODE_OK(REGNO, MODE) \ -((arc_hard_regno_mode_ok[REGNO] & arc_mode_class[MODE]) != 0) - -/* A C expression that is nonzero if it is desirable to choose - register allocation so as to avoid move instructions between a - value of mode MODE1 and a value of mode MODE2. - - If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, - MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1, - MODE2)' must be zero. */ - -/* Tie QI/HI/SI modes together. */ -#define MODES_TIEABLE_P(MODE1, MODE2) \ -(GET_MODE_CLASS (MODE1) == MODE_INT \ - && GET_MODE_CLASS (MODE2) == MODE_INT \ - && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD \ - && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD) - -/* Register classes and constants. */ - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. - - It is important that any condition codes have class NO_REGS. - See `register_operand'. */ - -enum reg_class { - NO_REGS, LPCOUNT_REG, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES -}; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ -#define REG_CLASS_NAMES \ -{ "NO_REGS", "LPCOUNT_REG", "GENERAL_REGS", "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS \ -{ {0, 0}, {0, 0x10000000}, {0xffffffff, 0xfffffff}, \ - {0xffffffff, 0x1fffffff} } - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ -extern enum reg_class arc_regno_reg_class[]; -#define REGNO_REG_CLASS(REGNO) \ -(arc_regno_reg_class[REGNO]) - -/* The class value for index registers, and the one for base regs. */ -#define INDEX_REG_CLASS GENERAL_REGS -#define BASE_REG_CLASS GENERAL_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ -#define REG_CLASS_FROM_LETTER(C) \ -((C) == 'l' ? LPCOUNT_REG /* ??? needed? */ \ - : NO_REGS) - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ -#define REGNO_OK_FOR_BASE_P(REGNO) \ -((REGNO) < 29 || (unsigned) reg_renumber[REGNO] < 29) -#define REGNO_OK_FOR_INDEX_P(REGNO) \ -((REGNO) < 29 || (unsigned) reg_renumber[REGNO] < 29) - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. */ -#define PREFERRED_RELOAD_CLASS(X,CLASS) \ -(CLASS) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ -((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* The letters I, J, K, L, M, N, O, P in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. */ -/* 'I' is used for short immediates (always signed). - 'J' is used for long immediates. - 'K' is used for any constant up to 64 bits (for 64x32 situations?). */ - -/* local to this file */ -#define SMALL_INT(X) ((unsigned) ((X) + 0x100) < 0x200) -/* local to this file */ -#define LARGE_INT(X) \ -((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \ - && (X) <= (unsigned HOST_WIDE_INT) 0xffffffff) - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'I' ? SMALL_INT (VALUE) \ - : (C) == 'J' ? LARGE_INT (VALUE) \ - : (C) == 'K' ? 1 \ - : 0) - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. */ -/* 'G' is used for integer values for the multiplication insns where the - operands are extended from 4 bytes to 8 bytes. - 'H' is used when any 64 bit constant is allowed. */ -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'G' ? arc_double_limm_p (VALUE) \ - : (C) == 'H' ? 1 \ - : 0) - -/* A C expression that defines the optional machine-dependent constraint - letters that can be used to segregate specific types of operands, - usually memory references, for the target machine. It should return 1 if - VALUE corresponds to the operand type represented by the constraint letter - C. If C is not defined as an extra constraint, the value returned should - be 0 regardless of VALUE. */ -/* ??? This currently isn't used. Waiting for PIC. */ -#if 0 -#define EXTRA_CONSTRAINT(VALUE, C) \ -((C) == 'R' ? (SYMBOL_REF_FLAG (VALUE) || GET_CODE (VALUE) == LABEL_REF) \ - : 0) -#endif - -/* Stack layout and stack pointer usage. */ - -/* Define this macro if pushing a word onto the stack moves the stack - pointer to a smaller address. */ -#define STACK_GROWS_DOWNWARD - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ -#define STARTING_FRAME_OFFSET 0 - -/* Offset from the stack pointer register to the first location at which - outgoing arguments are placed. */ -#define STACK_POINTER_OFFSET FIRST_PARM_OFFSET (0) - -/* Offset of first parameter from the argument pointer register value. */ -/* 4 bytes for each of previous fp, return address, and previous gp. - 4 byte reserved area for future considerations. */ -#define FIRST_PARM_OFFSET(FNDECL) 16 - -/* A C expression whose value is RTL representing the address in a - stack frame where the pointer to the caller's frame is stored. - Assume that FRAMEADDR is an RTL expression for the address of the - stack frame itself. - - If you don't define this macro, the default is to return the value - of FRAMEADDR--that is, the stack frame address is also the address - of the stack word that points to the previous frame. */ -/* ??? unfinished */ -/*define DYNAMIC_CHAIN_ADDRESS (FRAMEADDR)*/ - -/* A C expression whose value is RTL representing the value of the - return address for the frame COUNT steps up from the current frame. - FRAMEADDR is the frame pointer of the COUNT frame, or the frame - pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' - is defined. */ -/* The current return address is in r31. The return address of anything - farther back is at [%fp,4]. */ -#if 0 /* The default value should work. */ -#define RETURN_ADDR_RTX(COUNT, FRAME) \ -(((COUNT) == -1) \ - ? gen_rtx (REG, Pmode, 31) \ - : copy_to_reg (gen_rtx (MEM, Pmode, \ - memory_address (Pmode, plus_constant ((FRAME), UNITS_PER_WORD))))) -#endif - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM 28 - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 27 - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM - -/* Register in which static-chain is passed to a function. This must - not be a register used by the prologue. */ -#define STATIC_CHAIN_REGNUM 24 - -/* A C expression which is nonzero if a function must have and use a - frame pointer. This expression is evaluated in the reload pass. - If its value is nonzero the function will have a frame pointer. */ -#define FRAME_POINTER_REQUIRED \ -(current_function_calls_alloca) - -/* C statement to store the difference between the frame pointer - and the stack pointer values immediately after the function prologue. */ -#define INITIAL_FRAME_POINTER_OFFSET(VAR) \ -((VAR) = arc_compute_frame_size (get_frame_size ())) - -/* Function argument passing. */ - -/* When a prototype says `char' or `short', really pass an `int'. */ -#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'. No space will be pushed - onto the stack for each call; instead, the function prologue should - increase the stack frame size by this amount. */ -#define ACCUMULATE_OUTGOING_ARGS - -/* Value is the number of bytes of arguments automatically - popped when returning from a subroutine call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - SIZE is the number of bytes of arguments passed on the stack. */ -#define RETURN_POPS_ARGS(DECL, FUNTYPE, SIZE) 0 - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. */ -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ -((CUM) = 0) - -/* The number of registers used for parameter passing. Local to this file. */ -#define MAX_ARC_PARM_REGS 8 - -/* 1 if N is a possible register number for function argument passing. */ -#define FUNCTION_ARG_REGNO_P(N) \ -((unsigned) (N) < MAX_ARC_PARM_REGS) - -/* The ROUND_ADVANCE* macros are local to this file. */ -/* Round SIZE up to a word boundary. */ -#define ROUND_ADVANCE(SIZE) \ -(((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Round arg MODE/TYPE up to the next word boundary. */ -#define ROUND_ADVANCE_ARG(MODE, TYPE) \ -((MODE) == BLKmode \ - ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \ - : ROUND_ADVANCE (GET_MODE_SIZE (MODE))) - -/* Round CUM up to the necessary point for argument MODE/TYPE. */ -#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \ -((((MODE) == BLKmode ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) \ - > BITS_PER_WORD) \ - ? ((CUM) + 1 & ~1) \ - : (CUM)) - -/* Return boolean indicating arg of type TYPE and mode MODE will be passed in - a reg. This includes arguments that have to be passed by reference as the - pointer to them is passed in a reg if one is available (and that is what - we're given). - When passing arguments NAMED is always 1. When receiving arguments NAMED - is 1 for each argument except the last in a stdarg/varargs function. In - a stdarg function we want to treat the last named arg as named. In a - varargs function we want to treat the last named arg (which is - `__builtin_va_alist') as unnamed. - This macro is only used in this file. */ -extern int current_function_varargs; -#define PASS_IN_REG_P(CUM, MODE, TYPE, NAMED) \ -((!current_function_varargs || (NAMED)) \ - && (CUM) < MAX_ARC_PARM_REGS \ - && ((ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \ - + ROUND_ADVANCE_ARG ((MODE), (TYPE)) \ - <= MAX_ARC_PARM_REGS))) - -/* Determine where to put an argument to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ -/* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers - and the rest are pushed. */ -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ -(PASS_IN_REG_P ((CUM), (MODE), (TYPE), (NAMED)) \ - ? gen_rtx (REG, (MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))) \ - : 0) - -/* A C expression for the number of words, at the beginning of an - argument, must be put in registers. The value must be zero for - arguments that are passed entirely in registers or that are entirely - pushed on the stack. - - On some machines, certain arguments must be passed partially in - registers and partially in memory. On these machines, typically the - first @var{n} words of arguments are passed in registers, and the rest - on the stack. If a multi-word argument (a @code{double} or a - structure) crosses that boundary, its first few words must be passed - in registers and the rest must be pushed. This macro tells the - compiler when this occurs, and how many of the words should go in - registers. */ -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 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. */ -/* All aggregates and arguments greater than 8 bytes are passed this way. */ -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ -(TYPE \ - && (AGGREGATE_TYPE_P (TYPE) \ - || int_size_in_bytes (TYPE) > 8)) - -/* A C expression that indicates when it is the called function's - responsibility to make copies of arguments passed by reference. - If the callee can determine that the argument won't be modified, it can - avoid the copy. */ -/* ??? We'd love to be able to use NAMED here. Unfortunately, it doesn't - include the last named argument so we keep track of the args ourselves. */ - -#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \ -FUNCTION_ARG_PASS_BY_REFERENCE ((CUM), (MODE), (TYPE), (NAMED)) - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ -((CUM) = (ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \ - + ROUND_ADVANCE_ARG ((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) \ -(((TYPE) ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) <= PARM_BOUNDARY \ - ? PARM_BOUNDARY \ - : 2 * PARM_BOUNDARY) - -/* This macro offers an alternative - to using `__builtin_saveregs' and defining the macro - `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register - arguments into the stack so that all the arguments appear to have - been passed consecutively on the stack. Once this is done, you - can use the standard implementation of varargs that works for - machines that pass all their arguments on the stack. - - The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, - containing the values that obtain after processing of the named - arguments. The arguments MODE and TYPE describe the last named - argument--its machine mode and its data type as a tree node. - - The macro implementation should do two things: first, push onto the - stack all the argument registers *not* used for the named - arguments, and second, store the size of the data thus pushed into - the `int'-valued variable whose name is supplied as the argument - PRETEND_SIZE. The value that you store here will serve as - additional offset for setting up the stack frame. - - If the argument NO_RTL is nonzero, it means that the - arguments of the function are being analyzed for the second time. - This happens for an inline function, which is not actually - compiled until the end of the source file. The macro - `SETUP_INCOMING_VARARGS' should not generate any instructions in - this case. */ - -#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_SIZE, NO_RTL) \ -arc_setup_incoming_varargs(&ARGS_SO_FAR, MODE, TYPE, &PRETEND_SIZE, NO_RTL) - -/* Function results. */ - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. */ -#define FUNCTION_VALUE(VALTYPE, FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) - -/* 1 if N is a possible register number for a function value - as seen by the caller. */ -/* ??? What about r1 in DI/DF values. */ -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) - -/* A C expression which can inhibit the returning of certain function - values in registers, based on the type of value. A nonzero value says - to return the function value in memory, just as large structures are - always returned. Here TYPE will be a C expression of type `tree', - representing the data type of the value. */ -#define RETURN_IN_MEMORY(TYPE) \ -(AGGREGATE_TYPE_P (TYPE) \ - || int_size_in_bytes (TYPE) > 8 \ - || TREE_ADDRESSABLE (TYPE)) - -/* Tell GCC to use RETURN_IN_MEMORY. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Register in which address to store a structure value - is passed to a function, or 0 to use `invisible' first argument. */ -#define STRUCT_VALUE 0 - -/* Function entry and exit. */ - -/* This macro generates the assembly code for function entry. - FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - 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. */ -#define FUNCTION_PROLOGUE(FILE, SIZE) \ -arc_output_function_prologue (FILE, SIZE) - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. */ -#define EXIT_IGNORE_STACK 0 - -/* This macro generates the assembly code for function exit, - on machines that need it. If FUNCTION_EPILOGUE is not defined - then individual return instructions are generated for each - return statement. Args are same as for FUNCTION_PROLOGUE. - - The function epilogue should not depend on the current stack pointer! - It should use the frame pointer only. This is mandatory because - of alloca; we also take advantage of it to omit stack adjustments - before returning. */ -#define FUNCTION_EPILOGUE(FILE, SIZE) \ -arc_output_function_epilogue (FILE, SIZE) - -/* Epilogue delay slots. */ -#define DELAY_SLOTS_FOR_EPILOGUE arc_delay_slots_for_epilogue () - -#define ELIGIBLE_FOR_EPILOGUE_DELAY(TRIAL, SLOTS_FILLED) \ -arc_eligible_for_epilogue_delay (TRIAL, SLOTS_FILLED) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ -#define FUNCTION_PROFILER(FILE, LABELNO) - -/* Trampolines. */ -/* ??? This doesn't work yet because GCC will use as the address of a nested - function the address of the trampoline. We need to use that address - right shifted by 2. It looks like we'll need PSImode after all. :-( */ - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. */ -/* On the ARC, the trampoline is quite simple as we have 32 bit immediate - constants. - - mov r24,STATIC - j.nd FUNCTION -*/ -#define TRAMPOLINE_TEMPLATE(FILE) \ -do { \ - ASM_OUTPUT_INT (FILE, GEN_INT (0x631f7c00)); \ - ASM_OUTPUT_INT (FILE, const0_rtx); \ - ASM_OUTPUT_INT (FILE, GEN_INT (0x381f0000)); \ - ASM_OUTPUT_INT (FILE, const0_rtx); \ -} while (0) - -/* Length in units of the trampoline for entering a nested function. */ -#define TRAMPOLINE_SIZE 16 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -do { \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 4)), CXT); \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 12)), FNADDR); \ - emit_insn (gen_flush_icache (validize_mem (gen_rtx (MEM, SImode, TRAMP)))); \ -} while (0) - -/* Library calls. */ - -/* Generate calls to memcpy, memcmp and memset. */ -#define TARGET_MEM_FUNCTIONS - -/* Addressing modes, and classification of registers for them. */ - -/* Maximum number of registers that can appear in a valid memory address. */ -/* The `ld' insn allows 2, but the `st' insn only allows 1. */ -#define MAX_REGS_PER_ADDRESS 1 - -/* We have pre inc/dec (load/store with update). */ -#define HAVE_PRE_INCREMENT 1 -#define HAVE_PRE_DECREMENT 1 - -/* Recognize any constant value that is a valid address. */ -#define CONSTANT_ADDRESS_P(X) \ -(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST) - -/* Nonzero if the constant value X is a legitimate general operand. - We can handle any 32 or 64 bit constant. */ -/* "1" should work since the largest constant should be a 64 bit critter. */ -/* ??? Not sure what to do for 64x32 compiler. */ -#define LEGITIMATE_CONSTANT_P(X) 1 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) \ -((unsigned) REGNO (X) - 29 >= FIRST_PSEUDO_REGISTER - 29) -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) \ -((unsigned) REGNO (X) - 29 >= FIRST_PSEUDO_REGISTER - 29) - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. */ -/* The `ld' insn allows [reg],[reg+shimm],[reg+limm],[reg+reg],[limm] - but the `st' insn only allows [reg],[reg+shimm],[limm]. - The only thing we can do is only allow the most strict case `st' and hope - other parts optimize out the restrictions for `ld'. */ - -/* local to this file */ -#define RTX_OK_FOR_BASE_P(X) \ -(REG_P (X) && REG_OK_FOR_BASE_P (X)) - -/* local to this file */ -#define RTX_OK_FOR_INDEX_P(X) \ -(0 && /*???*/ REG_P (X) && REG_OK_FOR_INDEX_P (X)) - -/* local to this file */ -/* ??? Loads can handle any constant, stores can only handle small ones. */ -#define RTX_OK_FOR_OFFSET_P(X) \ -(GET_CODE (X) == CONST_INT && SMALL_INT (INTVAL (X))) - -#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \ -(GET_CODE (X) == PLUS \ - && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \ - && (RTX_OK_FOR_INDEX_P (XEXP (X, 1)) \ - || RTX_OK_FOR_OFFSET_P (XEXP (X, 1)))) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ if (RTX_OK_FOR_BASE_P (X)) \ - goto ADDR; \ - if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X))) \ - goto ADDR; \ - if (GET_CODE (X) == CONST_INT && LARGE_INT (INTVAL (X))) \ - goto ADDR; \ - if (GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == LABEL_REF \ - || GET_CODE (X) == CONST) \ - goto ADDR; \ - if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == PRE_INC) \ - /* We're restricted here by the `st' insn. */ \ - && RTX_OK_FOR_BASE_P (XEXP ((X), 0))) \ - goto ADDR; \ -} - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. */ - -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. */ -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ -{ if (GET_CODE (ADDR) == PRE_DEC) \ - goto LABEL; \ - if (GET_CODE (ADDR) == PRE_INC) \ - goto LABEL; \ -} - -/* Condition code usage. */ - -/* Some insns set all condition code flags, some only set the ZNC flags, and - some only set the ZN flags. */ - -#define EXTRA_CC_MODES CCZNCmode, CCZNmode - -#define EXTRA_CC_NAMES "CCZNC", "CCZN" - -/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, - return the mode to be used for the comparison. */ -extern enum machine_mode arc_select_cc_mode (); -#define SELECT_CC_MODE(OP, X, Y) \ -arc_select_cc_mode (OP, X, Y) - -/* Return non-zero if SELECT_CC_MODE will never return MODE for a - floating point inequality comparison. */ -#define REVERSIBLE_CC_MODE(MODE) 1 /*???*/ - -/* Costs. */ - -/* An insn is define to cost 4 "units", and we work from there. - COSTS_N_INSNS (N) is defined as (N) * 4 - 2 so that seems reasonable. - Some values are supposed to be defined relative to each other and thus - aren't necessarily related to COSTS_N_INSNS. */ - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. */ -/* Small integers are as cheap as registers. 4 byte values can be fetched - as immediate constants - let's give that the cost of an extra insn. */ -#define CONST_COSTS(X, CODE, OUTER_CODE) \ - case CONST_INT : \ - if (SMALL_INT (INTVAL (X))) \ - return 0; \ - /* fall through */ \ - case CONST : \ - case LABEL_REF : \ - case SYMBOL_REF : \ - return 4; \ - case CONST_DOUBLE : \ - { \ - rtx high, low; \ - split_double (X, &high, &low); \ - return 4 * (!SMALL_INT (INTVAL (high)) \ - + !SMALL_INT (INTVAL (low))); \ - } - -/* Compute the cost of an address. */ -#define ADDRESS_COST(ADDR) (REG_P (ADDR) ? 1 : arc_address_cost (ADDR)) - -/* Compute extra cost of moving data between one register class - and another. */ -#define REGISTER_MOVE_COST(CLASS1, CLASS2) 2 - -/* Compute the cost of moving data between registers and memory. */ -/* Memory is 3 times as expensive as registers. - ??? Is that the right way to look at it? */ -#define MEMORY_MOVE_COST(MODE,CLASS,IN) \ -(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12) - -/* The cost of a branch insn. */ -/* ??? What's the right value here? Branches are certainly more - expensive than reg->reg moves. */ -#define BRANCH_COST 2 - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. The purpose for the cost of MULT is to encourage - `synth_mult' to find a synthetic multiply when reasonable. - - If we need more than 12 insns to do a multiply, then go out-of-line, - since the call overhead will be < 10% of the cost of the multiply. */ -#define RTX_COSTS(X, CODE, OUTER_CODE) \ - case ASHIFT : \ - case ASHIFTRT : \ - case LSHIFTRT : \ - if (TARGET_SHIFTER) \ - return COSTS_N_INSNS (1); \ - if (GET_CODE (XEXP ((X), 1)) != CONST_INT) \ - return COSTS_N_INSNS (16); \ - return COSTS_N_INSNS (INTVAL (XEXP ((X), 1))); - -/* Nonzero if access to memory by bytes is slow and undesirable. - For RISC chips, it means that access to memory by bytes is no - better than access by words when possible, so grab a whole word - and maybe make use of that. */ -#define SLOW_BYTE_ACCESS 1 - -/* Define this macro if it is as good or better to call a constant - function address than to call an address kept in a register. */ -/* On the ARC, calling through registers is slow. */ -#define NO_FUNCTION_CSE - -/* Define this macro if it is as good or better for a function to call - itself with an explicit address than to call an address kept in a - register. */ -/* On the ARC, calling through registers is slow. */ -#define NO_RECURSIVE_FUNCTION_CSE - -/* Section selection. */ -/* WARNING: These section names also appear in dwarfout.c. */ - -/* The names of the text, data, and readonly-data sections are runtime - selectable. */ - -#define ARC_SECTION_FORMAT "\t.section %s" -#define ARC_DEFAULT_TEXT_SECTION ".text" -#define ARC_DEFAULT_DATA_SECTION ".data" -#define ARC_DEFAULT_RODATA_SECTION ".rodata" - -extern char *arc_text_section,*arc_data_section,*arc_rodata_section; - -/* initfini.c uses this in an asm. */ -#if defined (CRT_INIT) || defined (CRT_FINI) -#define TEXT_SECTION_ASM_OP "\t.section .text" -#else -#define TEXT_SECTION_ASM_OP arc_text_section /*"\t.section .text"*/ -#endif -#define DATA_SECTION_ASM_OP arc_data_section /*"\t.section .data"*/ - -#undef CONST_SECTION_ASM_OP -#define CONST_SECTION_ASM_OP arc_rodata_section /*"\t.section .rodata"*/ - -#define BSS_SECTION_ASM_OP "\t.section .bss" - -/* Define this macro if jump tables (for tablejump insns) should be - output in the text section, along with the assembler instructions. - Otherwise, the readonly data section is used. - This macro is irrelevant if there is no separate readonly data section. */ -/*#define JUMP_TABLES_IN_TEXT_SECTION*/ - -/* Define this macro if references to a symbol must be treated - differently depending on something about the variable or - function named by the symbol (such as what section it is in). - - The macro definition, if any, is executed immediately after the - rtl for DECL or other node is created. - The value of the rtl will be a `mem' whose address is a - `symbol_ref'. - - The usual thing for this macro to do is to store a flag in the - `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified - name string in the `symbol_ref' (if one bit is not enough - information). */ - -/* On the ARC, function addresses are not the same as normal addresses. - Branch to absolute address insns take an address that is right-shifted - by 2. We encode the fact that we have a function here, and then emit a - special assembler op when outputting the address. */ -#define ENCODE_SECTION_INFO(DECL) \ -do { \ - if (TREE_CODE (DECL) == FUNCTION_DECL) \ - SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \ -} while (0) - -/* Decode SYM_NAME and store the real name part in VAR, sans - the characters that encode section info. Define this macro if - ENCODE_SECTION_INFO alters the symbol's name string. */ -/*#define STRIP_NAME_ENCODING(VAR, SYM_NAME)*/ - -/* For DWARF. Marginally different than default so output is "prettier" - (and consistent with above). */ -#define PUSHSECTION_FORMAT "\t%s %s\n" - -/* Tell crtstuff.c we're using ELF. */ -#define OBJECT_FORMAT_ELF - -/* PIC */ - -/* The register number of the register used to address a table of static - data addresses in memory. In some cases this register is defined by a - processor's ``application binary interface'' (ABI). When this macro - is defined, RTL is generated for this register once, as with the stack - pointer and frame pointer registers. If this macro is not defined, it - is up to the machine-dependent files to allocate such a register (if - necessary). */ -#define PIC_OFFSET_TABLE_REGNUM 26 - -/* Define this macro if the register defined by PIC_OFFSET_TABLE_REGNUM is - clobbered by calls. Do not define this macro if PIC_OFFSET_TABLE_REGNUM - is not defined. */ -/* This register is call-saved on the ARC. */ -/*#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED*/ - -/* 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 arc_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 not - check this. You can also assume `flag_pic' is true, so you need not - check it either. You need not define this macro if all constants - (including SYMBOL_REF) can be immediate operands when generating - position independent code. */ -/*#define LEGITIMATE_PIC_OPERAND_P(X)*/ - -/* Control the assembler format that we output. */ - -/* Output at beginning of assembler file. */ -extern void arc_asm_file_start (); -#undef ASM_FILE_START -#define ASM_FILE_START(FILE) arc_asm_file_start (FILE) - -/* A C statement to output assembler commands which will identify the - object file as having been compiled with GNU CC (or another GNU - compiler). */ -#undef ASM_IDENTIFY_GCC -#define ASM_IDENTIFY_GCC(FILE) /* nothing */ - -/* Needed because we define ASM_IDENTIFY_GCC. */ -#define ASM_IDENTIFY_LANGUAGE(FILE) output_lang_identify (FILE) - -/* A C string constant describing how to begin a comment in the target - assembler language. The compiler assumes that the comment will - end at the end of the line. */ -#define ASM_COMMENT_START ";" - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ -#define ASM_APP_OFF "" - -/* This is how to output an assembler line defining a `char' constant. */ -#define ASM_OUTPUT_CHAR(FILE, VALUE) \ -( fprintf (FILE, "\t.byte\t"), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* This is how to output an assembler line defining a `short' constant. */ -#define ASM_OUTPUT_SHORT(FILE, VALUE) \ -( fprintf (FILE, "\t.hword\t"), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* This is how to output an assembler line defining an `int' constant. - We also handle symbol output here. Code addresses must be right shifted - by 2 because that's how the jump instruction wants them. */ -#define ASM_OUTPUT_INT(FILE, VALUE) \ -do { \ - fprintf (FILE, "\t.word\t"); \ - if ((GET_CODE (VALUE) == SYMBOL_REF && SYMBOL_REF_FLAG (VALUE)) \ - || GET_CODE (VALUE) == LABEL_REF) \ - { \ - fprintf (FILE, "%%st("); \ - output_addr_const (FILE, (VALUE)); \ - fprintf (FILE, ")"); \ - } \ - else \ - output_addr_const (FILE, (VALUE)); \ - fprintf (FILE, "\n"); \ -} while (0) - -/* This is how to output an assembler line defining a `float' constant. */ -#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ -{ \ - long t; \ - char str[30]; \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ - fprintf (FILE, "\t.word\t0x%lx %s %s\n", \ - t, ASM_COMMENT_START, str); \ -} - -/* This is how to output an assembler line defining a `double' constant. */ -#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ -{ \ - long t[2]; \ - char str[30]; \ - REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ - fprintf (FILE, "\t.word\t0x%lx %s %s\n\t.word\t0x%lx\n", \ - t[0], ASM_COMMENT_START, str, t[1]); \ -} - -/* This is how to output an assembler line for a numeric constant byte. */ -#define ASM_BYTE_OP ".byte" -#define ASM_OUTPUT_BYTE(FILE, VALUE) \ - fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE)) - -/* The assembler's parentheses characters. */ -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* This is how to output the definition of a user-level label named NAME, - such as the label on a static function or variable NAME. */ -#define ASM_OUTPUT_LABEL(FILE, NAME) \ -do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) - -/* This is how to output a command to make the user-level label named NAME - defined for reference from other files. */ -#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ -do { \ - fputs ("\t.global\t", FILE); \ - assemble_name (FILE, NAME); \ - fputs ("\n", FILE); \ -} while (0) - -/* A C statement (sans semicolon) to output on FILE an assembler pseudo-op to - declare a library function name external. The name of the library function - is given by SYMREF, which has type RTX and is a SYMBOL_REF. */ -#if 0 -/* On the ARC we want to have libgcc's for multiple cpus in one binary. - We can't use `assemble_name' here as that will call ASM_OUTPUT_LABELREF - and we'll get another suffix added on if -mmangle-cpu. */ -extern char *arc_mangle_cpu; -#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, SYMREF) \ -do { \ - if (TARGET_MANGLE_CPU_LIBGCC) \ - { \ - fprintf (FILE, "\t.rename\t_%s, _%s%s\n", \ - XSTR (SYMREF, 0), XSTR (SYMREF, 0), \ - arc_mangle_suffix); \ - } \ -} while (0) -#endif - -/* This is how to output a reference to a user-level label named NAME. - `assemble_name' uses this. */ -/* We mangle all user labels to provide protection from linking code - compiled for different cpus. */ -/* We work around a dwarfout.c deficiency by watching for labels from it and - not adding the '_' prefix nor the cpu suffix. There is a comment in - dwarfout.c that says it should be using ASM_OUTPUT_INTERNAL_LABEL. */ -extern char *arc_mangle_cpu; -#define ASM_OUTPUT_LABELREF(FILE, NAME) \ -do { \ - if ((NAME)[0] == '.' && (NAME)[1] == 'L') \ - fprintf (FILE, "%s", NAME); \ - else \ - { \ - fputc ('_', FILE); \ - if (TARGET_MANGLE_CPU && arc_mangle_cpu != NULL) \ - fprintf (FILE, "%s_", arc_mangle_cpu); \ - fprintf (FILE, "%s", NAME); \ - } \ -} while (0) - -/* This is how to output a definition of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ -#undef ASM_OUTPUT_INTERNAL_LABEL -#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \ -do { \ - arc_ccfsm_at_label (PREFIX, NUM); \ - fprintf (FILE, ".%s%d:\n", PREFIX, NUM); \ -} while (0) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) - -/* Assembler pseudo-op to equate one value with another. */ -/* ??? This is needed because dwarfout.c provides a default definition too - late for defaults.h (which contains the default definition of ASM_OUTPUT_DEF - that we use). */ -#define SET_ASM_OP ".set" - -/* A C statement (sans semicolon) to output an element in the table of - global constructors. */ -#undef ASM_OUTPUT_CONSTRUCTOR -#define ASM_OUTPUT_CONSTRUCTOR(FILE, NAME) \ -do { \ - ctors_section (); \ - fprintf (FILE, "\t.word\t%%st("); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ")\n"); \ -} while (0) - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ -#undef ASM_OUTPUT_DESTRUCTOR -#define ASM_OUTPUT_DESTRUCTOR(FILE, NAME) \ -do { \ - dtors_section (); \ - fprintf (FILE, "\t.word\t%%st("); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ")\n"); \ -} while (0) - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ -#define REGISTER_NAMES \ -{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ - "r24", "r25", "r26", "fp", "sp", "ilink1", "ilink2", "blink", \ - "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \ - "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", \ - "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \ - "r56", "r57", "r58", "r59", "lp_count", "cc"} - -/* Entry to the insn conditionalizer. */ -#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ -arc_final_prescan_insn (INSN, OPVEC, NOPERANDS) - -/* A C expression which evaluates to true if CODE is a valid - punctuation character for use in the `PRINT_OPERAND' macro. */ -extern char arc_punct_chars[]; -#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \ -arc_punct_chars[(unsigned char) (CHAR)] - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. */ -#define PRINT_OPERAND(FILE, X, CODE) \ -arc_print_operand (FILE, X, CODE) - -/* A C compound statement to output to stdio stream STREAM the - assembler syntax for an instruction operand that is a memory - reference whose address is ADDR. ADDR is an RTL expression. - - On some machines, the syntax for a symbolic address depends on - the section that the address refers to. On these machines, - define the macro `ENCODE_SECTION_INFO' to store the information - into the `symbol_ref', and then check for it here. */ -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ -arc_print_operand_address (FILE, ADDR) - -/* This is how to output an element of a case-vector that is absolute. */ -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ -do { \ - char label[30]; \ - ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \ - fprintf (FILE, "\t.word %%st("); \ - assemble_name (FILE, label); \ - fprintf (FILE, ")\n"); \ -} while (0) - -/* This is how to output an element of a case-vector that is relative. */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ -do { \ - char label[30]; \ - ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \ - fprintf (FILE, "\t.word %%st("); \ - assemble_name (FILE, label); \ - fprintf (FILE, "-"); \ - ASM_GENERATE_INTERNAL_LABEL (label, "L", REL); \ - assemble_name (FILE, label); \ - fprintf (FILE, ")\n"); \ -} while (0) - -/* The desired alignment for the location counter at the beginning - of a loop. */ -/* On the ARC, align loops to 32 byte boundaries (cache line size) - if -malign-loops. */ -#define LOOP_ALIGN(LABEL) (TARGET_ALIGN_LOOPS ? 5 : 0) - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ -do { if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG)); } while (0) - -/* Debugging information. */ - -/* Generate DBX and DWARF debugging information. */ -#define DBX_DEBUGGING_INFO -#define DWARF_DEBUGGING_INFO - -/* Prefer STABS (for now). */ -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG - -/* How to renumber registers for dbx and gdb. */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* Turn off splitting of long stabs. */ -#define DBX_CONTIN_LENGTH 0 - -/* Miscellaneous. */ - -/* 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. */ -/* It's not clear what PIC will look like or whether we want to use -fpic - for the embedded form currently being talked about. For now require -fpic - to get pc relative switch tables. */ -/*#define CASE_VECTOR_PC_RELATIVE 1 */ - -/* Define if operations between registers always perform the operation - on the full register even if a narrower mode is specified. */ -#define WORD_REGISTER_OPERATIONS - -/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD - will either zero-extend or sign-extend. The value of this macro should - be the code that says which one of the two operations is implicitly - done, NIL if none. */ -#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND - -/* Specify the tree operation to be used to convert reals to integers. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* This is the kind of divide that is easiest to do in the general case. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 4 - -/* Define this to be nonzero if shift instructions ignore all but the low-order - few bits. */ -#define SHIFT_COUNT_TRUNCATED 1 - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* We assume that the store-condition-codes instructions store 0 for false - and some other value for true. This is the value stored for true. */ -#define STORE_FLAG_VALUE 1 - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -/* ??? The arc doesn't have full 32 bit pointers, but making this PSImode has - its own problems (you have to add extendpsisi2 and trucnsipsi2 but how does - one do it without getting excess code?). Try to avoid it. */ -#define Pmode SImode - -/* A function address in a call instruction. */ -#define FUNCTION_MODE SImode - -/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS - is a valid machine specific attribute for DECL. - The attributes in ATTRIBUTES have previously been assigned to TYPE. */ -extern int arc_valid_machine_attribute (); -#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \ -arc_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS) - -/* A C expression that returns zero if the attributes on TYPE1 and TYPE2 are - incompatible, one if they are compatible, and two if they are - nearly compatible (which causes a warning to be generated). */ -extern int arc_comp_type_attributes (); -#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \ -arc_comp_type_attributes (TYPE1, TYPE2) - -/* Give newly defined TYPE some default attributes. */ -extern void arc_set_default_type_attributes (); -#define SET_DEFAULT_TYPE_ATTRIBUTES(TYPE) \ -arc_set_default_type_attributes (TYPE) - -/* Define this if the target system supports the function - atexit from the ANSI C standard. If this is not defined, - and INIT_SECTION_ASM_OP is not defined, a default - exit function will be provided to support C++. */ -#define HAVE_ATEXIT - -/* alloca should avoid clobbering the old register save area. */ -/* ??? Not defined in tm.texi. */ -#define SETJMP_VIA_SAVE_AREA - -/* 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 *arc_compare_op0, *arc_compare_op1; - -/* Define the function that build the compare insn for scc and bcc. */ -extern struct rtx_def *gen_compare_reg (); - -/* Declarations for various fns used in the .md file. */ -extern char *output_shift (); - -/* ARC function types. */ -enum arc_function_type { - ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL, - /* These are interrupt handlers. The name corresponds to the register - name that contains the return address. */ - ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2 -}; -#define ARC_INTERRUPT_P(TYPE) \ -((TYPE) == ARC_FUNCTION_ILINK1 || (TYPE) == ARC_FUNCTION_ILINK2) -/* Compute the type of a function from its DECL. */ -enum arc_function_type arc_compute_function_type (); diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md deleted file mode 100755 index 328b1eb..0000000 --- a/gcc/config/arc/arc.md +++ /dev/null @@ -1,1630 +0,0 @@ -;; Machine description of the Argonaut ARC cpu for GNU C compiler -;; Copyright (C) 1994, 1997 Free Software Foundation, Inc. - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;; See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; ??? This is an old port, and is undoubtedly suffering from bit rot. - -;; Insn type. Used to default other attribute values. - -(define_attr "type" - "move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc" - (const_string "binary")) - -;; Length (in # of insns, long immediate constants counted too). -;; ??? There's a nasty interaction between the conditional execution fsm -;; and insn lengths: insns with shimm values cannot be conditionally executed. -(define_attr "length" "" - (cond [(eq_attr "type" "load") - (if_then_else (match_operand 1 "long_immediate_loadstore_operand" "") - (const_int 2) (const_int 1)) - - (eq_attr "type" "store") - (if_then_else (match_operand 0 "long_immediate_loadstore_operand" "") - (const_int 2) (const_int 1)) - - (eq_attr "type" "move,unary,compare") - (if_then_else (match_operand 1 "long_immediate_operand" "") - (const_int 2) (const_int 1)) - - (eq_attr "type" "binary,mul") - (if_then_else (match_operand 2 "long_immediate_operand" "") - (const_int 2) (const_int 1)) - - (eq_attr "type" "cmove") - (if_then_else (match_operand 2 "register_operand" "") - (const_int 1) (const_int 2)) - - (eq_attr "type" "multi") (const_int 2) - ] - - (const_int 1))) - -;; The length here is the length of a single asm. Unfortunately it might be -;; 1 or 2 so we must allow for 2. That's ok though. How often will users -;; lament asm's not being put in delay slots? -(define_asm_attributes - [(set_attr "length" "2") - (set_attr "type" "multi")]) - -;; Condition codes: this one is used by final_prescan_insn to speed up -;; conditionalizing instructions. It saves having to scan the rtl to see if -;; it uses or alters the condition codes. - -;; USE: This insn uses the condition codes (eg: a conditional branch). -;; CANUSE: This insn can use the condition codes (for conditional execution). -;; SET: All condition codes are set by this insn. -;; SET_ZN: the Z and N flags are set by this insn. -;; SET_ZNC: the Z, N, and C flags are set by this insn. -;; CLOB: The condition codes are set to unknown values by this insn. -;; NOCOND: This insn can't use and doesn't affect the condition codes. - -(define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond" - (cond [(and (eq_attr "type" "unary,binary,move") - (eq_attr "length" "1")) - (const_string "canuse") - - (eq_attr "type" "compare") - (const_string "set") - - (eq_attr "type" "cmove,branch") - (const_string "use") - - (eq_attr "type" "multi,misc") - (const_string "clob") - ] - - (const_string "nocond"))) - -;; Delay slots. - -(define_attr "in_delay_slot" "false,true" - (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi") - (const_string "false") - ] - - (if_then_else (eq_attr "length" "1") - (const_string "true") - (const_string "false")))) - -(define_delay (eq_attr "type" "call") - [(eq_attr "in_delay_slot" "true") - (eq_attr "in_delay_slot" "true") - (eq_attr "in_delay_slot" "true")]) - -(define_delay (eq_attr "type" "branch,uncond_branch") - [(eq_attr "in_delay_slot" "true") - (eq_attr "in_delay_slot" "true") - (eq_attr "in_delay_slot" "true")]) - -;; Function units of the ARC - -;; (define_function_unit {name} {num-units} {n-users} {test} -;; {ready-delay} {issue-delay} [{conflict-list}]) - -;; 1) A conditional jump cannot immediately follow the insn setting the flags. -;; This isn't a complete solution as it doesn't come with guarantees. That -;; is done in the branch patterns and in arc_print_operand. This exists to -;; avoid inserting a nop when we can. -(define_function_unit "compare" 1 0 (eq_attr "type" "compare") 2 2 [(eq_attr "type" "branch")]) - -;; 2) References to loaded registers should wait a cycle. - -;; Memory with load-delay of 1 (i.e., 2 cycle load). -(define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0) - -;; Units that take one cycle do not need to be specified. - -;; Move instructions. - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - /* Everything except mem = const or mem = mem can be done easily. */ - - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (QImode, operands[1]); -}") - -(define_insn "*movqi_insn" - [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m") - (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))] -;; ??? Needed? - "register_operand (operands[0], QImode) - || register_operand (operands[1], QImode)" - "@ - mov%? %0,%1 - mov%? %0,%1 - ldb%U1%V1 %0,%1 - stb%U0%V0 %1,%0" - [(set_attr "type" "move,move,load,store")]) - -;; ??? This may never match since there's no cmpqi insn. - -(define_insn "*movqi_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi")) - (const_int 0))) - (set (match_operand:QI 0 "move_dest_operand" "=r") - (match_dup 1))] - "" - "mov%?.f %0,%1" - [(set_attr "type" "move") - (set_attr "cond" "set_zn")]) - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - /* Everything except mem = const or mem = mem can be done easily. */ - - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (HImode, operands[1]); -}") - -(define_insn "*movhi_insn" - [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m") - (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))] - "register_operand (operands[0], HImode) - || register_operand (operands[1], HImode)" - "@ - mov%? %0,%1 - mov%? %0,%1 - ldw%U1%V1 %0,%1 - stw%U0%V0 %1,%0" - [(set_attr "type" "move,move,load,store")]) - -;; ??? Will this ever match? - -(define_insn "*movhi_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi")) - (const_int 0))) - (set (match_operand:HI 0 "move_dest_operand" "=r") - (match_dup 1))] -;; ??? Needed? - "register_operand (operands[0], HImode) - || register_operand (operands[1], HImode)" - "mov%?.f %0,%1" - [(set_attr "type" "move") - (set_attr "cond" "set_zn")]) - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - /* Everything except mem = const or mem = mem can be done easily. */ - - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (SImode, operands[1]); -}") - -(define_insn "*movsi_insn" - [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m") - (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))] - "register_operand (operands[0], SImode) - || register_operand (operands[1], SImode)" - "@ - mov%? %0,%1 - mov%? %0,%S1 - ld%U1%V1 %0,%1 - st%U0%V0 %1,%0" - [(set_attr "type" "move,move,load,store")]) - -(define_insn "*movsi_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (match_operand:SI 1 "move_src_operand" "rIJi") - (const_int 0))) - (set (match_operand:SI 0 "move_dest_operand" "=r") - (match_dup 1))] - "register_operand (operands[0], SImode) - || register_operand (operands[1], SImode)" - "mov%?.f %0,%S1" - [(set_attr "type" "move") - (set_attr "cond" "set_zn")]) - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - /* Everything except mem = const or mem = mem can be done easily. */ - - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (DImode, operands[1]); -}") - -(define_insn "*movdi_insn" - [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m") - (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))] - "register_operand (operands[0], DImode) - || register_operand (operands[1], DImode)" - "* -{ - switch (which_alternative) - { - case 0 : - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register of - operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mov %R0,%R1\;mov %0,%1\"; - else - return \"mov %0,%1\;mov %R0,%R1\"; - case 1 : - return \"mov %0,%L1\;mov %R0,%H1\"; - case 2 : - /* If the low-address word is used in the address, we must load it - last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is known to be - dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands [1], 0)) - return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; - else - return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; - case 3 : - return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; - } -}" - [(set_attr "type" "move,move,load,store") - ;; ??? The ld/st values could be 4 if it's [reg,bignum]. - (set_attr "length" "2,4,2,2")]) - -;(define_expand "movdi" -; [(set (match_operand:DI 0 "general_operand" "") -; (match_operand:DI 1 "general_operand" ""))] -; "" -; " -;{ -; /* Flow doesn't understand that this is effectively a DFmode move. -; It doesn't know that all of `operands[0]' is set. */ -; emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); -; -; /* Emit insns that movsi_insn can handle. */ -; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode), -; operand_subword (operands[1], 0, 0, DImode))); -; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode), -; operand_subword (operands[1], 1, 0, DImode))); -; DONE; -;}") - -;; Floating point move insns. - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - /* Everything except mem = const or mem = mem can be done easily. */ - -#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT - if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = force_const_mem (SFmode, operands[1]); -#endif - - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (SFmode, operands[1]); -}") - -(define_insn "*movsf_insn" - [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m") - (match_operand:SF 1 "move_src_operand" "r,E,m,r"))] - "register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode)" - "@ - mov%? %0,%1 - mov%? %0,%1 ; %A1 - ld%U1%V1 %0,%1 - st%U0%V0 %1,%0" - [(set_attr "type" "move,move,load,store")]) - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - /* Everything except mem = const or mem = mem can be done easily. */ - -#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT - if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = force_const_mem (DFmode, operands[1]); -#endif - - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (DFmode, operands[1]); -}") - -(define_insn "*movdf_insn" - [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m") - (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))] - "register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode)" - "* -{ - switch (which_alternative) - { - case 0 : - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register of - operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mov %R0,%R1\;mov %0,%1\"; - else - return \"mov %0,%1\;mov %R0,%R1\"; - case 1 : - return \"mov %0,%L1\;mov %R0,%H1 ; %A1\"; - case 2 : - /* If the low-address word is used in the address, we must load it - last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is known to be - dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands [1], 0)) - return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\"; - else - return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\"; - case 3 : - return \"st%V0 %1,%0\;st%V0 %R1,%R0\"; - } -}" - [(set_attr "type" "move,move,load,store") - ;; ??? The ld/st values could be 4 if it's [reg,bignum]. - (set_attr "length" "2,4,2,2")]) - -;(define_expand "movdf" -; [(set (match_operand:DF 0 "general_operand" "") -; (match_operand:DF 1 "general_operand" ""))] -; "" -; " -;{ -; /* Flow doesn't understand that this is effectively a DFmode move. -; It doesn't know that all of `operands[0]' is set. */ -; emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); -; -; /* Emit insns that movsi_insn can handle. */ -; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode), -; operand_subword (operands[1], 0, 0, DFmode))); -; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode), -; operand_subword (operands[1], 1, 0, DFmode))); -; DONE; -;}") - -;; Load/Store with update instructions. -;; -;; Some of these we can get by using pre-decrement or pre-increment, but the -;; hardware can also do cases where the increment is not the size of the -;; object. -;; -;; In all these cases, we use operands 0 and 1 for the register being -;; incremented because those are the operands that local-alloc will -;; tie and these are the pair most likely to be tieable (and the ones -;; that will benefit the most). -;; -;; We use match_operator here because we need to know whether the memory -;; object is volatile or not. - -(define_insn "*loadqi_update" - [(set (match_operand:QI 3 "register_operand" "=r,r") - (match_operator:QI 4 "load_update_operand" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "rI,J")])) - (set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldb.a%V4 %3,[%0,%2]" - [(set_attr "type" "load,load") - (set_attr "length" "1,2")]) - -(define_insn "*load_zeroextendqisi_update" - [(set (match_operand:SI 3 "register_operand" "=r,r") - (zero_extend:SI (match_operator:QI 4 "load_update_operand" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) - (set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldb.a%V4 %3,[%0,%2]" - [(set_attr "type" "load,load") - (set_attr "length" "1,2")]) - -(define_insn "*load_signextendqisi_update" - [(set (match_operand:SI 3 "register_operand" "=r,r") - (sign_extend:SI (match_operator:QI 4 "load_update_operand" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) - (set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldb.x.a%V4 %3,[%0,%2]" - [(set_attr "type" "load,load") - (set_attr "length" "1,2")]) - -(define_insn "*storeqi_update" - [(set (match_operator:QI 4 "store_update_operand" - [(match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "short_immediate_operand" "I")]) - (match_operand:QI 3 "register_operand" "r")) - (set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "stb.a%V4 %3,[%0,%2]" - [(set_attr "type" "store") - (set_attr "length" "1")]) - -(define_insn "*loadhi_update" - [(set (match_operand:HI 3 "register_operand" "=r,r") - (match_operator:HI 4 "load_update_operand" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "rI,J")])) - (set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldw.a%V4 %3,[%0,%2]" - [(set_attr "type" "load,load") - (set_attr "length" "1,2")]) - -(define_insn "*load_zeroextendhisi_update" - [(set (match_operand:SI 3 "register_operand" "=r,r") - (zero_extend:SI (match_operator:HI 4 "load_update_operand" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) - (set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldw.a%V4 %3,[%0,%2]" - [(set_attr "type" "load,load") - (set_attr "length" "1,2")]) - -(define_insn "*load_signextendhisi_update" - [(set (match_operand:SI 3 "register_operand" "=r,r") - (sign_extend:SI (match_operator:HI 4 "load_update_operand" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "rI,J")]))) - (set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ldw.x.a%V4 %3,[%0,%2]" - [(set_attr "type" "load,load") - (set_attr "length" "1,2")]) - -(define_insn "*storehi_update" - [(set (match_operator:HI 4 "store_update_operand" - [(match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "short_immediate_operand" "I")]) - (match_operand:HI 3 "register_operand" "r")) - (set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "stw.a%V4 %3,[%0,%2]" - [(set_attr "type" "store") - (set_attr "length" "1")]) - -(define_insn "*loadsi_update" - [(set (match_operand:SI 3 "register_operand" "=r,r") - (match_operator:SI 4 "load_update_operand" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "rI,J")])) - (set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ld.a%V4 %3,[%0,%2]" - [(set_attr "type" "load,load") - (set_attr "length" "1,2")]) - -(define_insn "*storesi_update" - [(set (match_operator:SI 4 "store_update_operand" - [(match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "short_immediate_operand" "I")]) - (match_operand:SI 3 "register_operand" "r")) - (set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "st.a%V4 %3,[%0,%2]" - [(set_attr "type" "store") - (set_attr "length" "1")]) - -(define_insn "*loadsf_update" - [(set (match_operand:SF 3 "register_operand" "=r,r") - (match_operator:SF 4 "load_update_operand" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "rI,J")])) - (set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "ld.a%V4 %3,[%0,%2]" - [(set_attr "type" "load,load") - (set_attr "length" "1,2")]) - -(define_insn "*storesf_update" - [(set (match_operator:SF 4 "store_update_operand" - [(match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "short_immediate_operand" "I")]) - (match_operand:SF 3 "register_operand" "r")) - (set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_dup 1) (match_dup 2)))] - "" - "st.a%V4 %3,[%0,%2]" - [(set_attr "type" "store") - (set_attr "length" "1")]) - -;; Conditional move instructions. - -(define_expand "movsicc" - [(set (match_operand:SI 0 "register_operand" "") - (if_then_else (match_operand 1 "comparison_operator" "") - (match_operand:SI 2 "nonmemory_operand" "") - (match_operand:SI 3 "register_operand" "")))] - "" - " -{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = gen_rtx (REG, - SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), - 61); - - operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); -}") - -;(define_expand "movdicc" -; [(set (match_operand:DI 0 "register_operand" "") -; (if_then_else (match_operand 1 "comparison_operator" "") -; (match_operand:DI 2 "nonmemory_operand" "") -; (match_operand:DI 3 "register_operand" "")))] -; "0 /* ??? this would work better if we had cmpdi */" -; " -;{ -; enum rtx_code code = GET_CODE (operands[1]); -; rtx ccreg = gen_rtx (REG, -; SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), -; 61); -; -; operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); -;}") - -(define_expand "movsfcc" - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else (match_operand 1 "comparison_operator" "") - (match_operand:SF 2 "nonmemory_operand" "") - (match_operand:SF 3 "register_operand" "")))] - "" - " -{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = gen_rtx (REG, - SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), - 61); - - operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); -}") - -;(define_expand "movdfcc" -; [(set (match_operand:DF 0 "register_operand" "") -; (if_then_else (match_operand 1 "comparison_operator" "") -; (match_operand:DF 2 "nonmemory_operand" "") -; (match_operand:DF 3 "register_operand" "")))] -; "0 /* ??? can generate less efficient code if constants involved */" -; " -;{ -; enum rtx_code code = GET_CODE (operands[1]); -; rtx ccreg = gen_rtx (REG, -; SELECT_CC_MODE (code, arc_compare_op0, arc_compare_op1), -; 61); -; -; operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); -;}") - -(define_insn "*movsicc_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (if_then_else (match_operand 1 "comparison_operator" "") - (match_operand:SI 2 "nonmemory_operand" "rJi") - (match_operand:SI 3 "register_operand" "0")))] - "" - "mov.%d1 %0,%S2" - [(set_attr "type" "cmove")]) - -; ??? This doesn't properly handle constants. -;(define_insn "*movdicc_insn" -; [(set (match_operand:DI 0 "register_operand" "=r,r") -; (if_then_else (match_operand 1 "comparison_operator" "") -; (match_operand:DI 2 "nonmemory_operand" "r,Ji") -; (match_operand:DI 3 "register_operand" "0,0")))] -; "0" -; "* -;{ -; switch (which_alternative) -; { -; case 0 : -; /* We normally copy the low-numbered register first. However, if -; the first register operand 0 is the same as the second register of -; operand 1, we must copy in the opposite order. */ -; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) -; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; -; else -; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; -; case 1 : -; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; -; } -;}" -; [(set_attr "type" "cmove,cmove") -; (set_attr "length" "2,4")]) - -(define_insn "*movsfcc_insn" - [(set (match_operand:SF 0 "register_operand" "=r,r") - (if_then_else (match_operand 1 "comparison_operator" "") - (match_operand:SF 2 "nonmemory_operand" "r,E") - (match_operand:SF 3 "register_operand" "0,0")))] - "" - "@ - mov.%d1 %0,%2 - mov.%d1 %0,%2 ; %A2" - [(set_attr "type" "cmove,cmove")]) - -;(define_insn "*movdfcc_insn" -; [(set (match_operand:DF 0 "register_operand" "=r,r") -; (if_then_else (match_operand 1 "comparison_operator" "") -; (match_operand:DF 2 "nonmemory_operand" "r,E") -; (match_operand:DF 3 "register_operand" "0,0")))] -; "0" -; "* -;{ -; switch (which_alternative) -; { -; case 0 : -; /* We normally copy the low-numbered register first. However, if -; the first register operand 0 is the same as the second register of -; operand 1, we must copy in the opposite order. */ -; if (REGNO (operands[0]) == REGNO (operands[2]) + 1) -; return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\"; -; else -; return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\"; -; case 1 : -; return \"mov.%d1 %0,%L2\;mov.%d1 %R0,%H2 ; %A2\"; -; } -;}" -; [(set_attr "type" "cmove,cmove") -; (set_attr "length" "2,4")]) - -;; Zero extension instructions. -;; ??? We don't support volatile memrefs here, but I'm not sure why. - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] - "" - "@ - extb%? %0,%1 - ldb%U1 %0,%1" - [(set_attr "type" "unary,load")]) - -(define_insn "*zero_extendqihi2_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) - (const_int 0))) - (set (match_operand:HI 0 "register_operand" "=r") - (zero_extend:HI (match_dup 1)))] - "" - "extb%?.f %0,%1" - [(set_attr "type" "unary") - (set_attr "cond" "set_zn")]) - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] - "" - "@ - extb%? %0,%1 - ldb%U1 %0,%1" - [(set_attr "type" "unary,load")]) - -(define_insn "*zero_extendqisi2_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_dup 1)))] - "" - "extb%?.f %0,%1" - [(set_attr "type" "unary") - (set_attr "cond" "set_zn")]) - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] - "" - "@ - extw%? %0,%1 - ldw%U1 %0,%1" - [(set_attr "type" "unary,load")]) - -(define_insn "*zero_extendhisi2_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_dup 1)))] - "" - "extw%?.f %0,%1" - [(set_attr "type" "unary") - (set_attr "cond" "set_zn")]) - -;; Sign extension instructions. - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] - "" - "@ - sexb%? %0,%1 - ldb.x%U1 %0,%1" - [(set_attr "type" "unary,load")]) - -(define_insn "*extendqihi2_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) - (const_int 0))) - (set (match_operand:HI 0 "register_operand" "=r") - (sign_extend:HI (match_dup 1)))] - "" - "sexb%?.f %0,%1" - [(set_attr "type" "unary") - (set_attr "cond" "set_zn")]) - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))] - "" - "@ - sexb%? %0,%1 - ldb.x%U1 %0,%1" - [(set_attr "type" "unary,load")]) - -(define_insn "*extendqisi2_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_dup 1)))] - "" - "sexb%?.f %0,%1" - [(set_attr "type" "unary") - (set_attr "cond" "set_zn")]) - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))] - "" - "@ - sexw%? %0,%1 - ldw.x%U1 %0,%1" - [(set_attr "type" "unary,load")]) - -(define_insn "*extendhisi2_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (sign_extend:SI (match_operand:HI 1 "register_operand" "r")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_dup 1)))] - "" - "sexw%?.f %0,%1" - [(set_attr "type" "unary") - (set_attr "cond" "set_zn")]) - -;; Arithmetic instructions. - -(define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")))] - "" - "add%? %0,%1,%2") - -(define_insn "*addsi3_set_cc_insn" - [(set (reg:CC 61) (compare:CC - (plus:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_dup 1) - (match_dup 2)))] - "" - "add%?.f %0,%1,%2" - [(set_attr "cond" "set")]) - -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (plus:DI (match_operand:DI 1 "nonmemory_operand" "%r") - (match_operand:DI 2 "nonmemory_operand" "ri"))) - (clobber (reg:CC 61))] - "" - "* -{ - rtx op2 = operands[2]; - - if (GET_CODE (op2) == CONST_INT) - { - int sign = INTVAL (op2); - if (sign < 0) - return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\"; - else - return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\"; - } - else - return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\"; -}" - [(set_attr "length" "2")]) - -(define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")))] - "" - "sub%? %0,%1,%2") - -(define_insn "*subsi3_set_cc_insn" - [(set (reg:CC 61) (compare:CC - (minus:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (match_dup 1) - (match_dup 2)))] - "" - "sub%?.f %0,%1,%2" - [(set_attr "cond" "set")]) - -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (minus:DI (match_operand:DI 1 "nonmemory_operand" "r") - (match_operand:DI 2 "nonmemory_operand" "ri"))) - (clobber (reg:CC 61))] - "" - "* -{ - rtx op2 = operands[2]; - - if (GET_CODE (op2) == CONST_INT) - { - int sign = INTVAL (op2); - if (sign < 0) - return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\"; - else - return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\"; - } - else - return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\"; -}" - [(set_attr "length" "2")]) - -;; Boolean instructions. -;; -;; We don't define the DImode versions as expand_binop does a good enough job. - -(define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")))] - "" - "and%? %0,%1,%2") - -(define_insn "*andsi3_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (and:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_dup 1) - (match_dup 2)))] - "" - "and%?.f %0,%1,%2" - [(set_attr "cond" "set_zn")]) - -(define_insn "*bicsi3_insn" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") - (not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))] - "" - "bic%? %0,%1,%2" - [(set_attr "length" "1,2,1,2")]) - -(define_insn "*bicsi3_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (and:SI (match_operand:SI 1 "register_operand" "%r") - (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ"))) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_dup 1) - (not:SI (match_dup 2))))] - "" - "bic%?.f %0,%1,%2" - [(set_attr "cond" "set_zn")]) - -(define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")))] - "" - "or%? %0,%1,%2") - -(define_insn "*iorsi3_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (ior:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_dup 1) - (match_dup 2)))] - "" - "or%?.f %0,%1,%2" - [(set_attr "cond" "set_zn")]) - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (xor:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")))] - "" - "xor%? %0,%1,%2") - -(define_insn "*xorsi3_set_cc_insn" - [(set (reg:CCZN 61) (compare:CCZN - (xor:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "nonmemory_operand" "rIJ")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (xor:SI (match_dup 1) - (match_dup 2)))] - "" - "xor%?.f %0,%1,%2" - [(set_attr "cond" "set_zn")]) - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "sub%? %0,0,%1" - [(set_attr "type" "unary")]) - -(define_insn "*negsi2_set_cc_insn" - [(set (reg:CC 61) (compare:CC - (neg:SI (match_operand:SI 1 "register_operand" "r")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_dup 1)))] - "" - "sub%?.f %0,0,%1" - [(set_attr "type" "unary") - (set_attr "cond" "set")]) - -(define_insn "negdi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (neg:DI (match_operand:DI 1 "register_operand" "r"))) - (clobber (reg:SI 61))] - "" - "sub.f %L0,0,%L1\;sbc %H0,0,%H1" - [(set_attr "type" "unary") - (set_attr "length" "2")]) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "xor%? %0,%1,-1" - [(set_attr "type" "unary")]) - -(define_insn "*one_cmplsi2_set_cc_insn" - [(set (reg:CCZN 61) (compare:CC - (not:SI (match_operand:SI 1 "register_operand" "r")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_dup 1)))] - "" - "xor%?.f %0,%1,-1" - [(set_attr "type" "unary") - (set_attr "cond" "set_zn")]) - -;; Shift instructions. - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashift:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (! TARGET_SHIFTER) - { - emit_insn (gen_rtx - (PARALLEL, VOIDmode, - gen_rtvec (2, - gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (ASHIFT, SImode, operands[1], operands[2])), - gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0))))); - DONE; - } -}") - -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (! TARGET_SHIFTER) - { - emit_insn (gen_rtx - (PARALLEL, VOIDmode, - gen_rtvec (2, - gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (ASHIFTRT, SImode, operands[1], operands[2])), - gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0))))); - DONE; - } -}") - -(define_expand "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (! TARGET_SHIFTER) - { - emit_insn (gen_rtx - (PARALLEL, VOIDmode, - gen_rtvec (2, - gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (LSHIFTRT, SImode, operands[1], operands[2])), - gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0))))); - DONE; - } -}") - -(define_insn "*ashlsi3_insn" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") - (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] - "TARGET_SHIFTER" - "asl%? %0,%1,%2" - [(set_attr "type" "shift") - (set_attr "length" "1,2,1,2")]) - -(define_insn "*ashrsi3_insn" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") - (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] - "TARGET_SHIFTER" - "asr%? %0,%1,%2" - [(set_attr "type" "shift") - (set_attr "length" "1,2,1,2")]) - -(define_insn "*lshrsi3_insn" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J") - (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))] - "TARGET_SHIFTER" - "lsr%? %0,%1,%2" - [(set_attr "type" "shift") - (set_attr "length" "1,2,1,2")]) - -(define_insn "*shift_si3" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "rIJ")])) - (clobber (match_scratch:SI 4 "=&r"))] - "! TARGET_SHIFTER" - "* return output_shift (operands);" - [(set_attr "type" "shift") - (set_attr "length" "8")]) - -;; Compare instructions. -;; This controls RTL generation and register allocation. - -;; We generate RTL for comparisons and branches by having the cmpxx -;; patterns store away the operands. Then, the scc and bcc patterns -;; emit RTL for both the compare and the branch. - -(define_expand "cmpsi" - [(set (reg:CC 61) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - " -{ - arc_compare_op0 = operands[0]; - arc_compare_op1 = operands[1]; - DONE; -}") - -;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0. -;; This assumes sub.f 0,symbol,0 is a valid insn. -;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily -;; creating 8 byte insns we duplicate %1 in the destination reg of the insn -;; if it's a small constant. - -(define_insn "*cmpsi_cc_insn" - [(set (reg:CC 61) - (compare:CC (match_operand:SI 0 "register_operand" "r,r,r") - (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] - "" - "@ - sub.f 0,%0,%1 - sub.f %1,%0,%1 - sub.f 0,%0,%1" - [(set_attr "type" "compare,compare,compare")]) - -(define_insn "*cmpsi_cczn_insn" - [(set (reg:CCZN 61) - (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r") - (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] - "" - "@ - sub.f 0,%0,%1 - sub.f %1,%0,%1 - sub.f 0,%0,%1" - [(set_attr "type" "compare,compare,compare")]) - -(define_insn "*cmpsi_ccznc_insn" - [(set (reg:CCZNC 61) - (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r") - (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] - "" - "@ - sub.f 0,%0,%1 - sub.f %1,%0,%1 - sub.f 0,%0,%1" - [(set_attr "type" "compare,compare,compare")]) - -;; Next come the scc insns. - -(define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "=r") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "=r") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "=r") - (gt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "=r") - (le:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "=r") - (ge:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "=r") - (lt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "=r") - (gtu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "=r") - (leu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "=r") - (geu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "=r") - (ltu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); -}") - -(define_insn "*scc_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))] - "" - "mov %0,1\;sub.%D1 %0,%0,%0" - [(set_attr "type" "unary") - (set_attr "length" "2")]) - -;; ??? Look up negscc insn. See pa.md for example. -(define_insn "*neg_scc_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (neg:SI (match_operator:SI 1 "comparison_operator" - [(reg 61) (const_int 0)])))] - "" - "mov %0,-1\;sub.%D1 %0,%0,%0" - [(set_attr "type" "unary") - (set_attr "length" "2")]) - -(define_insn "*not_scc_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operator:SI 1 "comparison_operator" - [(reg 61) (const_int 0)])))] - "" - "mov %0,1\;sub.%d1 %0,%0,%0" - [(set_attr "type" "unary") - (set_attr "length" "2")]) - -;; These control RTL generation for conditional jump insns - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (EQ, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (NE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GE, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LT, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GTU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (GEU, arc_compare_op0, arc_compare_op1); -}") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_compare_reg (LTU, arc_compare_op0, arc_compare_op1); -}") - -;; Now match both normal and inverted jump. - -(define_insn "*branch_insn" - [(set (pc) - (if_then_else (match_operator 1 "proper_comparison_operator" - [(reg 61) (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - if (arc_ccfsm_branch_deleted_p ()) - { - arc_ccfsm_record_branch_deleted (); - return \"; branch deleted, next insns conditionalized\"; - } - else - return \"%~b%d1%# %l0\"; -}" - [(set_attr "type" "branch")]) - -(define_insn "*rev_branch_insn" - [(set (pc) - (if_then_else (match_operator 1 "proper_comparison_operator" - [(reg 61) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))" - "* -{ - if (arc_ccfsm_branch_deleted_p ()) - { - arc_ccfsm_record_branch_deleted (); - return \"; branch deleted, next insns conditionalized\"; - } - else - return \"%~b%D1%# %l0\"; -}" - [(set_attr "type" "branch")]) - -;; Unconditional and other jump instructions. - -(define_insn "jump" - [(set (pc) (label_ref (match_operand 0 "" "")))] - "" - "b%* %l0" - [(set_attr "type" "uncond_branch")]) - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "address_operand" "p"))] - "" - "j%* %a0" - [(set_attr "type" "uncond_branch")]) - -;; Implement a switch statement. -;; This wouldn't be necessary in the non-pic case if we could distinguish -;; label refs of the jump table from other label refs. The problem is that -;; label refs are output as "%st(.LL42)" but we don't want the %st - we want -;; the real address since it's the address of the table. - -(define_expand "casesi" - [(set (match_dup 5) - (minus:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" ""))) - (set (reg:CC 61) - (compare:CC (match_dup 5) - (match_operand:SI 2 "nonmemory_operand" ""))) - (set (pc) - (if_then_else (gtu (reg:CC 61) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (parallel - [(set (pc) - (mem:SI (plus:SI (mult:SI (match_dup 5) - (const_int 4)) - (label_ref (match_operand 3 "" ""))))) - (clobber (match_scratch:SI 6 "")) - (clobber (match_scratch:SI 7 ""))])] - "" - " -{ - operands[5] = gen_reg_rtx (SImode); -}") - -(define_insn "*casesi_insn" - [(set (pc) - (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r") - (const_int 4)) - (label_ref (match_operand 1 "" ""))))) - (clobber (match_scratch:SI 2 "=r")) - (clobber (match_scratch:SI 3 "=r"))] - "" - "* -{ - output_asm_insn (\"mov %2,%1\", operands); - if (TARGET_SHIFTER) - output_asm_insn (\"asl %3,%0,2\", operands); - else - output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands); - output_asm_insn (\"ld %2,[%2,%3]\", operands); - output_asm_insn (\"j.nd %a2\", operands); - return \"\"; -}" - [(set_attr "type" "uncond_branch") - (set_attr "length" "6")]) - -(define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "address_operand" "p")) - (use (label_ref (match_operand 1 "" "")))] - "0 /* disabled -> using casesi now */" - "j%* %a0" - [(set_attr "type" "uncond_branch")]) - -(define_expand "call" - ;; operands[1] is stack_size_rtx - ;; operands[2] is next_arg_register - [(parallel [(call (match_operand:SI 0 "call_operand" "") - (match_operand 1 "" "")) - (clobber (reg:SI 31))])] - "" - "") - -(define_insn "*call_via_reg" - [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) - (match_operand 1 "" "")) - (clobber (reg:SI 31))] - "" - "lr blink,[status]\;j.d %0\;add blink,blink,2" - [(set_attr "type" "call_no_delay_slot") - (set_attr "length" "3")]) - -(define_insn "*call_via_label" - [(call (mem:SI (match_operand:SI 0 "call_address_operand" "")) - (match_operand 1 "" "")) - (clobber (reg:SI 31))] - "" - ; The %~ is necessary in case this insn gets conditionalized and the previous - ; insn is the cc setter. - "%~bl%!%* %0" - [(set_attr "type" "call") - (set_attr "cond" "canuse")]) - -(define_expand "call_value" - ;; operand 2 is stack_size_rtx - ;; operand 3 is next_arg_register - [(parallel [(set (match_operand 0 "register_operand" "=r") - (call (match_operand:SI 1 "call_operand" "") - (match_operand 2 "" ""))) - (clobber (reg:SI 31))])] - "" - "") - -(define_insn "*call_value_via_reg" - [(set (match_operand 0 "register_operand" "=r") - (call (mem:SI (match_operand:SI 1 "register_operand" "r")) - (match_operand 2 "" ""))) - (clobber (reg:SI 31))] - "" - "lr blink,[status]\;j.d %1\;add blink,blink,2" - [(set_attr "type" "call_no_delay_slot") - (set_attr "length" "3")]) - -(define_insn "*call_value_via_label" - [(set (match_operand 0 "register_operand" "=r") - (call (mem:SI (match_operand:SI 1 "call_address_operand" "")) - (match_operand 2 "" ""))) - (clobber (reg:SI 31))] - "" - ; The %~ is necessary in case this insn gets conditionalized and the previous - ; insn is the cc setter. - "%~bl%!%* %1" - [(set_attr "type" "call") - (set_attr "cond" "canuse")]) - -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "type" "misc")]) - -;; Special pattern to flush the icache. -;; ??? Not sure what to do here. Some ARC's are known to support this. - -(define_insn "flush_icache" - [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)] - "" - "* return \"\";" - [(set_attr "type" "misc")]) - -;; Split up troublesome insns for better scheduling. - -;; Peepholes go at the end. diff --git a/gcc/config/arc/initfini.c b/gcc/config/arc/initfini.c deleted file mode 100755 index 084e229..0000000 --- a/gcc/config/arc/initfini.c +++ /dev/null @@ -1,157 +0,0 @@ -/* .init/.fini section handling + C++ global constructor/destructor handling. - This file is based on crtstuff.c, sol2-crti.asm, sol2-crtn.asm. - -Copyright (C) 1995, 1997 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* As a special exception, if you link this file 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. */ - -/* Declare a pointer to void function type. */ -typedef void (*func_ptr) (void); - -#ifdef CRT_INIT - -/* NOTE: In order to be able to support SVR4 shared libraries, we arrange - to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__, - __DTOR_END__ } per root executable and also one set of these symbols - per shared library. So in any given whole process image, we may have - multiple definitions of each of these symbols. In order to prevent - these definitions from conflicting with one another, and in order to - ensure that the proper lists are used for the initialization/finalization - of each individual shared library (respectively), we give these symbols - only internal (i.e. `static') linkage, and we also make it a point to - refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__ - symbol in crtinit.o, where they are defined. */ - -static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors"))) - = { (func_ptr) (-1) }; - -static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors"))) - = { (func_ptr) (-1) }; - -/* Run all the global destructors on exit from the program. */ - -/* Some systems place the number of pointers in the first word of the - table. On SVR4 however, that word is -1. In all cases, the table is - null-terminated. On SVR4, we start from the beginning of the list and - invoke each per-compilation-unit destructor routine in order - until we find that null. - - Note that this function MUST be static. There will be one of these - functions in each root executable and one in each shared library, but - although they all have the same code, each one is unique in that it - refers to one particular associated `__DTOR_LIST__' which belongs to the - same particular root executable or shared library file. */ - -static void __do_global_dtors () -asm ("__do_global_dtors") __attribute__ ((section (".text"))); - -static void -__do_global_dtors () -{ - func_ptr *p; - for (p = __DTOR_LIST__ + 1; *p; p++) - (*p) (); -} - -/* .init section start. - This must appear at the start of the .init section. */ - -asm (" - .section .init\n - .global init\n - .word 0\n -init:\n - st blink,[sp,4]\n - st fp,[sp]\n - mov fp,sp\n - sub sp,sp,16\n -"); - -/* .fini section start. - This must appear at the start of the .init section. */ - -asm (" - .section .fini\n - .global fini\n - .word 0\n -fini:\n - st blink,[sp,4]\n - st fp,[sp]\n - mov fp,sp\n - sub sp,sp,16\n - bl.nd __do_global_dtors -"); - -#endif /* CRT_INIT */ - -#ifdef CRT_FINI - -/* Put a word containing zero at the end of each of our two lists of function - addresses. Note that the words defined here go into the .ctors and .dtors - sections of the crtend.o file, and since that file is always linked in - last, these words naturally end up at the very ends of the two lists - contained in these two sections. */ - -static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors"))) - = { (func_ptr) 0 }; - -static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors"))) - = { (func_ptr) 0 }; - -/* Run all global constructors for the program. - Note that they are run in reverse order. */ - -static void __do_global_ctors () -asm ("__do_global_ctors") __attribute__ ((section (".text"))); - -static void -__do_global_ctors () -{ - func_ptr *p; - for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--) - (*p) (); -} - -/* .init section end. - This must live at the end of the .init section. */ - -asm (" - .section .init\n - bl.nd __do_global_ctors - ld blink,[fp,4]\n - j.d blink\n - ld.a fp,[sp,16]\n -"); - -/* .fini section end. - This must live at the end of the .fini section. */ - -asm (" - .section .fini\n - ld blink,[fp,4]\n - j.d blink\n - ld.a fp,[sp,16]\n -"); - -#endif /* CRT_FINI */ diff --git a/gcc/config/arc/lib1funcs.asm b/gcc/config/arc/lib1funcs.asm deleted file mode 100755 index a2d509a..0000000 --- a/gcc/config/arc/lib1funcs.asm +++ /dev/null @@ -1,273 +0,0 @@ -; libgcc1 routines for ARC cpu. - -/* Copyright (C) 1995, 1997 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 GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* As a special exception, if you link this library with other files, - some of which are compiled with GCC, to produce an executable, - this library does not by itself cause the resulting executable - to be covered by the GNU General Public License. - This exception does not however invalidate any other reasons why - the executable file might be covered by the GNU General Public License. */ - -#ifdef L_mulsi3 - .section .text - .align 4 - -#ifdef __base__ - .cpu base - .global ___mulsi3 -___mulsi3: - -/* This the simple version. - - while (a) - { - if (a & 1) - r += b; - a >>= 1; - b <<= 1; - } -*/ - mov r2,0 ; Accumulate result here. -.Lloop: - sub.f 0,r0,0 ; while (a) - nop - beq.nd .Ldone - and.f 0,r0,1 ; if (a & 1) - add.nz r2,r2,r1 ; r += b - lsr r0,r0 ; a >>= 1 - b.d .Lloop - lsl r1,r1 ; b <<= 1 -.Ldone: - j.d blink - mov r0,r2 -#endif - -#endif /* L_mulsi3 */ - -#ifdef L_umulsidi3 - .section .text - .align 4 - -#ifdef __base__ - .cpu base - .global ___umulsidi3 -___umulsidi3: - -/* This the simple version. - - while (a) - { - if (a & 1) - r += b; - a >>= 1; - b <<= 1; - } -*/ - mov r2,0 ; Top part of b. - mov r3,0 ; Accumulate result here. - mov r4,0 -.Lloop: - sub.f 0,r0,0 ; while (a) - nop - beq.nd .Ldone - and.f 0,r0,1 ; if (a & 1) - add.nz r4,r4,r1 ; r += b - adc.nz r3,r3,r2 - lsr r0,r0 ; a >>= 1 - lsl.f r1,r1 ; b <<= 1 - b.d .Lloop - rlc r2,r2 -.Ldone: -#ifdef __big_endian__ - mov r1,r4 - j.d blink - mov r0,r3 -#else - mov r0,r4 - j.d blink - mov r1,r3 -#endif -#endif - -#endif /* L_umulsidi3 */ - -#ifdef L_divmod_tools - -; Utilities used by all routines. - - .section .text - .align 4 - -; inputs: r0 = numerator, r1 = denominator -; outputs: positive r0/r1, -; r6.bit1 = sign of numerator, r6.bit0 = sign of result - - .global ___divnorm -___divnorm: - mov r6,0 ; keep sign in r6 - sub.f 0,r0,0 ; is numerator -ve? - sub.lt r0,0,r0 ; negate numerator - mov.lt r6,3 ; sign is -ve - sub.f 0,r1,0 ; is denominator -ve? - sub.lt r1,0,r1 ; negate denominator - xor.lt r6,r6,1 ; toggle sign - j.nd blink - -/* -unsigned long -udivmodsi4(int modwanted, unsigned long num, unsigned long den) -{ - unsigned long bit = 1; - unsigned long res = 0; - - while (den < num && bit && !(den & (1L<<31))) - { - den <<=1; - bit <<=1; - } - while (bit) - { - if (num >= den) - { - num -= den; - res |= bit; - } - bit >>=1; - den >>=1; - } - if (modwanted) return num; - return res; -} -*/ - -; inputs: r0 = numerator, r1 = denominator -; outputs: r0 = quotient, r1 = remainder, r2/r3 trashed - - .global ___udivmodsi4 -___udivmodsi4: - mov r2,1 ; bit = 1 - mov r3,0 ; res = 0 -.Lloop1: - sub.f 0,r1,r0 ; while (den < num - nop - bnc.nd .Lloop2 - sub.f 0,r2,0 ; && bit - nop - bz.nd .Lloop2 - lsl.f 0,r1 ; && !(den & (1<<31)) - nop - bc.nd .Lloop2 - lsl r1,r1 ; den <<= 1 - b.d .Lloop1 - lsl r2,r2 ; bit <<= 1 -.Lloop2: - sub.f 0,r2,0 ; while (bit) - nop - bz.nd .Ldivmodend - sub.f 0,r0,r1 ; if (num >= den) - nop - bc.nd .Lshiftdown - sub r0,r0,r1 ; num -= den - or r3,r3,r2 ; res |= bit -.Lshiftdown: - lsr r2,r2 ; bit >>= 1 - b.d .Lloop2 - lsr r1,r1 ; den >>= 1 -.Ldivmodend: - mov r1,r0 ; r1 = mod - j.d blink - mov r0,r3 ; r0 = res - -#endif - -#ifdef L_udivsi3 - .section .text - .align 4 - -#ifdef __base__ - .cpu base - .global ___udivsi3 -___udivsi3: - mov r7,blink - bl.nd ___udivmodsi4 - j.nd r7 -#endif - -#endif /* L_udivsi3 */ - -#ifdef L_divsi3 - .section .text - .align 4 - -#ifdef __base__ - .cpu base - .global ___divsi3 -___divsi3: - mov r7,blink - bl.nd ___divnorm - bl.nd ___udivmodsi4 - and.f 0,r6,1 - sub.nz r0,0,r0 ; cannot go in delay slot, has limm value - j.nd r7 -#endif - -#endif /* L_divsi3 */ - -#ifdef L_umodsi3 - .section .text - .align 4 - -#ifdef __base__ - .cpu base - .global ___umodsi3 -___umodsi3: - mov r7,blink - bl.nd ___udivmodsi4 - j.d r7 - mov r0,r1 -#endif - -#endif /* L_umodsi3 */ - -#ifdef L_modsi3 - .section .text - .align 4 - -#ifdef __base__ - .cpu base - .global ___modsi3 -___modsi3: - mov r7,blink - bl.nd ___divnorm - bl.nd ___udivmodsi4 - and.f 0,r6,2 - sub.nz r1,0,r1 - j.d r7 - mov r0,r1 -#endif - -#endif /* L_modsi3 */ diff --git a/gcc/config/arc/t-arc b/gcc/config/arc/t-arc deleted file mode 100755 index d922c27..0000000 --- a/gcc/config/arc/t-arc +++ /dev/null @@ -1,72 +0,0 @@ -CROSS_LIBGCC1 = libgcc1-asm.a -LIB1ASMSRC = arc/lib1funcs.asm -LIB1ASMFUNCS = _mulsi3 _umulsidi3 _udivsi3 _divsi3 _umodsi3 _modsi3 _divmod_tools - -# We need libgcc routines to be mangled according to which cpu they -# were compiled for. -# ??? -mmangle-cpu passed by default for now. -#LIBGCC2_CFLAGS = -g1 -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -mmangle-cpu - -# These are really part of libgcc1, but this will cause them to be -# built correctly, so... - -LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c - -dp-bit.c: $(srcdir)/config/fp-bit.c - echo '#ifndef __big_endian__' > dp-bit.c - echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c - echo '#endif' >> dp-bit.c - cat $(srcdir)/config/fp-bit.c >> dp-bit.c - -fp-bit.c: $(srcdir)/config/fp-bit.c - echo '#define FLOAT' > fp-bit.c - echo '#ifndef __big_endian__' >> fp-bit.c - echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c - echo '#endif' >> fp-bit.c - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - -# .init/.fini section routines - -x-crtinit.o: $(srcdir)/config/arc/initfini.c $(GCC_PASSES) $(CONFIG_H) - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ - -DCRT_INIT -finhibit-size-directive -fno-inline-functions \ - -g0 -c $(srcdir)/config/arc/initfini.c -o $(dir)/crtinit.o - -x-crtfini.o: $(srcdir)/config/arc/initfini.c $(GCC_PASSES) $(CONFIG_H) - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \ - -DCRT_FINI -finhibit-size-directive -fno-inline-functions \ - -g0 -c $(srcdir)/config/arc/initfini.c -o $(dir)/crtfini.o - -MULTILIB_OPTIONS = EB -MULTILIB_DIRNAMES = be - -# We need our own versions to build multiple copies of crt*.o. -# ??? Use new support in Makefile. - -LIBGCC = stmp-multilib-arc -INSTALL_LIBGCC = install-multilib-arc - -stmp-multilib-arc: stmp-multilib - for i in `$(GCC_FOR_TARGET) --print-multi-lib`; do \ - dir=`echo $$i | sed -e 's/;.*$$//'`; \ - flags=`echo $$i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; \ - $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \ - CC="$(CC)" CFLAGS="$(CFLAGS)" \ - HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \ - GCC_CFLAGS="$(GCC_CFLAGS) $${flags}" \ - INCLUDES="$(INCLUDES)" CRTSTUFF_T_CFLAGS=$(CRTSTUFF_T_CFLAGS) \ - dir="$${dir}" x-crtinit.o x-crtfini.o; \ - if [ $$? -eq 0 ] ; then true; else exit 1; fi; \ - done - touch stmp-multilib-arc - -install-multilib-arc: install-multilib - for i in `$(GCC_FOR_TARGET) --print-multi-lib`; do \ - dir=`echo $$i | sed -e 's/;.*$$//'`; \ - rm -f $(libsubdir)/$${dir}/crtinit.o; \ - $(INSTALL_DATA) $${dir}/crtinit.o $(libsubdir)/$${dir}/crtinit.o; \ - chmod a-x $(libsubdir)/$${dir}/crtinit.o; \ - rm -f $(libsubdir)/$${dir}/crtfini.o; \ - $(INSTALL_DATA) $${dir}/crtfini.o $(libsubdir)/$${dir}/crtfini.o; \ - chmod a-x $(libsubdir)/$${dir}/crtfini.o; \ - done diff --git a/gcc/config/arc/xm-arc.h b/gcc/config/arc/xm-arc.h deleted file mode 100755 index ba011e9..0000000 --- a/gcc/config/arc/xm-arc.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Configuration for GNU C-compiler for the ARC processor. - Copyright (C) 1994, 1997 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 8 -#define HOST_BITS_PER_SHORT 16 -#define HOST_BITS_PER_INT 32 -#define HOST_BITS_PER_LONG 32 -#define HOST_BITS_PER_LONGLONG 64 - -/* Doubles are stored in memory with the high order word first. This - matters when cross-compiling. */ -#define HOST_WORDS_BIG_ENDIAN 1 - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* If compiled with Sun CC, the use of alloca requires this #include. */ -#ifndef __GNUC__ -#include "alloca.h" -#endif diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c deleted file mode 100755 index abbfba1..0000000 --- a/gcc/config/c4x/c4x.c +++ /dev/null @@ -1,4341 +0,0 @@ -/* Subroutines for assembler code output on the TMS320C[34]x - Copyright (C) 1994-98, 1999 Free Software Foundation, Inc. - - Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) - and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl). - - This file is part of GNU CC. - - GNU CC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - GNU CC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNU CC; see the file COPYING. If not, write to - the Free Software Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* Some output-actions in c4x.md need these. */ -#include "config.h" -#include "system.h" -#include "toplev.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "basic-block.h" -#include "real.h" -#include "insn-config.h" -#include "insn-attr.h" -#include "insn-codes.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "tree.h" -#include "expr.h" -#include "flags.h" -#include "loop.h" -#include "recog.h" -#include "c-tree.h" - -static int c4x_leaf_function; - -static char *float_reg_names[] = FLOAT_REGISTER_NAMES; - -/* Array of the smallest class containing reg number REGNO, indexed by - REGNO. Used by REGNO_REG_CLASS in c4x.h. We assume that all these - registers are available and set the class to NO_REGS for registers - that the target switches say are unavailable. */ - -enum reg_class c4x_regclass_map[FIRST_PSEUDO_REGISTER] = -{ - /* Reg Modes Saved */ - R0R1_REGS, /* R0 QI, QF, HF No */ - R0R1_REGS, /* R1 QI, QF, HF No */ - R2R3_REGS, /* R2 QI, QF, HF No */ - R2R3_REGS, /* R3 QI, QF, HF No */ - EXT_LOW_REGS, /* R4 QI, QF, HF QI */ - EXT_LOW_REGS, /* R5 QI, QF, HF QI */ - EXT_LOW_REGS, /* R6 QI, QF, HF QF */ - EXT_LOW_REGS, /* R7 QI, QF, HF QF */ - ADDR_REGS, /* AR0 QI No */ - ADDR_REGS, /* AR1 QI No */ - ADDR_REGS, /* AR2 QI No */ - ADDR_REGS, /* AR3 QI QI */ - ADDR_REGS, /* AR4 QI QI */ - ADDR_REGS, /* AR5 QI QI */ - ADDR_REGS, /* AR6 QI QI */ - ADDR_REGS, /* AR7 QI QI */ - DP_REG, /* DP QI No */ - INDEX_REGS, /* IR0 QI No */ - INDEX_REGS, /* IR1 QI No */ - BK_REG, /* BK QI QI */ - SP_REG, /* SP QI No */ - ST_REG, /* ST CC No */ - NO_REGS, /* DIE/IE No */ - NO_REGS, /* IIE/IF No */ - NO_REGS, /* IIF/IOF No */ - INT_REGS, /* RS QI No */ - INT_REGS, /* RE QI No */ - RC_REG, /* RC QI No */ - EXT_REGS, /* R8 QI, QF, HF QI */ - EXT_REGS, /* R9 QI, QF, HF No */ - EXT_REGS, /* R10 QI, QF, HF No */ - EXT_REGS, /* R11 QI, QF, HF No */ -}; - -enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER] = -{ - /* Reg Modes Saved */ - HFmode, /* R0 QI, QF, HF No */ - HFmode, /* R1 QI, QF, HF No */ - HFmode, /* R2 QI, QF, HF No */ - HFmode, /* R3 QI, QF, HF No */ - QFmode, /* R4 QI, QF, HF QI */ - QFmode, /* R5 QI, QF, HF QI */ - QImode, /* R6 QI, QF, HF QF */ - QImode, /* R7 QI, QF, HF QF */ - QImode, /* AR0 QI No */ - QImode, /* AR1 QI No */ - QImode, /* AR2 QI No */ - QImode, /* AR3 QI QI */ - QImode, /* AR4 QI QI */ - QImode, /* AR5 QI QI */ - QImode, /* AR6 QI QI */ - QImode, /* AR7 QI QI */ - VOIDmode, /* DP QI No */ - QImode, /* IR0 QI No */ - QImode, /* IR1 QI No */ - QImode, /* BK QI QI */ - VOIDmode, /* SP QI No */ - VOIDmode, /* ST CC No */ - VOIDmode, /* DIE/IE No */ - VOIDmode, /* IIE/IF No */ - VOIDmode, /* IIF/IOF No */ - QImode, /* RS QI No */ - QImode, /* RE QI No */ - VOIDmode, /* RC QI No */ - QFmode, /* R8 QI, QF, HF QI */ - HFmode, /* R9 QI, QF, HF No */ - HFmode, /* R10 QI, QF, HF No */ - HFmode, /* R11 QI, QF, HF No */ -}; - - -/* Test and compare insns in c4x.md store the information needed to - generate branch and scc insns here. */ - -struct rtx_def *c4x_compare_op0 = NULL_RTX; -struct rtx_def *c4x_compare_op1 = NULL_RTX; - -char *c4x_rpts_cycles_string; -int c4x_rpts_cycles = 0; /* Max. cycles for RPTS */ -char *c4x_cpu_version_string; -int c4x_cpu_version = 40; /* CPU version C30/31/32/40/44 */ - -/* Pragma definitions. */ - -tree code_tree = NULL_TREE; -tree data_tree = NULL_TREE; -tree pure_tree = NULL_TREE; -tree noreturn_tree = NULL_TREE; -tree interrupt_tree = NULL_TREE; - - -/* Override command line options. - Called once after all options have been parsed. - Mostly we process the processor - type and sometimes adjust other TARGET_ options. */ - -void -c4x_override_options () -{ - if (c4x_rpts_cycles_string) - c4x_rpts_cycles = atoi (c4x_rpts_cycles_string); - else - c4x_rpts_cycles = 0; - - if (TARGET_C30) - c4x_cpu_version = 30; - else if (TARGET_C31) - c4x_cpu_version = 31; - else if (TARGET_C32) - c4x_cpu_version = 32; - else if (TARGET_C40) - c4x_cpu_version = 40; - else if (TARGET_C44) - c4x_cpu_version = 44; - else - c4x_cpu_version = 40; - - /* -mcpu=xx overrides -m40 etc. */ - if (c4x_cpu_version_string) - c4x_cpu_version = atoi (c4x_cpu_version_string); - - target_flags &= ~(C30_FLAG | C31_FLAG | C32_FLAG | C40_FLAG | C44_FLAG); - - switch (c4x_cpu_version) - { - case 30: target_flags |= C30_FLAG; break; - case 31: target_flags |= C31_FLAG; break; - case 32: target_flags |= C32_FLAG; break; - case 40: target_flags |= C40_FLAG; break; - case 44: target_flags |= C44_FLAG; break; - default: - warning ("Unknown CPU version %d, using 40.\n", c4x_cpu_version); - c4x_cpu_version = 40; - target_flags |= C40_FLAG; - } - - if (TARGET_C30 || TARGET_C31 || TARGET_C32) - target_flags |= C3X_FLAG; - else - target_flags &= ~C3X_FLAG; - - /* Convert foo / 8.0 into foo * 0.125, etc. */ - flag_fast_math = 1; - - /* We should phase out the following at some stage. - This provides compatibility with the old -mno-aliases option. */ - if (! TARGET_ALIASES && ! flag_argument_noalias) - flag_argument_noalias = 1; -} - -/* This is called before c4x_override_options. */ -void -c4x_optimization_options (level, size) - int level; - int size ATTRIBUTE_UNUSED; -{ - /* Scheduling before register allocation can screw up global - register allocation, especially for functions that use MPY||ADD - instructions. The benefit we gain we get by scheduling before - register allocation is probably marginal anyhow. */ - flag_schedule_insns = 0; - - /* When optimizing, enable use of RPTB instruction. */ - if (level >= 1) - flag_branch_on_count_reg = 1; -} - -/* Write an ASCII string. */ - -#define C4X_ASCII_LIMIT 40 - -void -c4x_output_ascii (stream, ptr, len) - FILE *stream; - unsigned char *ptr; - int len; -{ - char sbuf[C4X_ASCII_LIMIT + 1]; - int s, first, onlys; - - if (len) - { - fprintf (stream, "\t.byte\t"); - first = 1; - } - - for (s = 0; len > 0; --len, ++ptr) - { - onlys = 0; - - /* Escape " and \ with a \". */ - if (*ptr == '\"' || *ptr == '\\') - sbuf[s++] = '\\'; - - /* If printable - add to buff. */ - if (*ptr >= 0x20 && *ptr < 0x7f) - { - sbuf[s++] = *ptr; - if (s < C4X_ASCII_LIMIT - 1) - continue; - onlys = 1; - } - if (s) - { - if (first) - first = 0; - else - fputc (',', stream); - - sbuf[s] = 0; - fprintf (stream, "\"%s\"", sbuf); - s = 0; - } - if (onlys) - continue; - - if (first) - first = 0; - else - fputc (',', stream); - - fprintf (stream, "%d", *ptr); - } - if (s) - { - if (! first) - fputc (',', stream); - - sbuf[s] = 0; - fprintf (stream, "\"%s\"", sbuf); - s = 0; - } - fputc ('\n', stream); -} - - -int -c4x_hard_regno_mode_ok (regno, mode) - int regno; - enum machine_mode mode; -{ - switch (mode) - { -#if Pmode != QImode - case Pmode: /* Pointer (24/32 bits) */ -#endif - case QImode: /* Integer (32 bits) */ - return IS_INT_REG (regno); - - case QFmode: /* Float, Double (32 bits) */ - case HFmode: /* Long Double (40 bits) */ - return IS_EXT_REG (regno); - - case CCmode: /* Condition Codes */ - case CC_NOOVmode: /* Condition Codes */ - return IS_ST_REG (regno); - - case HImode: /* Long Long (64 bits) */ - /* We need two registers to store long longs. Note that - it is much easier to constrain the first register - to start on an even boundary. */ - return IS_INT_REG (regno) - && IS_INT_REG (regno + 1) - && (regno & 1) == 0; - - default: - return 0; /* We don't support these modes */ - } - - return 0; -} - - -/* The TI C3x C compiler register argument runtime model uses 6 registers, - AR2, R2, R3, RC, RS, RE. - - The first two floating point arguments (float, double, long double) - that are found scanning from left to right are assigned to R2 and R3. - - The remaining integer (char, short, int, long) or pointer arguments - are assigned to the remaining registers in the order AR2, R2, R3, - RC, RS, RE when scanning left to right, except for the last named - argument prior to an ellipsis denoting variable number of - arguments. We don't have to worry about the latter condition since - function.c treats the last named argument as anonymous (unnamed). - - All arguments that cannot be passed in registers are pushed onto - the stack in reverse order (right to left). GCC handles that for us. - - c4x_init_cumulative_args() is called at the start, so we can parse - the args to see how many floating point arguments and how many - integer (or pointer) arguments there are. c4x_function_arg() is - then called (sometimes repeatedly) for each argument (parsed left - to right) to obtain the register to pass the argument in, or zero - if the argument is to be passed on the stack. Once the compiler is - happy, c4x_function_arg_advance() is called. - - Don't use R0 to pass arguments in, we use 0 to indicate a stack - argument. */ - -static int c4x_int_reglist[3][6] = -{ - {AR2_REGNO, R2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO}, - {AR2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0}, - {AR2_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0, 0} -}; - -static int c4x_fp_reglist[2] = {R2_REGNO, R3_REGNO}; - - -/* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a - function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ - -void -c4x_init_cumulative_args (cum, fntype, libname) - CUMULATIVE_ARGS *cum; /* argument info to initialize */ - tree fntype; /* tree ptr for function decl */ - rtx libname; /* SYMBOL_REF of library name or 0 */ -{ - tree param, next_param; - - cum->floats = cum->ints = 0; - cum->init = 0; - cum->var = 0; - cum->args = 0; - - if (TARGET_DEBUG) - { - fprintf (stderr, "\nc4x_init_cumulative_args ("); - if (fntype) - { - tree ret_type = TREE_TYPE (fntype); - - fprintf (stderr, "fntype code = %s, ret code = %s", - tree_code_name[(int) TREE_CODE (fntype)], - tree_code_name[(int) TREE_CODE (ret_type)]); - } - else - fprintf (stderr, "no fntype"); - - if (libname) - fprintf (stderr, ", libname = %s", XSTR (libname, 0)); - } - - cum->prototype = (fntype && TYPE_ARG_TYPES (fntype)); - - for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0; - param; param = next_param) - { - tree type; - - next_param = TREE_CHAIN (param); - - type = TREE_VALUE (param); - if (type && type != void_type_node) - { - enum machine_mode mode; - - /* If the last arg doesn't have void type then we have - variable arguments. */ - if (! next_param) - cum->var = 1; - - if ((mode = TYPE_MODE (type))) - { - if (! MUST_PASS_IN_STACK (mode, type)) - { - /* Look for float, double, or long double argument. */ - if (mode == QFmode || mode == HFmode) - cum->floats++; - /* Look for integer, enumeral, boolean, char, or pointer - argument. */ - else if (mode == QImode || mode == Pmode) - cum->ints++; - } - } - cum->args++; - } - } - - if (TARGET_DEBUG) - fprintf (stderr, "%s%s, args = %d)\n", - cum->prototype ? ", prototype" : "", - cum->var ? ", variable args" : "", - cum->args); -} - - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - -void -c4x_function_arg_advance (cum, mode, type, named) - CUMULATIVE_ARGS *cum; /* current arg information */ - enum machine_mode mode; /* current arg mode */ - tree type; /* type of the argument or 0 if lib support */ - int named; /* whether or not the argument was named */ -{ - if (TARGET_DEBUG) - fprintf (stderr, "c4x_function_adv(mode=%s, named=%d)\n\n", - GET_MODE_NAME (mode), named); - if (! TARGET_MEMPARM - && named - && type - && ! MUST_PASS_IN_STACK (mode, type)) - { - /* Look for float, double, or long double argument. */ - if (mode == QFmode || mode == HFmode) - cum->floats++; - /* Look for integer, enumeral, boolean, char, or pointer argument. */ - else if (mode == QImode || mode == Pmode) - cum->ints++; - } - else if (! TARGET_MEMPARM && ! type) - { - /* Handle libcall arguments. */ - if (mode == QFmode || mode == HFmode) - cum->floats++; - else if (mode == QImode || mode == Pmode) - cum->ints++; - } - return; -} - - -/* Define where to put the arguments to a function. Value is zero to - push the argument on the stack, or a hard register in which to - store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ - -struct rtx_def * -c4x_function_arg (cum, mode, type, named) - CUMULATIVE_ARGS *cum; /* current arg information */ - enum machine_mode mode; /* current arg mode */ - tree type; /* type of the argument or 0 if lib support */ - int named; /* != 0 for normal args, == 0 for ... args */ -{ - int reg = 0; /* default to passing argument on stack */ - - if (! cum->init) - { - /* We can handle at most 2 floats in R2, R3 */ - cum->maxfloats = (cum->floats > 2) ? 2 : cum->floats; - - /* We can handle at most 6 integers minus number of floats passed - in registers. */ - cum->maxints = (cum->ints > 6 - cum->maxfloats) ? - 6 - cum->maxfloats : cum->ints; - - /* If there is no prototype, assume all the arguments are integers. */ - if (! cum->prototype) - cum->maxints = 6; - - cum->ints = cum->floats = 0; - cum->init = 1; - } - - if (! TARGET_MEMPARM - && named - && type - && ! MUST_PASS_IN_STACK (mode, type)) - { - /* Look for float, double, or long double argument. */ - if (mode == QFmode || mode == HFmode) - { - if (cum->floats < cum->maxfloats) - reg = c4x_fp_reglist[cum->floats]; - } - /* Look for integer, enumeral, boolean, char, or pointer argument. */ - else if (mode == QImode || mode == Pmode) - { - if (cum->ints < cum->maxints) - reg = c4x_int_reglist[cum->maxfloats][cum->ints]; - } - } - else if (! TARGET_MEMPARM && ! type) - { - /* We could use a different argument calling model for libcalls, - since we're only calling functions in libgcc. Thus we could - pass arguments for long longs in registers rather than on the - stack. In the meantime, use the odd TI format. We make the - assumption that we won't have more than two floating point - args, six integer args, and that all the arguments are of the - same mode. */ - if (mode == QFmode || mode == HFmode) - reg = c4x_fp_reglist[cum->floats]; - else if (mode == QImode || mode == Pmode) - reg = c4x_int_reglist[0][cum->ints]; - } - - if (TARGET_DEBUG) - { - fprintf (stderr, "c4x_function_arg(mode=%s, named=%d", - GET_MODE_NAME (mode), named); - if (reg) - fprintf (stderr, ", reg=%s", reg_names[reg]); - else - fprintf (stderr, ", stack"); - fprintf (stderr, ")\n"); - } - if (reg) - return gen_rtx_REG (mode, reg); - else - return NULL_RTX; -} - - -static int -c4x_isr_reg_used_p (regno) - int regno; -{ - /* Don't save/restore FP or ST, we handle them separately. */ - if (regno == FRAME_POINTER_REGNUM - || IS_ST_REG (regno)) - return 0; - - /* We could be a little smarter abut saving/restoring DP. - We'll only save if for the big memory model or if - we're paranoid. ;-) */ - if (IS_DP_REG (regno)) - return ! TARGET_SMALL || TARGET_PARANOID; - - /* Only save/restore regs in leaf function that are used. */ - if (c4x_leaf_function) - return regs_ever_live[regno] && fixed_regs[regno] == 0; - - /* Only save/restore regs that are used by the ISR and regs - that are likely to be used by functions the ISR calls - if they are not fixed. */ - return IS_EXT_REG (regno) - || ((regs_ever_live[regno] || call_used_regs[regno]) - && fixed_regs[regno] == 0); -} - - -static int -c4x_leaf_function_p () -{ - /* A leaf function makes no calls, so we only need - to save/restore the registers we actually use. - For the global variable leaf_function to be set, we need - to define LEAF_REGISTERS and all that it entails. - Let's check ourselves... */ - - if (lookup_attribute ("leaf_pretend", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) - return 1; - - /* Use the leaf_pretend attribute at your own risk. This is a hack - to speed up ISRs that call a function infrequently where the - overhead of saving and restoring the additional registers is not - warranted. You must save and restore the additional registers - required by the called function. Caveat emptor. Here's enough - rope... */ - - if (leaf_function_p ()) - return 1; - - return 0; -} - - -static int -c4x_assembler_function_p () -{ - tree type; - - type = TREE_TYPE (current_function_decl); - return lookup_attribute ("assembler", TYPE_ATTRIBUTES (type)) != NULL; -} - - -static int -c4x_interrupt_function_p () -{ - if (lookup_attribute ("interrupt", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) - return 1; - - /* Look for TI style c_intnn */ - return current_function_name[0] == 'c' - && current_function_name[1] == '_' - && current_function_name[2] == 'i' - && current_function_name[3] == 'n' - && current_function_name[4] == 't' - && isdigit (current_function_name[5]) - && isdigit (current_function_name[6]); -} - - -/* Write function prologue. */ - -void -c4x_function_prologue (file, size) - FILE *file; - int size; -{ - int regno; - -/* In functions where ar3 is not used but frame pointers are still - specified, frame pointers are not adjusted (if >= -O2) and this is - used so it won't be needlessly push the frame pointer. */ - int dont_push_ar3; - - /* For __assembler__ function don't build a prologue. */ - if (c4x_assembler_function_p ()) - { - fprintf (file, "; *** Assembler Function ***\n"); - return; - } - - /* For __interrupt__ function build specific prologue. */ - if (c4x_interrupt_function_p ()) - { - c4x_leaf_function = c4x_leaf_function_p (); - fprintf (file, "; *** Interrupt Entry %s ***\n", - c4x_leaf_function ? "(leaf)" : ""); - - fprintf (file, "\tpush\tst\n"); - if (size) - { - fprintf (file, "\tpush\tar3\n\tldi\tsp,ar3\n"); - /* FIXME: Assume ISR doesn't require more than 32767 words - of local variables. */ - if (size > 32767) - error ("ISR %s requires %d words of local variables, " - "maximum is 32767.", current_function_name, size); - fprintf (file, "\taddi\t%d,sp\n", size); - } - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - if (c4x_isr_reg_used_p (regno)) - { - fprintf (file, "\tpush\t%s\n", reg_names[regno]); - if (IS_EXT_REG (regno)) /* save 32MSB of R0--R11 */ - fprintf (file, "\tpushf\t%s\n", float_reg_names[regno]); - } - } - /* We need to clear the repeat mode flag if the ISR is - going to use a RPTB instruction or uses the RC, RS, or RE - registers. */ - if (regs_ever_live[RC_REGNO] - || regs_ever_live[RS_REGNO] - || regs_ever_live[RE_REGNO]) - fprintf (file, "\tandn\t0100h,st\n"); - - /* Reload DP reg if we are paranoid about some turkey - violating small memory model rules. */ - if (TARGET_SMALL && TARGET_PARANOID) - fprintf (file, TARGET_C3X ? - "\tldp\t@data_sec\n" : - "\tldpk\t@data_sec\n"); - } - else - { - if (frame_pointer_needed) - { - if ((size != 0) - || (current_function_args_size != 0) - || (optimize < 2)) - { - fprintf (file, "\tpush\tar3\n"); - fprintf (file, "\tldi\tsp,ar3\n"); - dont_push_ar3 = 1; - } - else - { - /* Since ar3 is not used, we don't need to push it. */ - dont_push_ar3 = 1; - } - } - else - { - /* If we use ar3, we need to push it. */ - dont_push_ar3 = 0; - if ((size != 0) || (current_function_args_size != 0)) - { - /* If we are omitting the frame pointer, we still have - to make space for it so the offsets are correct - unless we don't use anything on the stack at all. */ - size += 1; - } - } - - if (size > 32767) - { - /* Local vars are too big, it will take multiple operations - to increment SP. */ - if (TARGET_C3X) - { - fprintf (file, "\tldi\t%d,r1\n", size >> 16); - fprintf (file, "\tlsh\t16,r1\n"); - } - else - fprintf (file, "\tldhi\t%d,r1\n", size >> 16); - fprintf (file, "\tor\t%d,r1\n", size & 0xffff); - fprintf (file, "\taddi\tr1,sp\n"); - } - else if (size != 0) - { - /* Local vars take up less than 32767 words, so we can directly - add the number. */ - fprintf (file, "\taddi\t%d,sp\n", size); - } - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - if (regs_ever_live[regno] && ! call_used_regs[regno]) - { - if ((regno == R6_REGNO) || (regno == R7_REGNO)) - { - /* R6 and R7 are saved as floating point */ - if (TARGET_PRESERVE_FLOAT) - fprintf (file, "\tpush\t%s\n", reg_names[regno]); - fprintf (file, "\tpushf\t%s\n", float_reg_names[regno]); - } - else if ((! dont_push_ar3) || (regno != AR3_REGNO)) - { - fprintf (file, "\tpush\t%s\n", reg_names[regno]); - } - } - } - } -} - - -/* Write function epilogue. */ - -void -c4x_function_epilogue (file, size) - FILE *file; - int size; -{ - int regno; - int restore_count = 0; - int delayed_jump = 0; - int dont_pop_ar3; - rtx insn; - - insn = get_last_insn (); - if (insn && GET_CODE (insn) == NOTE) - insn = prev_nonnote_insn (insn); - - if (insn && GET_CODE (insn) == BARRIER) - return; - - /* For __assembler__ function build no epilogue. */ - if (c4x_assembler_function_p ()) - { - fprintf (file, "\trets\n"); /* Play it safe */ - return; - } - -#ifdef FUNCTION_BLOCK_PROFILER_EXIT - if (profile_block_flag == 2) - { - FUNCTION_BLOCK_PROFILER_EXIT (file); - } -#endif - - /* For __interrupt__ function build specific epilogue. */ - if (c4x_interrupt_function_p ()) - { - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno) - { - if (! c4x_isr_reg_used_p (regno)) - continue; - if (IS_EXT_REG (regno)) - fprintf (file, "\tpopf\t%s\n", float_reg_names[regno]); - fprintf (file, "\tpop\t%s\n", reg_names[regno]); - } - if (size) - { - fprintf (file, "\tsubi\t%d,sp\n", size); - fprintf (file, "\tpop\tar3\n"); - } - fprintf (file, "\tpop\tst\n"); - fprintf (file, "\treti\n"); - } - else - { - if (frame_pointer_needed) - { - if ((size != 0) - || (current_function_args_size != 0) - || (optimize < 2)) - { - /* R2 holds the return value. */ - fprintf (file, "\tldi\t*-ar3(1),r2\n"); - - /* We already have the return value and the fp, - so we need to add those to the stack. */ - size += 2; - delayed_jump = 1; - restore_count = 1; - dont_pop_ar3 = 1; - } - else - { - /* Since ar3 is not used for anything, we don't need to - pop it. */ - dont_pop_ar3 = 1; - } - } - else - { - dont_pop_ar3 = 0; /* If we use ar3, we need to pop it */ - if (size || current_function_args_size) - { - /* If we are ommitting the frame pointer, we still have - to make space for it so the offsets are correct - unless we don't use anything on the stack at all. */ - size += 1; - } - } - - /* Now get the number of instructions required to restore the - registers. */ - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) - { - if ((regs_ever_live[regno] && ! call_used_regs[regno]) - && ((! dont_pop_ar3) || (regno != AR3_REGNO))) - { - restore_count++; - if (TARGET_PRESERVE_FLOAT - && ((regno == R6_REGNO) || (regno == R7_REGNO))) - restore_count++; - } - } - - /* Get the number of instructions required to restore the stack. */ - if (size > 32767) - restore_count += (TARGET_C3X ? 4 : 3); - else if (size != 0) - restore_count += 1; - - if (delayed_jump && (restore_count < 3)) - { - /* We don't have enough instructions to account for the delayed - branch, so put some nops in. */ - - fprintf (file, "\tbud\tr2\n"); - while (restore_count < 3) - { - fprintf (file, "\tnop\n"); - restore_count++; - } - restore_count = 0; - } - - /* Now restore the saved registers, putting in the delayed branch - where required. */ - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) - { - if (regs_ever_live[regno] && ! call_used_regs[regno]) - { - if (regno == AR3_REGNO && dont_pop_ar3) - continue; - - if (delayed_jump && (restore_count == 3)) - fprintf (file, "\tbud\tr2\n"); - - /* R6 and R7 are saved as floating point. */ - if ((regno == R6_REGNO) || (regno == R7_REGNO)) - { - fprintf (file, "\tpopf\t%s\n", float_reg_names[regno]); - if (TARGET_PRESERVE_FLOAT) - { - restore_count--; - if (delayed_jump && (restore_count == 3)) - fprintf (file, "\tbud\tr2\n"); - fprintf (file, "\tpop\t%s\n", reg_names[regno]); - } - } - else - fprintf (file, "\tpop\t%s\n", reg_names[regno]); - restore_count--; - } - } - - if (delayed_jump && (restore_count == 3)) - fprintf (file, "\tbud\tr2\n"); - - if (frame_pointer_needed) - { - if ((size != 0) - || (current_function_args_size != 0) - || (optimize < 2)) - { - /* Restore the old FP. */ - fprintf (file, "\tldi\t*ar3,ar3\n"); - restore_count--; - - if (delayed_jump && (restore_count == 3)) - fprintf (file, "\tbud\tr2\n"); - } - } - - if (size > 32767) - { - /* Local vars are too big, it will take multiple operations - to decrement SP. */ - if (TARGET_C3X) - { - fprintf (file, "\tldi\t%d,r3\n", size >> 16); - if (delayed_jump) - fprintf (file, "\tbud\tr2\n"); - fprintf (file, "\tlsh\t16,r3\n"); - } - else - fprintf (file, "\tldhi\t%d,r3\n", size >> 16); - fprintf (file, "\tor\t%d,r3\n", size & 0xffff); - fprintf (file, "\tsubi\tr3,sp\n"); - } - else if (size != 0) - { - /* Local vars take up less than 32768 words, so we can directly - subtract the number. */ - fprintf (file, "\tsubi\t%d,sp\n", size); - } - - if (! delayed_jump) - fprintf (file, "\trets\n"); - } -} - -int -c4x_null_epilogue_p () -{ - int regno; - - if (reload_completed - && ! c4x_assembler_function_p () - && ! c4x_interrupt_function_p () - && ! current_function_calls_alloca - && ! current_function_args_size - && ! (profile_block_flag == 2) - && ! (optimize < 2) - && ! get_frame_size ()) - { - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) - if (regs_ever_live[regno] && ! call_used_regs[regno] - && (regno != AR3_REGNO)) - return 0; - return 1; - } - return 0; -} - - -void -c4x_emit_libcall (name, code, dmode, smode, noperands, operands) - char *name; - enum rtx_code code; - enum machine_mode dmode; - enum machine_mode smode; - int noperands; - rtx *operands; -{ - rtx ret; - rtx insns; - rtx libcall; - rtx equiv; - - start_sequence (); - libcall = gen_rtx_SYMBOL_REF (Pmode, name); - switch (noperands) - { - case 2: - ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1, - operands[1], smode); - equiv = gen_rtx (code, dmode, operands[1]); - break; - - case 3: - ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 2, - operands[1], smode, operands[2], smode); - equiv = gen_rtx (code, dmode, operands[1], operands[2]); - break; - - default: - fatal ("c4x_emit_libcall: Bad number of operands"); - } - - insns = get_insns (); - end_sequence (); - emit_libcall_block (insns, operands[0], ret, equiv); -} - - -void -c4x_emit_libcall3 (name, code, mode, operands) - const char *name; - enum rtx_code code; - enum machine_mode mode; - rtx *operands; -{ - return c4x_emit_libcall (name, code, mode, mode, 3, operands); -} - -void -c4x_emit_libcall_mulhi (name, code, mode, operands) - char *name; - enum rtx_code code; - enum machine_mode mode; - rtx *operands; -{ - rtx ret; - rtx insns; - rtx libcall; - rtx equiv; - - start_sequence (); - libcall = gen_rtx_SYMBOL_REF (Pmode, name); - ret = emit_library_call_value (libcall, NULL_RTX, 1, mode, 2, - operands[1], mode, operands[2], mode); - equiv = gen_rtx_TRUNCATE (mode, - gen_rtx_LSHIFTRT (HImode, - gen_rtx_MULT (HImode, - gen_rtx (code, HImode, operands[1]), - gen_rtx (code, HImode, operands[2])), - GEN_INT (32))); - insns = get_insns (); - end_sequence (); - emit_libcall_block (insns, operands[0], ret, equiv); -} - - -enum reg_class -c4x_preferred_reload_class (x, class) - rtx x; - enum reg_class class; -{ - return class; -} - - -enum reg_class -c4x_limit_reload_class (mode, class) - enum machine_mode mode ATTRIBUTE_UNUSED; - enum reg_class class; -{ - return class; -} - - -enum reg_class -c4x_secondary_memory_needed (class1, class2, mode) - enum reg_class class1 ATTRIBUTE_UNUSED; - enum reg_class class2 ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return 0; -} - - -int -c4x_check_legit_addr (mode, addr, strict) - enum machine_mode mode; - rtx addr; - int strict; -{ - rtx base = NULL_RTX; /* Base register (AR0-AR7) */ - rtx indx = NULL_RTX; /* Index register (IR0,IR1) */ - rtx disp = NULL_RTX; /* Displacement */ - enum rtx_code code; - - code = GET_CODE (addr); - switch (code) - { - /* Register indirect with auto increment/decrement. We don't - allow SP here---push_operand should recognise an operand - being pushed on the stack. */ - - case PRE_DEC: - case POST_DEC: - if (mode != QImode && mode != QFmode) - return 0; - case PRE_INC: - case POST_INC: - base = XEXP (addr, 0); - if (! REG_P (base)) - return 0; - break; - - case PRE_MODIFY: - case POST_MODIFY: - { - rtx op0 = XEXP (addr, 0); - rtx op1 = XEXP (addr, 1); - - if (mode != QImode && mode != QFmode) - return 0; - - if (! REG_P (op0) - || (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)) - return 0; - base = XEXP (op1, 0); - if (base != op0) - return 0; - if (REG_P (XEXP (op1, 1))) - indx = XEXP (op1, 1); - else - disp = XEXP (op1, 1); - } - break; - - /* Register indirect. */ - case REG: - base = addr; - break; - - /* Register indirect with displacement or index. */ - case PLUS: - { - rtx op0 = XEXP (addr, 0); - rtx op1 = XEXP (addr, 1); - enum rtx_code code0 = GET_CODE (op0); - - switch (code0) - { - case USE: - /* The uses are put in to avoid problems - with referenced things disappearing. */ - return c4x_check_legit_addr (mode, op1, strict); - - case PLUS: - /* This is another reference to keep things - from disappearing, but it contains a plus - of a use and DP. */ - if (GET_CODE (XEXP (op0, 0)) == USE) - return c4x_check_legit_addr (mode, op1, strict); - return 0; - - case REG: - if (REG_P (op1)) - { - base = op0; /* base + index */ - indx = op1; - if (IS_INDEX_REGNO (base) || IS_ADDR_REGNO (indx)) - { - base = op1; - indx = op0; - } - } - else - { - base = op0; /* base + displacement */ - disp = op1; - } - break; - - default: - return 0; - } - } - break; - - /* Direct addressing with some work for the assembler... */ - case CONST: - if (GET_CODE (XEXP (addr, 0)) == PLUS - && (GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF - || GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF) - && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT) - return 1; - - /* Direct addressing. */ - case SYMBOL_REF: - case LABEL_REF: - return 1; - - /* Do not allow direct memory access to absolute addresses. - This is more pain than its worth, especially for the - small memory model where we can't guarantee that - this address is within the data page---we don't want - to modify the DP register in the small memory model, - even temporarily, since an interrupt can sneak in.... */ - case CONST_INT: - return 0; - - /* Indirect indirect addressing. */ - case MEM: - return 0; - - case CONST_DOUBLE: - fatal_insn ("Using CONST_DOUBLE for address", addr); - - default: - return 0; - } - - /* Validate the base register. */ - if (base) - { - /* Check that the address is offsettable for HImode and HFmode. */ - if (indx && (mode == HImode || mode == HFmode)) - return 0; - - /* Handle DP based stuff. */ - if (REGNO (base) == DP_REGNO) - return 1; - if (strict && ! REGNO_OK_FOR_BASE_P (REGNO (base))) - return 0; - else if (! strict && ! IS_ADDR_OR_PSEUDO_REGNO (base)) - return 0; - } - - /* Now validate the index register. */ - if (indx) - { - if (GET_CODE (indx) != REG) - return 0; - if (strict && ! REGNO_OK_FOR_INDEX_P (REGNO (indx))) - return 0; - else if (! strict && ! IS_INDEX_OR_PSEUDO_REGNO (indx)) - return 0; - } - - /* Validate displacement. */ - if (disp) - { - if (GET_CODE (disp) != CONST_INT) - return 0; - if (mode == HImode || mode == HFmode) - { - /* The offset displacement must be legitimate. */ - if (! IS_DISP8_OFF_CONST (INTVAL (disp))) - return 0; - } - else - { - if (! IS_DISP8_CONST (INTVAL (disp))) - return 0; - } - /* Can't add an index with a disp. */ - if (indx) - return 0; - } - return 1; -} - - -rtx -c4x_legitimize_address (orig, mode) - rtx orig ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return NULL_RTX; -} - - -/* Provide the costs of an addressing mode that contains ADDR. - If ADDR is not a valid address, its cost is irrelevant. - This is used in cse and loop optimisation to determine - if it is worthwhile storing a common address into a register. - Unfortunately, the C4x address cost depends on other operands. */ - -int -c4x_address_cost (addr) -rtx addr; -{ - switch (GET_CODE (addr)) - { - case REG: - return 1; - - case CONST: - { - rtx offset = const0_rtx; - addr = eliminate_constant_term (addr, &offset); - - if (GET_CODE (addr) == LABEL_REF) - return 3; - - if (GET_CODE (addr) != SYMBOL_REF) - return 4; - - if (INTVAL (offset) == 0) - return 3; - } - - /* fall through */ - - case POST_INC: - case POST_DEC: - case PRE_INC: - case PRE_DEC: - return 1; - - case SYMBOL_REF: - case LABEL_REF: - return TARGET_SMALL ? 3 : 4; - - case PLUS: - { - register rtx op0 = XEXP (addr, 0); - register rtx op1 = XEXP (addr, 1); - - if (GET_CODE (op0) != REG) - break; - - switch (GET_CODE (op1)) - { - default: - break; - - case REG: - return 2; - - case CONST_INT: - if (IS_DISP1_CONST (INTVAL (op1))) - return 1; - - if (! TARGET_C3X && IS_UINT5_CONST (INTVAL (op1))) - return 2; - - return 3; - } - } - default: - } - - return 4; -} - - -rtx -c4x_gen_compare_reg (code, x, y) - enum rtx_code code; - rtx x, y; -{ - enum machine_mode mode = SELECT_CC_MODE (code, x, y); - rtx cc_reg; - - if (mode == CC_NOOVmode - && (code == LE || code == GE || code == LT || code == GT)) - return NULL_RTX; - - cc_reg = gen_rtx_REG (mode, ST_REGNO); - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, - gen_rtx_COMPARE (mode, x, y))); - return cc_reg; -} - -char * -c4x_output_cbranch (form, seq) - char *form; - rtx seq; -{ - int delayed = 0; - int annultrue = 0; - int annulfalse = 0; - rtx delay; - char *cp; - static char str[100]; - - if (final_sequence) - { - delay = XVECEXP (final_sequence, 0, 1); - delayed = ! INSN_ANNULLED_BRANCH_P (seq); - annultrue = INSN_ANNULLED_BRANCH_P (seq) && ! INSN_FROM_TARGET_P (delay); - annulfalse = INSN_ANNULLED_BRANCH_P (seq) && INSN_FROM_TARGET_P (delay); - } - strcpy (str, form); - cp = &str [strlen (str)]; - if (delayed) - { - *cp++ = '%'; - *cp++ = '#'; - } - if (annultrue) - { - *cp++ = 'a'; - *cp++ = 't'; - } - if (annulfalse) - { - *cp++ = 'a'; - *cp++ = 'f'; - } - *cp++ = '\t'; - *cp++ = '%'; - *cp++ = 'l'; - *cp++ = '1'; - *cp = 0; - return str; -} - -void -c4x_print_operand (file, op, letter) - FILE *file; /* file to write to */ - rtx op; /* operand to print */ - int letter; /* % or 0 */ -{ - rtx op1; - enum rtx_code code; - - switch (letter) - { - case '#': /* delayed */ - if (final_sequence) - asm_fprintf (file, "d"); - return; - } - - code = GET_CODE (op); - switch (letter) - { - case 'A': /* direct address */ - if (code == CONST_INT || code == SYMBOL_REF) - asm_fprintf (file, "@"); - break; - - case 'C': /* call */ - if (code != MEM) - fatal_insn ("c4x_print_operand: %%C inconsistency", op); - op1 = XEXP (op, 0); - SYMBOL_REF_FLAG (op1) = 1; - output_addr_const (file, op1); - return; - - case 'H': /* sethi */ - if (code == SYMBOL_REF) - SYMBOL_REF_FLAG (op) = 1; - break; - - case 'I': /* reversed condition */ - code = reverse_condition (code); - break; - - case 'L': /* log 2 of constant */ - if (code != CONST_INT) - fatal_insn ("c4x_print_operand: %%L inconsistency", op); - fprintf (file, "%d", exact_log2 (INTVAL (op))); - return; - - case 'N': /* ones complement of small constant */ - if (code != CONST_INT) - fatal_insn ("c4x_print_operand: %%N inconsistency", op); - fprintf (file, "%d", ~INTVAL (op)); - return; - - case 'K': /* generate ldp(k) if direct address */ - if (! TARGET_SMALL - && code == MEM - && GET_CODE (XEXP (op, 0)) == PLUS - && GET_CODE(XEXP (XEXP (op, 0), 0)) == REG - && REGNO(XEXP (XEXP (op, 0), 0)) == DP_REGNO) - { - op1 = XEXP (XEXP (op, 0), 1); - if (GET_CODE(op1) == CONST_INT || GET_CODE(op1) == SYMBOL_REF) - { - asm_fprintf (file, "\t%s\t", TARGET_C3X ? "ldp" : "ldpk"); - output_address (XEXP (adj_offsettable_operand (op, 1), 0)); - asm_fprintf (file, "\n"); - } - } - return; - - case 'M': /* generate ldp(k) if direct address */ - if (! TARGET_SMALL /* only used in asm statements */ - && code == MEM - && (GET_CODE (XEXP (op, 0)) == CONST - || GET_CODE (XEXP (op, 0)) == SYMBOL_REF)) - { - asm_fprintf (file, "%s\t", TARGET_C3X ? "ldp" : "ldpk"); - output_address (XEXP (op, 0)); - asm_fprintf (file, "\n\t"); - } - return; - - case 'O': /* offset address */ - if (code == MEM && c4x_autoinc_operand (op, Pmode)) - break; - else if (code == MEM) - output_address (XEXP (adj_offsettable_operand (op, 1), 0)); - else if (code == REG) - fprintf (file, "%s", reg_names[REGNO (op) + 1]); - else - fatal_insn ("c4x_print_operand: %%O inconsistency", op); - return; - - case 'R': /* call register */ - op1 = XEXP (op, 0); - if (code != MEM || GET_CODE (op1) != REG) - fatal_insn ("c4x_print_operand: %%R inconsistency", op); - else - fprintf (file, "%s", reg_names[REGNO (op1)]); - return; - - default: - break; - } - - switch (code) - { - case REG: - if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT) - fprintf (file, "%s", float_reg_names[REGNO (op)]); - else - fprintf (file, "%s", reg_names[REGNO (op)]); - break; - - case MEM: - output_address (XEXP (op, 0)); - break; - - case CONST_DOUBLE: - { - char str[30]; - REAL_VALUE_TYPE r; - - REAL_VALUE_FROM_CONST_DOUBLE (r, op); - REAL_VALUE_TO_DECIMAL (r, "%20f", str); - fprintf (file, "%s", str); - } - break; - - case CONST_INT: - fprintf (file, "%d", INTVAL (op)); - break; - - case NE: - asm_fprintf (file, "ne"); - break; - - case EQ: - asm_fprintf (file, "eq"); - break; - - case GE: - asm_fprintf (file, "ge"); - break; - - case GT: - asm_fprintf (file, "gt"); - break; - - case LE: - asm_fprintf (file, "le"); - break; - - case LT: - asm_fprintf (file, "lt"); - break; - - case GEU: - asm_fprintf (file, "hs"); - break; - - case GTU: - asm_fprintf (file, "hi"); - break; - - case LEU: - asm_fprintf (file, "ls"); - break; - - case LTU: - asm_fprintf (file, "lo"); - break; - - case SYMBOL_REF: - output_addr_const (file, op); - break; - - case CONST: - output_addr_const (file, XEXP (op, 0)); - break; - - case CODE_LABEL: - break; - - default: - fatal_insn ("c4x_print_operand: Bad operand case", op); - break; - } -} - - -void -c4x_print_operand_address (file, addr) - FILE *file; - rtx addr; -{ - switch (GET_CODE (addr)) - { - case REG: - fprintf (file, "*%s", reg_names[REGNO (addr)]); - break; - - case PRE_DEC: - fprintf (file, "*--%s", reg_names[REGNO (XEXP (addr, 0))]); - break; - - case POST_INC: - fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]); - break; - - case POST_MODIFY: - { - rtx op0 = XEXP (XEXP (addr, 1), 0); - rtx op1 = XEXP (XEXP (addr, 1), 1); - - if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1)) - fprintf (file, "*%s++(%s)", reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); - else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0) - fprintf (file, "*%s++(%d)", reg_names[REGNO (op0)], - INTVAL (op1)); - else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0) - fprintf (file, "*%s--(%d)", reg_names[REGNO (op0)], - -INTVAL (op1)); - else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1)) - fprintf (file, "*%s--(%s)", reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); - else - fatal_insn ("c4x_print_operand_address: Bad post_modify", addr); - } - break; - - case PRE_MODIFY: - { - rtx op0 = XEXP (XEXP (addr, 1), 0); - rtx op1 = XEXP (XEXP (addr, 1), 1); - - if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1)) - fprintf (file, "*++%s(%s)", reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); - else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0) - fprintf (file, "*++%s(%d)", reg_names[REGNO (op0)], - INTVAL (op1)); - else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0) - fprintf (file, "*--%s(%d)", reg_names[REGNO (op0)], - -INTVAL (op1)); - else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1)) - fprintf (file, "*--%s(%s)", reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); - else - fatal_insn ("c4x_print_operand_address: Bad pre_modify", addr); - } - break; - - case PRE_INC: - fprintf (file, "*++%s", reg_names[REGNO (XEXP (addr, 0))]); - break; - - case POST_DEC: - fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]); - break; - - case PLUS: /* Indirect with displacement. */ - { - rtx op0 = XEXP (addr, 0); - rtx op1 = XEXP (addr, 1); - enum rtx_code code0 = GET_CODE (op0); - - if (code0 == USE || code0 == PLUS) - { - asm_fprintf (file, "@"); - output_addr_const (file, op1); - } - else if (REG_P (op0)) - { - if (REGNO (op0) == DP_REGNO) - { - c4x_print_operand_address (file, op1); - } - else if (REG_P (op1)) - { - if (IS_INDEX_REGNO (op0)) - { - fprintf (file, "*+%s(%s)", - reg_names[REGNO (op1)], - reg_names[REGNO (op0)]); /* index + base */ - } - else - { - fprintf (file, "*+%s(%s)", - reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); /* base + index */ - } - } - else if (INTVAL (op1) < 0) - { - fprintf (file, "*-%s(%d)", - reg_names[REGNO (op0)], - -INTVAL (op1)); /* base - displacement */ - } - else - { - fprintf (file, "*+%s(%d)", - reg_names[REGNO (op0)], - INTVAL (op1)); /* base + displacement */ - } - } - } - break; - - case CONST: - case SYMBOL_REF: - case LABEL_REF: - if (! SYMBOL_REF_FLAG (addr)) - fprintf (file, "@"); - output_addr_const (file, addr); - SYMBOL_REF_FLAG (addr) = 0; - break; - - /* We shouldn't access CONST_INT addresses. */ - case CONST_INT: - - default: - fatal_insn ("c4x_print_operand_address: Bad operand case", addr); - break; - } -} - - -static int -c4x_immed_float_p (operand) - rtx operand; -{ - long convval[2]; - int exponent; - REAL_VALUE_TYPE r; - - REAL_VALUE_FROM_CONST_DOUBLE (r, operand); - if (GET_MODE (operand) == HFmode) - REAL_VALUE_TO_TARGET_DOUBLE (r, convval); - else - { - REAL_VALUE_TO_TARGET_SINGLE (r, convval[0]); - convval[1] = 0; - } - - /* sign extend exponent */ - exponent = (((convval[0] >> 24) & 0xff) ^ 0x80) - 0x80; - if (exponent == -128) - return 1; /* 0.0 */ - if ((convval[0] & 0x00000fff) != 0 || convval[1] != 0) - return 0; /* Precision doesn't fit */ - return (exponent <= 7) /* Positive exp */ - && (exponent >= -7); /* Negative exp */ -} - - -/* This function checks for an insn operand that requires direct - addressing and inserts a load of the DP register prior to the - insn if the big memory model is being compiled for. Immediate - operands that do not fit within the opcode field get changed - into memory references using direct addressing. At this point - all pseudos have been converted to hard registers. */ - -int -c4x_scan_for_ldp (newop, insn, operand0) - rtx *newop; - rtx insn; - rtx operand0; -{ - int i; - char *format_ptr; - rtx op0, op1, op2, addr; - rtx operand = *newop; - - switch (GET_CODE (operand)) - { - case MEM: - op0 = XEXP (operand, 0); - - /* We have something we need to emit a load dp insn for. - The first operand should hold the rtx for the instruction - required. */ - - switch (GET_CODE (op0)) - { - case CONST_INT: - fatal_insn ("c4x_scan_for_ldp: Direct memory access to const_int", - op0); - break; - - case CONST: - case SYMBOL_REF: - if (! TARGET_C3X && ! TARGET_SMALL - && recog_memoized (insn) == CODE_FOR_movqi_noclobber - && ((addr = find_reg_note (insn, REG_EQUAL, NULL_RTX)) - || (addr = find_reg_note (insn, REG_EQUIV, NULL_RTX))) - && (IS_STD_OR_PSEUDO_REGNO (operand0))) - { - addr = XEXP (addr, 0); - if (GET_CODE (addr) == CONST_INT) - { - op1 = GEN_INT (INTVAL (addr) & ~0xffff); - emit_insn_before (gen_movqi (operand0, op1), insn); - op1 = GEN_INT (INTVAL (addr) & 0xffff); - emit_insn_before (gen_iorqi3_noclobber (operand0, - operand0, op1), insn); - delete_insn (insn); - return 1; - } - else if (GET_CODE (addr) == SYMBOL_REF) - { - emit_insn_before (gen_set_high_use (operand0, addr, addr), - insn); - emit_insn_before (gen_set_ior_lo_use (operand0, addr, addr), - insn); - delete_insn (insn); - return 1; - } - else if (GET_CODE (addr) == CONST - && GET_CODE (op1 = XEXP (addr, 0)) == PLUS - && GET_CODE (op2 = XEXP (op1, 0)) == SYMBOL_REF - && GET_CODE (XEXP (op1, 1)) == CONST_INT) - { - emit_insn_before (gen_set_high_use (operand0, addr, op2), - insn); - emit_insn_before (gen_set_ior_lo_use (operand0, addr, op2), - insn); - delete_insn (insn); - return 1; - } - } - if (! TARGET_SMALL) - emit_insn_before (gen_set_ldp (gen_rtx_REG (Pmode, DP_REGNO), - operand), insn); - - /* Replace old memory reference with direct reference. */ - *newop = gen_rtx_MEM (GET_MODE (operand), - gen_rtx_PLUS (Pmode, - gen_rtx_REG (Pmode, DP_REGNO), - op0)); - - /* Use change_address? */ - RTX_UNCHANGING_P (*newop) = RTX_UNCHANGING_P (operand); - MEM_COPY_ATTRIBUTES (*newop, operand); - break; - - default: - break; - } - - return 0; - - case CONST_INT: - if (SMALL_CONST (INTVAL (operand), insn)) - break; - fatal_insn ("Immediate integer too large", insn); - - case CONST_DOUBLE: - if (c4x_immed_float_p (operand)) - break; - - /* We'll come here if a CONST_DOUBLE integer has slipped - though the net... */ - fatal_insn ("Immediate CONST_DOUBLE integer too large", insn); - - case CONST: - fatal_insn ("Immediate integer not known", insn); - - /* Symbol and label immediate addresses cannot be stored - within a C[34]x instruction, so we store them in memory - and use direct addressing instead. */ - case LABEL_REF: - case SYMBOL_REF: - if (GET_CODE (operand0) != REG) - break; - - op0 = XEXP (force_const_mem (Pmode, operand), 0); - *newop = gen_rtx_MEM (GET_MODE (operand), - gen_rtx_PLUS (Pmode, - gen_rtx_PLUS (Pmode, - gen_rtx_USE (VOIDmode, operand), - gen_rtx_REG (Pmode, DP_REGNO)), - op0)); - - if (! TARGET_SMALL) - emit_insn_before (gen_set_ldp_use (gen_rtx_REG (Pmode, DP_REGNO), - *newop, operand), insn); - return 0; - - default: - break; - } - - format_ptr = GET_RTX_FORMAT (GET_CODE (operand)); - - /* Recursively hunt for required loads of DP. */ - for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++) - { - if (*format_ptr++ == 'e') /* rtx expression */ - if (c4x_scan_for_ldp (&XEXP (operand, i), insn, operand0)) - break; - } - return 0; -} - - -/* The last instruction in a repeat block cannot be a Bcond, DBcound, - CALL, CALLCond, TRAPcond, RETIcond, RETScond, IDLE, RPTB or RPTS. - - None of the last four instructions from the bottom of the block can - be a BcondD, BRD, DBcondD, RPTBD, LAJ, LAJcond, LATcond, BcondAF, - BcondAT or RETIcondD. - - This routine scans the four previous insns for a jump insn, and if - one is found, returns 1 so that we bung in a nop instruction. - This simple minded strategy will add a nop, when it may not - be required. Say when there is a JUMP_INSN near the end of the - block that doesn't get converted into a delayed branch. - - Note that we cannot have a call insn, since we don't generate - repeat loops with calls in them (although I suppose we could, but - there's no benefit.) - - !!! FIXME. The rptb_top insn may be sucked into a SEQUENCE. */ - -int -c4x_rptb_nop_p (insn) - rtx insn; -{ - rtx start_label; - int i; - - /* Extract the start label from the jump pattern (rptb_end). */ - start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0); - - /* If there is a label at the end of the loop we must insert - a NOP. */ - insn = prev_nonnote_insn (insn); - if (GET_CODE (insn) == CODE_LABEL) - return 1; - - for (i = 0; i < 4; i++) - { - /* Search back for prev non-note and non-label insn. */ - while (GET_CODE (insn) == NOTE || GET_CODE (insn) == CODE_LABEL - || GET_CODE (insn) == USE || GET_CODE (insn) == CLOBBER) - { - if (insn == start_label) - return i == 0; - - insn = PREV_INSN (insn); - }; - - /* If we have a jump instruction we should insert a NOP. If we - hit repeat block top we should only insert a NOP if the loop - is empty. */ - if (GET_CODE (insn) == JUMP_INSN) - return 1; - insn = PREV_INSN (insn); - } - return 0; -} - - -void -c4x_rptb_insert (insn) - rtx insn; -{ - rtx end_label; - rtx start_label; - rtx count_reg; - - /* If the count register has not been allocated to RC, say if - there is a movstr pattern in the loop, then do not insert a - RPTB instruction. Instead we emit a decrement and branch - at the end of the loop. */ - count_reg = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0), 0); - if (REGNO (count_reg) != RC_REGNO) - return; - - /* Extract the start label from the jump pattern (rptb_end). */ - start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0); - - /* We'll have to update the basic blocks. */ - end_label = gen_label_rtx (); - emit_label_after (end_label, insn); - - for (; insn; insn = PREV_INSN (insn)) - if (insn == start_label) - break; - if (! insn) - fatal_insn ("c4x_rptb_insert: Cannot find start label", start_label); - - /* We'll have to update the basic blocks. */ - emit_insn_before (gen_rptb_top (start_label, end_label), insn); -} - -/* This function is a C4x special. It scans through all the insn - operands looking for places where the DP register needs to be - reloaded and for large immediate operands that need to be converted - to memory references. The latter should be avoidable with proper - definition of patterns in machine description. We come here right - near the end of things, immediately before delayed branch - scheduling. */ - -void -c4x_process_after_reload (first) - rtx first; -{ - rtx insn; - int i; - - for (insn = first; insn; insn = NEXT_INSN (insn)) - { - /* Look for insn. */ - if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') - { - int insn_code_number; - - insn_code_number = recog_memoized (insn); - - if (insn_code_number < 0) - continue; - - /* Insert the RTX for RPTB at the top of the loop - and a label at the end of the loop. */ - if (insn_code_number == CODE_FOR_rptb_end) - c4x_rptb_insert(insn); - - /* We split all insns here if they have a # for the output - template if we are using the big memory model since there - is a chance that we might be accessing memory across a - page boundary. */ - - if (! TARGET_SMALL) - { - char *template; - - template = insn_template[insn_code_number]; - if (template && template[0] == '#' && template[1] == '\0') - { - rtx new = try_split (PATTERN(insn), insn, 0); - - /* If we didn't split the insn, go away. */ - if (new == insn && PATTERN (new) == PATTERN(insn)) - fatal_insn ("Couldn't split pattern", insn); - - PUT_CODE (insn, NOTE); - NOTE_SOURCE_FILE (insn) = 0; - NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - - /* Do we have to update the basic block info here? - Maybe reorg wants it sorted out... */ - - /* Continue with the first of the new insns generated - by the split. */ - insn = new; - - insn_code_number = recog_memoized (insn); - - if (insn_code_number < 0) - continue; - } - } - - /* Ignore jumps and calls. */ - if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN) - continue; - - insn_extract (insn); - for (i = 0; i < insn_n_operands[insn_code_number]; i++) - if (c4x_scan_for_ldp (recog_operand_loc[i], insn, - recog_operand[0])) - break; - } - } -} - - -static int -c4x_a_register (op) - rtx op; -{ - return REG_P (op) && IS_ADDR_OR_PSEUDO_REGNO (op); -} - - -static int -c4x_x_register (op) - rtx op; -{ - return REG_P (op) && IS_INDEX_OR_PSEUDO_REGNO (op); -} - - -static int -c4x_int_constant (op) - rtx op; -{ - if (GET_CODE (op) != CONST_INT) - return 0; - return GET_MODE (op) == VOIDmode - || GET_MODE_CLASS (op) == MODE_INT - || GET_MODE_CLASS (op) == MODE_PARTIAL_INT; -} - - -static int -c4x_float_constant (op) - rtx op; -{ - if (GET_CODE (op) != CONST_DOUBLE) - return 0; - return GET_MODE (op) == QFmode || GET_MODE (op) == HFmode; -} - - -int -c4x_H_constant (op) - rtx op; -{ - return c4x_float_constant (op) && c4x_immed_float_p (op); -} - - -int -c4x_I_constant (op) - rtx op; -{ - return c4x_int_constant (op) && IS_INT16_CONST (INTVAL (op)); -} - - -int -c4x_J_constant (op) - rtx op; -{ - if (TARGET_C3X) - return 0; - return c4x_int_constant (op) && IS_INT8_CONST (INTVAL (op)); -} - - -static int -c4x_K_constant (op) - rtx op; -{ - if (TARGET_C3X) - return 0; - return c4x_int_constant (op) && IS_INT5_CONST (INTVAL (op)); -} - - -int -c4x_L_constant (op) - rtx op; -{ - return c4x_int_constant (op) && IS_UINT16_CONST (INTVAL (op)); -} - - -static int -c4x_N_constant (op) - rtx op; -{ - return c4x_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op)); -} - - -static int -c4x_O_constant (op) - rtx op; -{ - return c4x_int_constant (op) && IS_HIGH_CONST (INTVAL (op)); -} - - -/* The constraints do not have to check the register class, - except when needed to discriminate between the constraints. - The operand has been checked by the predicates to be valid. */ - -/* ARx + 9-bit signed const or IRn - *ARx, *+ARx(n), *-ARx(n), *+ARx(IRn), *-Arx(IRn) for -256 < n < 256 - We don't include the pre/post inc/dec forms here since - they are handled by the <> constraints. */ - -int -c4x_Q_constraint (op) - rtx op; -{ - enum machine_mode mode = GET_MODE (op); - - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return 1; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (! REG_P (op0)) - return 0; - - if (REG_P (op1)) - return 1; - - if (GET_CODE (op1) != CONST_INT) - return 0; - - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_DISP8_OFF_CONST (INTVAL (op1)); - - return IS_DISP8_CONST (INTVAL (op1)); - } - break; - default: - break; - } - return 0; -} - - -/* ARx + 5-bit unsigned const - *ARx, *+ARx(n) for n < 32 */ - -int -c4x_R_constraint (op) - rtx op; -{ - enum machine_mode mode = GET_MODE (op); - - if (TARGET_C3X) - return 0; - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return 1; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (! REG_P (op0)) - return 0; - - if (GET_CODE (op1) != CONST_INT) - return 0; - - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_UINT5_CONST (INTVAL (op1) + 1); - - return IS_UINT5_CONST (INTVAL (op1)); - } - break; - default: - break; - } - return 0; -} - - -static int -c4x_R_indirect (op) - rtx op; -{ - enum machine_mode mode = GET_MODE (op); - - if (TARGET_C3X || GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return IS_ADDR_OR_PSEUDO_REGNO (op); - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_ADDR_OR_PSEUDO_REGNO (op0) - && GET_CODE (op1) == CONST_INT - && IS_UINT5_CONST (INTVAL (op1) + 1); - - return REG_P (op0) - && IS_ADDR_OR_PSEUDO_REGNO (op0) - && GET_CODE (op1) == CONST_INT - && IS_UINT5_CONST (INTVAL (op1)); - } - break; - - default: - break; - } - return 0; -} - - -/* ARx + 1-bit unsigned const or IRn - *ARx, *+ARx(1), *-ARx(1), *+ARx(IRn), *-Arx(IRn) - We don't include the pre/post inc/dec forms here since - they are handled by the <> constraints. */ - -int -c4x_S_constraint (op) - rtx op; -{ - enum machine_mode mode = GET_MODE (op); - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return 1; - - case PRE_MODIFY: - case POST_MODIFY: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS) - || (op0 != XEXP (op1, 0))) - return 0; - - op0 = XEXP (op1, 0); - op1 = XEXP (op1, 1); - return REG_P (op0) && REG_P (op1); - /* pre or post_modify with a displacement of 0 or 1 - should not be generated. */ - } - break; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (!REG_P (op0)) - return 0; - - if (REG_P (op1)) - return 1; - - if (GET_CODE (op1) != CONST_INT) - return 0; - - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_DISP1_OFF_CONST (INTVAL (op1)); - - return IS_DISP1_CONST (INTVAL (op1)); - } - break; - default: - break; - } - return 0; -} - - -static int -c4x_S_indirect (op) - rtx op; -{ - enum machine_mode mode = GET_MODE (op); - if (GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case PRE_DEC: - case POST_DEC: - if (mode != QImode && mode != QFmode) - return 0; - case PRE_INC: - case POST_INC: - op = XEXP (op, 0); - - case REG: - return IS_ADDR_OR_PSEUDO_REGNO (op); - - case PRE_MODIFY: - case POST_MODIFY: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (mode != QImode && mode != QFmode) - return 0; - - if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS) - || (op0 != XEXP (op1, 0))) - return 0; - - op0 = XEXP (op1, 0); - op1 = XEXP (op1, 1); - return REG_P (op0) && IS_ADDR_OR_PSEUDO_REGNO (op0) - && REG_P (op1) && IS_INDEX_OR_PSEUDO_REGNO (op1); - /* pre or post_modify with a displacement of 0 or 1 - should not be generated. */ - } - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (REG_P (op0)) - { - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_ADDR_OR_PSEUDO_REGNO (op0) - && GET_CODE (op1) == CONST_INT - && IS_DISP1_OFF_CONST (INTVAL (op1)); - - if (REG_P (op1)) - return (IS_INDEX_OR_PSEUDO_REGNO (op1) - && IS_ADDR_OR_PSEUDO_REGNO (op0)) - || (IS_ADDR_OR_PSEUDO_REGNO (op1) - && IS_INDEX_OR_PSEUDO_REGNO (op0)); - - return IS_ADDR_OR_PSEUDO_REGNO (op0) - && GET_CODE (op1) == CONST_INT - && IS_DISP1_CONST (INTVAL (op1)); - } - } - break; - - default: - break; - } - return 0; -} - - -/* Symbol ref. */ - -int -c4x_T_constraint (op) - rtx op; -{ - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - - if ((GET_CODE (op) == PLUS) - && (GET_CODE (XEXP (op, 0)) == REG) - && (REGNO (XEXP (op, 0)) == DP_REGNO)) - { - op = XEXP (op, 1); - } - else if ((GET_CODE (op) == PLUS) - && (GET_CODE (XEXP (op, 0)) == PLUS) - && (GET_CODE (XEXP (XEXP (op, 0), 0)) == USE)) - { - op = XEXP (op, 1); - } - else if ((GET_CODE (op) == PLUS) && (GET_CODE (XEXP (op, 0)) == USE)) - { - op = XEXP (op, 1); - } - - /* Don't allow direct addressing to an arbitrary constant. */ - if (GET_CODE (op) == CONST - && GET_CODE (XEXP (op, 0)) == PLUS - && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF - && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT) - return 1; - - return GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF; -} - - -int -c4x_autoinc_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) == MEM) - { - enum rtx_code code = GET_CODE (XEXP (op, 0)); - - if (code == PRE_INC - || code == PRE_DEC - || code == POST_INC - || code == POST_DEC - || code == PRE_MODIFY - || code == POST_MODIFY - ) - return 1; - } - return 0; -} - - -/* Match any operand. */ - -int -any_operand (op, mode) - register rtx op ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return 1; -} - - -/* Nonzero if OP is a floating point value with value 0.0. */ - -int -fp_zero_operand (op) - rtx op; -{ - REAL_VALUE_TYPE r; - - REAL_VALUE_FROM_CONST_DOUBLE (r, op); - return REAL_VALUES_EQUAL (r, dconst0); -} - - -int -const_operand (op, mode) - register rtx op; - register enum machine_mode mode; -{ - switch (mode) - { - case QFmode: - case HFmode: - if (GET_CODE (op) != CONST_DOUBLE - || GET_MODE (op) != mode - || GET_MODE_CLASS (mode) != MODE_FLOAT) - return 0; - - return c4x_immed_float_p (op); - -#if Pmode != QImode - case Pmode: -#endif - case QImode: - if (GET_CODE (op) != CONST_INT - || (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode) - || GET_MODE_CLASS (mode) != MODE_INT) - return 0; - - return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op)); - - case HImode: - return 0; - - default: - return 0; - } -} - - -int -stik_const_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return c4x_K_constant (op); -} - - -int -not_const_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return c4x_N_constant (op); -} - - -int -reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return register_operand (op, mode); -} - -int -reg_imm_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (REG_P (op) || CONSTANT_P (op)) - return 1; - return 0; -} - -int -not_modify_reg (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (REG_P (op) || CONSTANT_P (op)) - return 1; - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return 1; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (! REG_P (op0)) - return 0; - - if (REG_P (op1) || GET_CODE (op1) == CONST_INT) - return 1; - } - case CONST: - case SYMBOL_REF: - case LABEL_REF: - return 1; - default: - break; - } - return 0; -} - -int -not_rc_reg (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (REG_P (op) && REGNO (op) == RC_REGNO) - return 0; - return 1; -} - -/* Extended precision register R0-R1. */ - -int -r0r1_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (! register_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_R0R1_OR_PSEUDO_REGNO (op); -} - - -/* Extended precision register R2-R3. */ - -int -r2r3_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (! register_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_R2R3_OR_PSEUDO_REGNO (op); -} - - -/* Low extended precision register R0-R7. */ - -int -ext_low_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (! register_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REGNO (op); -} - - -/* Extended precision register. */ - -int -ext_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (! register_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (! REG_P (op)) - return 0; - return IS_EXT_OR_PSEUDO_REGNO (op); -} - - -/* Standard precision register. */ - -int -std_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (! register_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_STD_OR_PSEUDO_REGNO (op); -} - - -/* Address register. */ - -int -addr_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (! register_operand (op, mode)) - return 0; - return c4x_a_register (op); -} - - -/* Index register. */ - -int -index_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (! register_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return c4x_x_register (op); -} - - -/* DP register. */ - -int -dp_reg_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return REG_P (op) && IS_DP_OR_PSEUDO_REGNO (op); -} - - -/* SP register. */ - -int -sp_reg_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return REG_P (op) && IS_SP_OR_PSEUDO_REGNO (op); -} - - -/* ST register. */ - -int -st_reg_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return REG_P (op) && IS_ST_OR_PSEUDO_REGNO (op); -} - - -/* RC register. */ - -int -rc_reg_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return REG_P (op) && IS_RC_OR_PSEUDO_REGNO (op); -} - - -int -call_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case SYMBOL_REF: - case REG: - return 1; - default: - } - return 0; -} - - -/* Check src operand of two operand arithmetic instructions. */ - -int -src_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (REG_P (op)) - return reg_operand (op, mode); - - if (mode == VOIDmode) - mode = GET_MODE (op); - - /* We could allow certain CONST_INT values for HImode... */ - if (GET_CODE (op) == CONST_INT) - return (mode == QImode || mode == Pmode) && c4x_I_constant (op); - - /* We don't like CONST_DOUBLE integers. */ - if (GET_CODE (op) == CONST_DOUBLE) - return c4x_H_constant (op); - - return general_operand (op, mode); -} - - -int -src_hi_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (c4x_O_constant (op)) - return 1; - return src_operand (op, mode); -} - - -/* Check src operand of two operand logical instructions. */ - -int -lsrc_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode == VOIDmode) - mode = GET_MODE (op); - - if (mode != QImode && mode != Pmode) - fatal_insn ("Mode not QImode", op); - - if (REG_P (op)) - return reg_operand (op, mode); - - if (GET_CODE (op) == CONST_INT) - return c4x_L_constant (op) || c4x_J_constant (op); - - return general_operand (op, mode); -} - - -/* Check src operand of two operand tricky instructions. */ - -int -tsrc_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode == VOIDmode) - mode = GET_MODE (op); - - if (mode != QImode && mode != Pmode) - fatal_insn ("Mode not QImode", op); - - if (REG_P (op)) - return reg_operand (op, mode); - - if (GET_CODE (op) == CONST_INT) - return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op); - - return general_operand (op, mode); -} - - -int -reg_or_const_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return reg_operand (op, mode) || const_operand (op, mode); -} - - -/* Check for indirect operands allowable in parallel instruction. */ - -int -par_ind_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - - return c4x_S_indirect (op); -} - - -/* Check for operands allowable in parallel instruction. */ - -int -parallel_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode); -} - - -static void -c4x_S_address_parse (op, base, incdec, index, disp) - rtx op; - int *base; - int *incdec; - int *index; - int *disp; -{ - *base = 0; - *incdec = 0; - *index = 0; - *disp = 0; - - if (GET_CODE (op) != MEM) - fatal_insn ("Invalid indirect memory address", op); - - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case PRE_DEC: - *base = REGNO (XEXP (op, 0)); - *incdec = 1; - *disp = -1; - return; - - case POST_DEC: - *base = REGNO (XEXP (op, 0)); - *incdec = 1; - *disp = 0; - return; - - case PRE_INC: - *base = REGNO (XEXP (op, 0)); - *incdec = 1; - *disp = 1; - return; - - case POST_INC: - *base = REGNO (XEXP (op, 0)); - *incdec = 1; - *disp = 0; - return; - - case POST_MODIFY: - *base = REGNO (XEXP (op, 0)); - if (REG_P (XEXP (XEXP (op, 1), 1))) - { - *index = REGNO (XEXP (XEXP (op, 1), 1)); - *disp = 0; /* ??? */ - } - else - *disp = INTVAL (XEXP (XEXP (op, 1), 1)); - *incdec = 1; - return; - - case PRE_MODIFY: - *base = REGNO (XEXP (op, 0)); - if (REG_P (XEXP (XEXP (op, 1), 1))) - { - *index = REGNO (XEXP (XEXP (op, 1), 1)); - *disp = 1; /* ??? */ - } - else - *disp = INTVAL (XEXP (XEXP (op, 1), 1)); - *incdec = 1; - - return; - - case REG: - *base = REGNO (op); - return; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (c4x_a_register (op0)) - { - if (c4x_x_register (op1)) - { - *base = REGNO (op0); - *index = REGNO (op1); - return; - } - else if ((GET_CODE (op1) == CONST_INT - && IS_DISP1_CONST (INTVAL (op1)))) - { - *base = REGNO (op0); - *disp = INTVAL (op1); - return; - } - } - else if (c4x_x_register (op0) && c4x_a_register (op1)) - { - *base = REGNO (op1); - *index = REGNO (op0); - return; - } - } - /* Fallthrough */ - - default: - fatal_insn ("Invalid indirect (S) memory address", op); - } -} - - -int -c4x_address_conflict (op0, op1, store0, store1) - rtx op0; - rtx op1; - int store0; - int store1; -{ - int base0; - int base1; - int incdec0; - int incdec1; - int index0; - int index1; - int disp0; - int disp1; - - if (MEM_VOLATILE_P (op0) && MEM_VOLATILE_P (op1)) - return 1; - - c4x_S_address_parse (op0, &base0, &incdec0, &index0, &disp0); - c4x_S_address_parse (op1, &base1, &incdec1, &index1, &disp1); - - if (store0 && store1) - { - /* If we have two stores in parallel to the same address, then - the C4x only executes one of the stores. This is unlikely to - cause problems except when writing to a hardware device such - as a FIFO since the second write will be lost. The user - should flag the hardware location as being volatile so that - we don't do this optimisation. While it is unlikely that we - have an aliased address if both locations are not marked - volatile, it is probably safer to flag a potential conflict - if either location is volatile. */ - if (! flag_argument_noalias) - { - if (MEM_VOLATILE_P (op0) || MEM_VOLATILE_P (op1)) - return 1; - } - } - - /* If have a parallel load and a store to the same address, the load - is performed first, so there is no conflict. Similarly, there is - no conflict if have parallel loads from the same address. */ - - /* Cannot use auto increment or auto decrement twice for same - base register. */ - if (base0 == base1 && incdec0 && incdec0) - return 1; - - /* It might be too confusing for GCC if we have use a base register - with a side effect and a memory reference using the same register - in parallel. */ - if (! TARGET_DEVEL && base0 == base1 && (incdec0 || incdec1)) - return 1; - - /* We can not optimize the case where op1 and op2 refer to the same - address. */ - if (base0 == base1 && disp0 == disp1 && index0 == index1) - return 1; - - /* No conflict. */ - return 0; -} - - -/* Check for while loop inside a decrement and branch loop. */ - -int -c4x_label_conflict (insn, jump, db) - rtx insn; - rtx jump; - rtx db; -{ - while (insn) - { - if (GET_CODE (insn) == CODE_LABEL) - { - if (CODE_LABEL_NUMBER (jump) == CODE_LABEL_NUMBER (insn)) - return 1; - if (CODE_LABEL_NUMBER (db) == CODE_LABEL_NUMBER (insn)) - return 0; - } - insn = PREV_INSN (insn); - } - return 1; -} - - -/* Validate combination of operands for parallel load/store instructions. */ - -int -valid_parallel_load_store (operands, mode) - rtx *operands; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - rtx op3 = operands[3]; - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - if (GET_CODE (op3) == SUBREG) - op3 = SUBREG_REG (op3); - - /* The patterns should only allow ext_low_reg_operand() or - par_ind_operand() operands. Thus of the 4 operands, only 2 - should be REGs and the other 2 should be MEMs. */ - - /* This test prevents the multipack pass from using this pattern if - op0 is used as an index or base register in op2 or op3, since - this combination will require reloading. */ - if (GET_CODE (op0) == REG - && ((GET_CODE (op2) == MEM && reg_mentioned_p (op0, XEXP (op2, 0))) - || (GET_CODE (op3) == MEM && reg_mentioned_p (op0, XEXP (op3, 0))))) - return 0; - - /* LDI||LDI */ - if (GET_CODE (op0) == REG && GET_CODE (op2) == REG) - return (REGNO (op0) != REGNO (op2)) - && GET_CODE (op1) == MEM && GET_CODE (op3) == MEM - && ! c4x_address_conflict (op1, op3, 0, 0); - - /* STI||STI */ - if (GET_CODE (op1) == REG && GET_CODE (op3) == REG) - return GET_CODE (op0) == MEM && GET_CODE (op2) == MEM - && ! c4x_address_conflict (op0, op2, 1, 1); - - /* LDI||STI */ - if (GET_CODE (op0) == REG && GET_CODE (op3) == REG) - return GET_CODE (op1) == MEM && GET_CODE (op2) == MEM - && ! c4x_address_conflict (op1, op2, 0, 1); - - /* STI||LDI */ - if (GET_CODE (op1) == REG && GET_CODE (op2) == REG) - return GET_CODE (op0) == MEM && GET_CODE (op3) == MEM - && ! c4x_address_conflict (op0, op3, 1, 0); - - return 0; -} - - -int -valid_parallel_operands_4 (operands, mode) - rtx *operands; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx op0 = operands[0]; - rtx op2 = operands[2]; - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - - /* This test prevents the multipack pass from using this pattern if - op0 is used as an index or base register in op2, since this combination - will require reloading. */ - if (GET_CODE (op0) == REG - && GET_CODE (op2) == MEM - && reg_mentioned_p (op0, XEXP (op2, 0))) - return 0; - - return 1; -} - - -int -valid_parallel_operands_5 (operands, mode) - rtx *operands; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - int regs = 0; - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - rtx op3 = operands[3]; - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - - /* The patterns should only allow ext_low_reg_operand() or - par_ind_operand() operands. Operands 1 and 2 may be commutative - but only one of them can be a register. */ - if (GET_CODE (op1) == REG) - regs++; - if (GET_CODE (op2) == REG) - regs++; - - if (regs != 1) - return 0; - - /* This test prevents the multipack pass from using this pattern if - op0 is used as an index or base register in op3, since this combination - will require reloading. */ - if (GET_CODE (op0) == REG - && GET_CODE (op3) == MEM - && reg_mentioned_p (op0, XEXP (op3, 0))) - return 0; - - return 1; -} - - -int -valid_parallel_operands_6 (operands, mode) - rtx *operands; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - int regs = 0; - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - rtx op4 = operands[4]; - rtx op5 = operands[5]; - - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - if (GET_CODE (op4) == SUBREG) - op4 = SUBREG_REG (op4); - if (GET_CODE (op5) == SUBREG) - op5 = SUBREG_REG (op5); - - /* The patterns should only allow ext_low_reg_operand() or - par_ind_operand() operands. Thus of the 4 input operands, only 2 - should be REGs and the other 2 should be MEMs. */ - - if (GET_CODE (op1) == REG) - regs++; - if (GET_CODE (op2) == REG) - regs++; - if (GET_CODE (op4) == REG) - regs++; - if (GET_CODE (op5) == REG) - regs++; - - /* The new C30/C40 silicon dies allow 3 regs of the 4 input operands. - Perhaps we should count the MEMs as well? */ - if (regs != 2) - return 0; - - /* This test prevents the multipack pass from using this pattern if - op0 is used as an index or base register in op4 or op5, since - this combination will require reloading. */ - if (GET_CODE (op0) == REG - && ((GET_CODE (op4) == MEM && reg_mentioned_p (op0, XEXP (op4, 0))) - || (GET_CODE (op5) == MEM && reg_mentioned_p (op0, XEXP (op5, 0))))) - return 0; - - return 1; -} - - -/* Validate combination of src operands. Note that the operands have - been screened by the src_operand predicate. We just have to check - that the combination of operands is valid. If FORCE is set, ensure - that the destination regno is valid if we have a 2 operand insn. */ - -static int -c4x_valid_operands (code, operands, mode, force) - enum rtx_code code; - rtx *operands; - enum machine_mode mode; - int force; -{ - rtx op1; - rtx op2; - enum rtx_code code1; - enum rtx_code code2; - - if (code == COMPARE) - { - op1 = operands[0]; - op2 = operands[1]; - } - else - { - op1 = operands[1]; - op2 = operands[2]; - } - - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - - code1 = GET_CODE (op1); - code2 = GET_CODE (op2); - - if (code1 == REG && code2 == REG) - return 1; - - if (code1 == MEM && code2 == MEM) - { - if (c4x_S_indirect (op1, mode) && c4x_S_indirect (op2, mode)) - return 1; - return c4x_R_indirect (op1, mode) && c4x_R_indirect (op2, mode); - } - - if (code1 == code2) - return 0; - - if (code1 == REG) - { - switch (code2) - { - case CONST_INT: - if (c4x_J_constant (op2) && c4x_R_indirect (op1)) - return 1; - break; - - case CONST_DOUBLE: - if (! c4x_H_constant (op2)) - return 0; - break; - - /* Any valid memory operand screened by src_operand is OK. */ - case MEM: - - /* After CSE, any remaining (ADDRESSOF:P reg) gets converted - into a stack slot memory address comprising a PLUS and a - constant. */ - case ADDRESSOF: - break; - - default: - fatal ("c4x_valid_operands: Internal error"); - break; - } - - /* Check that we have a valid destination register for a two operand - instruction. */ - return ! force || code == COMPARE || REGNO (op1) == REGNO (operands[0]); - } - - /* We assume MINUS is commutative since the subtract patterns - also support the reverse subtract instructions. Since op1 - is not a register, and op2 is a register, op1 can only - be a restricted memory operand for a shift instruction. */ - if (code == ASHIFTRT || code == LSHIFTRT - || code == ASHIFT || code == COMPARE) - return code2 == REG - && (c4x_S_indirect (op1) || c4x_R_indirect (op1)); - - switch (code1) - { - case CONST_INT: - if (c4x_J_constant (op1) && c4x_R_indirect (op2)) - return 1; - break; - - case CONST_DOUBLE: - if (! c4x_H_constant (op1)) - return 0; - break; - - /* Any valid memory operand screened by src_operand is OK. */ - case MEM: - - /* After CSE, any remaining (ADDRESSOF:P reg) gets converted - into a stack slot memory address comprising a PLUS and a - constant. */ - case ADDRESSOF: - break; - - default: - fatal ("c4x_valid_operands: Internal error"); - break; - } - - /* Check that we have a valid destination register for a two operand - instruction. */ - return ! force || REGNO (op1) == REGNO (operands[0]); -} - - -int valid_operands (code, operands, mode) - enum rtx_code code; - rtx *operands; - enum machine_mode mode; -{ - - /* If we are not optimizing then we have to let anything go and let - reload fix things up. instantiate_decl in function.c can produce - invalid insns by changing the offset of a memory operand from a - valid one into an invalid one, when the second operand is also a - memory operand. The alternative is not to allow two memory - operands for an insn when not optimizing. The problem only rarely - occurs, for example with the C-torture program DFcmp.c */ - - return ! optimize || c4x_valid_operands (code, operands, mode, 0); -} - - -int -legitimize_operands (code, operands, mode) - enum rtx_code code; - rtx *operands; - enum machine_mode mode; -{ - /* Compare only has 2 operands. */ - if (code == COMPARE) - { - /* During RTL generation, force constants into pseudos so that - they can get hoisted out of loops. This will tie up an extra - register but can save an extra cycle. Only do this if loop - optimisation enabled. (We cannot pull this trick for add and - sub instructions since the flow pass won't find - autoincrements etc.) This allows us to generate compare - instructions like CMPI R0, *AR0++ where R0 = 42, say, instead - of LDI *AR0++, R0; CMPI 42, R0. - - Note that expand_binops will try to load an expensive constant - into a register if it is used within a loop. Unfortunately, - the cost mechanism doesn't allow us to look at the other - operand to decide whether the constant is expensive. */ - - if (! reload_in_progress - && TARGET_HOIST - && optimize > 0 - && ((GET_CODE (operands[1]) == CONST_INT - && ! c4x_J_constant (operands[1]) - && INTVAL (operands[1]) != 0) - || GET_CODE (operands[1]) == CONST_DOUBLE)) - operands[1] = force_reg (mode, operands[1]); - - if (! reload_in_progress - && ! c4x_valid_operands (code, operands, mode, 0)) - operands[0] = force_reg (mode, operands[0]); - return 1; - } - - /* We cannot do this for ADDI/SUBI insns since we will - defeat the flow pass from finding autoincrement addressing - opportunities. */ - if (! reload_in_progress - && ! ((code == PLUS || code == MINUS) && mode == Pmode) - && (TARGET_HOIST && optimize > 1 - && ((GET_CODE (operands[2]) == CONST_INT - && ! c4x_J_constant (operands[2]) - && INTVAL (operands[2]) != 0) - || GET_CODE (operands[2]) == CONST_DOUBLE))) - operands[2] = force_reg (mode, operands[2]); - - /* We can get better code on a C30 if we force constant shift counts - into a register. This way they can get hoisted out of loops, - tying up a register, but saving an instruction. The downside is - that they may get allocated to an address or index register, and - thus we will get a pipeline conflict if there is a nearby - indirect address using an address register. - - Note that expand_binops will not try to load an expensive constant - into a register if it is used within a loop for a shift insn. */ - - if (! reload_in_progress - && ! c4x_valid_operands (code, operands, mode, TARGET_FORCE)) - { - /* If the operand combination is invalid, we force operand1 into a - register, preventing reload from having doing to do this at a - later stage. */ - operands[1] = force_reg (mode, operands[1]); - if (TARGET_FORCE) - { - emit_move_insn (operands[0], operands[1]); - operands[1] = copy_rtx (operands[0]); - } - else - { - /* Just in case... */ - if (! c4x_valid_operands (code, operands, mode, 0)) - operands[2] = force_reg (mode, operands[2]); - } - } - - /* Right shifts require a negative shift count, but GCC expects - a positive count, so we emit a NEG. */ - if ((code == ASHIFTRT || code == LSHIFTRT) - && (GET_CODE (operands[2]) != CONST_INT)) - operands[2] = gen_rtx_NEG (mode, negate_rtx (mode, operands[2])); - - return 1; -} - - -/* The following predicates are used for instruction scheduling. */ - -int -group1_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_GROUP1_REG (REGNO (op)); -} - - -int -group1_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - - if (GET_CODE (op) == MEM) - { - op = XEXP (op, 0); - if (GET_CODE (op) == PLUS) - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (((GET_CODE (op0) == REG) && IS_GROUP1_REGNO (op0)) - || ((GET_CODE (op1) == REG) && IS_GROUP1_REGNO (op1))) - return 1; - } - else if ((REG_P (op)) && IS_GROUP1_REGNO (op)) - return 1; - } - - return 0; -} - - -/* Return true if any one of the address registers. */ - -int -arx_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_ADDR_REGNO (op); -} - - -static int -c4x_arn_reg_operand (op, mode, regno) - rtx op; - enum machine_mode mode; - int regno; -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && (REGNO (op) == regno); -} - - -static int -c4x_arn_mem_operand (op, mode, regno) - rtx op; - enum machine_mode mode; - int regno; -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - - if (GET_CODE (op) == MEM) - { - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case PRE_DEC: - case POST_DEC: - case PRE_INC: - case POST_INC: - op = XEXP (op, 0); - - case REG: - if (REG_P (op) && (REGNO (op) == regno)) - return 1; - break; - - case PRE_MODIFY: - case POST_MODIFY: - if (REG_P (XEXP (op, 0)) && (REGNO (XEXP (op, 0)) == regno)) - return 1; - if (REG_P (XEXP (XEXP (op, 1), 1)) - && (REGNO (XEXP (XEXP (op, 1), 1)) == regno)) - return 1; - break; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (((GET_CODE (op0) == REG) && (REGNO (op0) == regno)) - || ((GET_CODE (op1) == REG) && (REGNO (op1) == regno))) - return 1; - } - break; - default: - break; - } - } - return 0; -} - - -int -ar0_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, AR0_REGNO); -} - - -int -ar0_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, AR0_REGNO); -} - - -int -ar1_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, AR1_REGNO); -} - - -int -ar1_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, AR1_REGNO); -} - - -int -ar2_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, AR2_REGNO); -} - - -int -ar2_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, AR2_REGNO); -} - - -int -ar3_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, AR3_REGNO); -} - - -int -ar3_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, AR3_REGNO); -} - - -int -ar4_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, AR4_REGNO); -} - - -int -ar4_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, AR4_REGNO); -} - - -int -ar5_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, AR5_REGNO); -} - - -int -ar5_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, AR5_REGNO); -} - - -int -ar6_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, AR6_REGNO); -} - - -int -ar6_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, AR6_REGNO); -} - - -int -ar7_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, AR7_REGNO); -} - - -int -ar7_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, AR7_REGNO); -} - - -int -ir0_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, IR0_REGNO); -} - - -int -ir0_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, IR0_REGNO); -} - - -int -ir1_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_reg_operand (op, mode, IR1_REGNO); -} - - -int -ir1_mem_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return c4x_arn_mem_operand (op, mode, IR1_REGNO); -} - - -/* We allow autoincrement addressing. */ - -rtx -c4x_operand_subword (op, i, validate_address, mode) - rtx op; - int i; - int validate_address; - enum machine_mode mode; -{ - if (mode != HImode && mode != HFmode) - fatal_insn ("c4x_operand_subword: invalid mode", op); - - if (mode == HFmode && REG_P (op)) - fatal_insn ("c4x_operand_subword: invalid operand", op); - - if (GET_CODE (op) == MEM) - { - enum rtx_code code = GET_CODE (XEXP (op, 0)); - enum machine_mode mode = GET_MODE (XEXP (op, 0)); - - switch (code) - { - case POST_INC: - case PRE_INC: - if (mode == HImode) - mode = QImode; - else if (mode == HFmode) - mode = QFmode; - return gen_rtx_MEM (mode, XEXP (op, 0)); - - case POST_DEC: - case PRE_DEC: - case PRE_MODIFY: - case POST_MODIFY: - /* We could handle these with some difficulty. - e.g., *p-- => *(p-=2); *(p+1). */ - fatal_insn ("c4x_operand_subword: invalid autoincrement", op); - - default: - break; - } - } - - return operand_subword (op, i, validate_address, mode); -} - -/* Handle machine specific pragmas for compatibility with existing - compilers for the C3x/C4x. - - pragma attribute - ---------------------------------------------------------- - CODE_SECTION(symbol,"section") section("section") - DATA_SECTION(symbol,"section") section("section") - FUNC_CANNOT_INLINE(function) - FUNC_EXT_CALLED(function) - FUNC_IS_PURE(function) const - FUNC_IS_SYSTEM(function) - FUNC_NEVER_RETURNS(function) noreturn - FUNC_NO_GLOBAL_ASG(function) - FUNC_NO_IND_ASG(function) - INTERRUPT(function) interrupt - - */ - -int -c4x_handle_pragma (p_getc, p_ungetc, pname) - int (* p_getc) PROTO ((void)); - void (* p_ungetc) PROTO ((int)) ATTRIBUTE_UNUSED; - char *pname; -{ - int i; - int c; - int namesize; - char *name; - tree func; - tree sect = NULL_TREE; - tree new; - - c = p_getc (); - while (c == ' ' || c == '\t') c = p_getc (); - if (c != '(') - return 0; - - c = p_getc (); - while (c == ' ' || c == '\t') c = p_getc (); - if (! (isalpha(c) || c == '_' || c == '$' || c == '@')) - return 0; - - i = 0; - namesize = 16; - name = xmalloc (namesize); - while (isalnum (c) || c == '_' || c == '$' || c == '@') - { - if (i >= namesize-1) - { - namesize += 16; - name = xrealloc (name, namesize); - } - name[i++] = c; - c = p_getc (); - } - name[i] = 0; - func = get_identifier (name); - free (name); - - if (strcmp (pname, "CODE_SECTION") == 0 - || strcmp (pname, "DATA_SECTION") == 0) - { - while (c == ' ' || c == '\t') c = p_getc (); - if (c != ',') - return 0; - - c = p_getc (); - while (c == ' ' || c == '\t') c = p_getc (); - if (c != '"') - return 0; - - i = 0; - namesize = 16; - name = xmalloc (namesize); - c = p_getc (); - while (c != '"' && c != '\n' && c != '\r' && c != EOF) - { - if (i >= namesize-1) - { - namesize += 16; - name = xrealloc (name, namesize); - } - name[i++] = c; - c = p_getc (); - } - name[i] = 0; - sect = build_string (i, name); - free (name); - sect = build_tree_list (NULL_TREE, sect); - - if (c != '"') - return 0; - c = p_getc (); - } - while (c == ' ' || c == '\t') c = p_getc (); - if (c != ')') - return 0; - - new = build_tree_list (func, sect); - if (strcmp (pname, "CODE_SECTION") == 0) - code_tree = chainon (code_tree, new); - - else if (strcmp (pname, "DATA_SECTION") == 0) - data_tree = chainon (data_tree, new); - - else if (strcmp (pname, "FUNC_CANNOT_INLINE") == 0) - ; /* ignore */ - - else if (strcmp (pname, "FUNC_EXT_CALLED") == 0) - ; /* ignore */ - - else if (strcmp (pname, "FUNC_IS_PURE") == 0) - pure_tree = chainon (pure_tree, new); - - else if (strcmp (pname, "FUNC_IS_SYSTEM") == 0) - ; /* ignore */ - - else if (strcmp (pname, "FUNC_NEVER_RETURNS") == 0) - noreturn_tree = chainon (noreturn_tree, new); - - else if (strcmp (pname, "FUNC_NO_GLOBAL_ASG") == 0) - ; /* ignore */ - - else if (strcmp (pname, "FUNC_NO_IND_ASG") == 0) - ; /* ignore */ - - else if (strcmp (pname, "INTERRUPT") == 0) - interrupt_tree = chainon (interrupt_tree, new); - - else - return 0; - - return 1; -} - - -static void -c4x_check_attribute(attrib, list, decl, attributes) - char *attrib; - tree list, decl, *attributes; -{ - while (list != NULL_TREE - && IDENTIFIER_POINTER (TREE_PURPOSE (list)) - != IDENTIFIER_POINTER (DECL_NAME (decl))) - list = TREE_CHAIN(list); - if (list) - *attributes = chainon (*attributes, - build_tree_list (get_identifier (attrib), - TREE_VALUE(list))); -} - - -void -c4x_set_default_attributes(decl, attributes) - tree decl, *attributes; -{ - switch (TREE_CODE (decl)) - { - case FUNCTION_DECL: - c4x_check_attribute ("section", code_tree, decl, attributes); - c4x_check_attribute ("const", pure_tree, decl, attributes); - c4x_check_attribute ("noreturn", noreturn_tree, decl, attributes); - c4x_check_attribute ("interrupt", interrupt_tree, decl, attributes); - break; - - case VAR_DECL: - c4x_check_attribute ("section", data_tree, decl, attributes); - break; - - default: - break; - } -} - - -/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine - specific attribute for TYPE. The attributes in ATTRIBUTES have - previously been assigned to TYPE. */ - -int -c4x_valid_type_attribute_p (type, attributes, identifier, args) - tree type; - tree attributes ATTRIBUTE_UNUSED; - tree identifier; - tree args ATTRIBUTE_UNUSED; -{ - if (TREE_CODE (type) != FUNCTION_TYPE) - return 0; - - if (is_attribute_p ("interrupt", identifier)) - return 1; - - if (is_attribute_p ("assembler", identifier)) - return 1; - - if (is_attribute_p ("leaf_pretend", identifier)) - return 1; - - return 0; -} - - -/* !!! FIXME to emit RPTS correctly. */ -int -c4x_rptb_rpts_p (insn, op) - rtx insn, op; -{ - /* The next insn should be our label marking where the - repeat block starts. */ - insn = NEXT_INSN (insn); - if (GET_CODE (insn) != CODE_LABEL) - { - /* Some insns may have been shifted between the RPTB insn - and the top label... They were probably destined to - be moved out of the loop. For now, let's leave them - where they are and print a warning. We should - probably move these insns before the repeat block insn. */ - if (TARGET_DEBUG) - fatal_insn("c4x_rptb_rpts_p: Repeat block top label moved\n", - insn); - return 0; - } - - /* Skip any notes. */ - insn = next_nonnote_insn (insn); - - /* This should be our first insn in the loop. */ - if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') - return 0; - - /* Skip any notes. */ - insn = next_nonnote_insn (insn); - - if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') - return 0; - - if (recog_memoized (insn) != CODE_FOR_rptb_end) - return 0; - - if (TARGET_RPTS) - return 1; - - return (GET_CODE (op) == CONST_INT) && TARGET_RPTS_CYCLES (INTVAL (op)); -} - - -/* 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. - A set of an address register followed by a use occurs a 2 cycle - stall (reduced to a single cycle on the c40 using LDA), while - a read of an address register followed by a use occurs a single cycle. */ -#define SET_USE_COST 3 -#define SETLDA_USE_COST 2 -#define READ_USE_COST 2 - -int -c4x_adjust_cost (insn, link, dep_insn, cost) - rtx insn; - rtx link; - rtx dep_insn; - int cost; -{ - /* Don't worry about this until we know what registers have been - assigned. */ - if (! reload_completed) - return 0; - - /* How do we handle dependencies where a read followed by another - read causes a pipeline stall? For example, a read of ar0 followed - by the use of ar0 for a memory reference. It looks like we - need to extend the scheduler to handle this case. */ - - /* Reload sometimes generates a CLOBBER of a stack slot, e.g., - (clobber (mem:QI (plus:QI (reg:QI 11 ar3) (const_int 261)))), - so only deal with insns we know about. */ - if (recog_memoized (dep_insn) < 0) - return 0; - - if (REG_NOTE_KIND (link) == 0) - { - int max = 0; - - /* Data dependency; DEP_INSN writes a register that INSN reads some - cycles later. */ - - if (TARGET_C3X) - { - if (get_attr_setgroup1 (dep_insn) && get_attr_usegroup1 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_readarx (dep_insn) && get_attr_usegroup1 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - } - else - { - /* This could be significantly optimized. We should look - to see if dep_insn sets ar0-ar7 or ir0-ir1 and if - insn uses ar0-ar7. We then test if the same register - is used. The tricky bit is that some operands will - use several registers... */ - - if (get_attr_setar0 (dep_insn) && get_attr_usear0 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar0 (dep_insn) && get_attr_usear0 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar0 (dep_insn) && get_attr_usear0 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar1 (dep_insn) && get_attr_usear1 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar1 (dep_insn) && get_attr_usear1 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar1 (dep_insn) && get_attr_usear1 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar2 (dep_insn) && get_attr_usear2 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar2 (dep_insn) && get_attr_usear2 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar2 (dep_insn) && get_attr_usear2 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar3 (dep_insn) && get_attr_usear3 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar3 (dep_insn) && get_attr_usear3 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar3 (dep_insn) && get_attr_usear3 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar4 (dep_insn) && get_attr_usear4 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar4 (dep_insn) && get_attr_usear4 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar4 (dep_insn) && get_attr_usear4 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar5 (dep_insn) && get_attr_usear5 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar5 (dep_insn) && get_attr_usear5 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar5 (dep_insn) && get_attr_usear5 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar6 (dep_insn) && get_attr_usear6 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar6 (dep_insn) && get_attr_usear6 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar6 (dep_insn) && get_attr_usear6 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar7 (dep_insn) && get_attr_usear7 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar7 (dep_insn) && get_attr_usear7 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar7 (dep_insn) && get_attr_usear7 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setir0 (dep_insn) && get_attr_useir0 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ir0 (dep_insn) && get_attr_useir0 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - - if (get_attr_setir1 (dep_insn) && get_attr_useir1 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ir1 (dep_insn) && get_attr_useir1 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - } - - if (max) - cost = max; - - /* For other data dependencies, the default cost specified in the - md is correct. */ - return cost; - } - else if (REG_NOTE_KIND (link) == REG_DEP_ANTI) - { - /* Anti dependency; DEP_INSN reads a register that INSN writes some - cycles later. */ - - /* For c4x anti dependencies, the cost is 0. */ - return 0; - } - else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT) - { - /* Output dependency; DEP_INSN writes a register that INSN writes some - cycles later. */ - - /* For c4x output dependencies, the cost is 0. */ - return 0; - } - else - abort (); -} diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h deleted file mode 100755 index 2a0a7c0..0000000 --- a/gcc/config/c4x/c4x.h +++ /dev/null @@ -1,2671 +0,0 @@ -/* Definitions of target machine for GNU compiler. TMS320C[34]x - Copyright (C) 1994-98, 1999 Free Software Foundation, Inc. - - Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) - and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl). - - This file is part of GNU CC. - - GNU CC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) - any later version. - - GNU CC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNU CC; see the file COPYING. If not, write to - the Free Software Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* Set the following so that some of the macros expand to function - calls to simplify debugging. */ -#define C4X_DEBUG 1 - -/* RUN-TIME TARGET SPECIFICATION */ - -#define C4x 1 - -/* Name of the c4x assembler */ - -#define ASM_PROG "c4x-as" - -/* Name of the c4x linker */ - -#define LD_PROG "c4x-ld" - -/* Define assembler options */ - -#define ASM_SPEC "\ -%{!mcpu=30:%{!mcpu=31:%{!mcpu=32:%{!mcpu=40:%{!mcpu=44:\ -%{!m30:%{!m40:-m40}}}}}}} \ -%{mcpu=30:-m30} \ -%{mcpu=31:-m31} \ -%{mcpu=32:-m32} \ -%{mcpu=40:-m40} \ -%{mcpu=44:-m44} \ -%{m30:-m30} \ -%{m31:-m31} \ -%{m32:-m32} \ -%{m40:-m40} \ -%{m44:-m44} \ -%{mmemparm:-p} %{mregparm:-r} \ -%{!mmemparm:%{!mregparm:-r}} \ -%{mbig:-b} %{msmall:-s} \ -%{!msmall:%{!mbig:-b}}" - -/* Define linker options */ - -#define LINK_SPEC "\ -%{m30:--architecture c3x} \ -%{m31:--architecture c3x} \ -%{m32:--architecture c3x} \ -%{mcpu=30:--architecture c3x} \ -%{mcpu=31:--architecture c3x} \ -%{mcpu=32:--architecture c3x}" - -/* Define C preprocessor options. */ - -#define CPP_SPEC "\ -%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32:%{!mcpu=40:%{!mcpu=44:\ - %{!m40:%{!m44:-D_TMS320C4x -D_C4x -D_TMS320C40 -D_C40 }}}}}}}}}} \ -%{mcpu=30:-D_TMS320C3x -D_C3x -D_TMS320C30 -D_C30 } \ -%{m30:-D_TMS320C3x -D_C3x -D_TMS320C30 -D_C30 } \ -%{mcpu=31:-D_TMS320C3x -D_C3x -D_TMS320C31 -D_C31 } \ -%{m31:-D_TMS320C3x -D_C3x -D_TMS320C31 -D_C31 } \ -%{mcpu=32:-D_TMS320C3x -D_C3x -D_TMS320C32 -D_C32 } \ -%{m32:-D_TMS320C3x -D_C3x -D_TMS320C32 -D_C32 } \ -%{mcpu=40:-D_TMS320C4x -D_C4x -D_TMS320C40 -D_C40 } \ -%{m40:-D_TMS320C4x -D_C4x -D_TMS320C40 -D_C40 } \ -%{mcpu=44:-D_TMS320C4x -D_C4x -D_TMS320C44 -D_C44 } \ -%{m44:-D_TMS320C4x -D_C4x -D_TMS320C44 -D_C44 } \ -%{mmemparm:-U_REGPARM }%{mregparm:-D_REGPARM } \ -%{!mmemparm:%{!mregparm:-D_REGPARM }} \ -%{msmall:-U_BIGMODEL } %{mbig:-D_BIGMODEL } \ -%{!msmall:%{!mbig:-D_BIGMODEL }} \ -%{finline-functions:-D_INLINE }" - -/* Specify the startup file to link with. */ - -#define STARTFILE_SPEC "\ -%{!mmemparm:%{m30:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \ -%{mmemparm:%{m30:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \ -%{!mmemparm:%{m31:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \ -%{mmemparm:%{m31:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \ -%{!mmemparm:%{m32:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \ -%{mmemparm:%{m32:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \ -%{!mmemparm:%{mcpu=30:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \ -%{mmemparm:%{mcpu=30:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \ -%{!mmemparm:%{mcpu=31:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \ -%{mmemparm:%{mcpu=31:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \ -%{!mmemparm:%{mcpu=32:%{msmall:crt0_3sr%O%s} %{!msmall:crt0_3br%O%s}}} \ -%{mmemparm:%{mcpu=32:%{msmall:crt0_3sm%O%s} %{!msmall:crt0_3bm%O%s}}} \ -%{!mmemparm:%{m40:%{msmall:crt0_4sr%O%s} %{!msmall:crt0_4br%O%s}}} \ -%{mmemparm:%{m40:%{msmall:crt0_4sm%O%s} %{!msmall:crt0_4bm%O%s}}} \ -%{!mmemparm:%{m44:%{msmall:crt0_4sr%O%s} %{!msmall:crt0_4br%O%s}}} \ -%{mmemparm:%{m44:%{msmall:crt0_4sm%O%s} %{!msmall:crt0_4bm%O%s}}} \ -%{!mmemparm:%{mcpu=40:%{msmall:crt0_4sr%O%s} %{!msmall:crt0_4br%O%s}}} \ -%{mmemparm:%{mcpu=40:%{msmall:crt0_4sm%O%s} %{!msmall:crt0_4bm%O%s}}} \ -%{!mmemparm:%{mcpu=44:%{msmall:crt0_4sr%O%s} %{!msmall:crt0_4br%O%s}}} \ -%{mmemparm:%{mcpu=44:%{msmall:crt0_4sm%O%s} %{!msmall:crt0_4bm%O%s}}} \ -%{!mmemparm:%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32: \ - %{!mcpu=40:%{!mcpu=44:%{!m40:%{!m44:%{msmall:crt0_4sr%O%s}}}}}}}}}}}} \ -%{mmemparm:%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32: \ - %{!mcpu=40:%{!mcpu=44:%{!m40:%{!m44:%{msmall:crt0_4sm%O%s}}}}}}}}}}}} \ -%{!mmemparm:%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32: \ - %{!mcpu=40:%{!mcpu=44:%{!m40:%{!m44:%{!msmall:crt0_4br%O%s}}}}}}}}}}}} \ -%{mmemparm:%{!m30:%{!m31:%{!m32:%{!mcpu=30:%{!mcpu=31:%{!mcpu=32: \ - %{!mcpu=40:%{!mcpu=44:%{!m40:%{!m44:%{!msmall:crt0_4bm%O%s}}}}}}}}}}}}" - -/* Specify the end file to link with */ - -#define ENDFILE_SPEC "" - -/* Target compilation option flags */ - -#define SMALL_MEMORY_FLAG 0x0000001 /* small memory model */ -#define MPYI_FLAG 0x0000002 /* use 24-bit MPYI for C3x */ -#define FAST_FIX_FLAG 0x0000004 /* fast fixing of floats */ -#define RPTS_FLAG 0x0000008 /* allow use of RPTS */ -#define C3X_FLAG 0x0000010 /* emit C3x code */ -#define TI_FLAG 0x0000020 /* be compatible with TI assembler */ -#define PARANOID_FLAG 0x0000040 /* be paranoid about DP reg. in ISRs */ -#define MEMPARM_FLAG 0x0000080 /* pass arguments on stack */ -#define DEVEL_FLAG 0x0000100 /* enable features under development */ -#define RPTB_FLAG 0x0000200 /* enable repeat block */ -#define BK_FLAG 0x0000400 /* use BK as general register */ -#define DB_FLAG 0x0000800 /* use decrement and branch for C3x */ -#define DEBUG_FLAG 0x0001000 /* enable debugging of GCC */ -#define HOIST_FLAG 0x0002000 /* force constants into registers */ -#define LOOP_UNSIGNED_FLAG 0x0004000 /* allow unsigned loop counters */ -#define FORCE_FLAG 0x0008000 /* force op0 and op1 to be same */ -#define PRESERVE_FLOAT_FLAG 0x0010000 /* save all 40 bits for floats */ -#define PARALLEL_PACK_FLAG 0x0020000 /* allow parallel insn packing */ -#define PARALLEL_MPY_FLAG 0x0040000 /* allow MPY||ADD, MPY||SUB insns */ -#define ALIASES_FLAG 0x0080000 /* assume mem refs possibly aliased */ - -#define C30_FLAG 0x0100000 /* emit C30 code */ -#define C31_FLAG 0x0200000 /* emit C31 code */ -#define C32_FLAG 0x0400000 /* emit C32 code */ -#define C40_FLAG 0x1000000 /* emit C40 code */ -#define C44_FLAG 0x2000000 /* emit C44 code */ - -/* 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 \ -{ { "small", SMALL_MEMORY_FLAG }, \ - { "big", -SMALL_MEMORY_FLAG }, \ - { "mpyi", MPYI_FLAG}, \ - { "no-mpyi", -MPYI_FLAG}, \ - { "fast-fix", FAST_FIX_FLAG}, \ - { "no-fast-fix", -FAST_FIX_FLAG}, \ - { "rpts", RPTS_FLAG}, \ - { "no-rpts", -RPTS_FLAG}, \ - { "rptb", RPTB_FLAG}, \ - { "no-rptb", -RPTB_FLAG}, \ - { "30", C30_FLAG}, \ - { "31", C31_FLAG}, \ - { "32", C32_FLAG}, \ - { "40", C40_FLAG}, \ - { "44", C44_FLAG}, \ - { "ti", TI_FLAG}, \ - { "no-ti", -TI_FLAG}, \ - { "paranoid", PARANOID_FLAG}, \ - { "no-paranoid", -PARANOID_FLAG}, \ - { "isr-dp-reload", PARANOID_FLAG}, \ - { "no-isr-dp-reload", -PARANOID_FLAG}, \ - { "memparm", MEMPARM_FLAG}, \ - { "regparm", -MEMPARM_FLAG}, \ - { "devel", DEVEL_FLAG}, \ - { "no-devel", -DEVEL_FLAG}, \ - { "bk", BK_FLAG}, \ - { "no-bk", -BK_FLAG}, \ - { "db", DB_FLAG}, \ - { "no-db", -DB_FLAG}, \ - { "debug", DEBUG_FLAG}, \ - { "no-debug", -DEBUG_FLAG}, \ - { "hoist", HOIST_FLAG}, \ - { "no-hoist", -HOIST_FLAG}, \ - { "no-force", -FORCE_FLAG}, \ - { "force", FORCE_FLAG}, \ - { "loop-unsigned", LOOP_UNSIGNED_FLAG}, \ - { "no-loop-unsigned", -LOOP_UNSIGNED_FLAG}, \ - { "preserve-float", PRESERVE_FLOAT_FLAG}, \ - { "no-preserve-float", -PRESERVE_FLOAT_FLAG}, \ - { "parallel-insns", PARALLEL_PACK_FLAG}, \ - { "no-parallel-mpy", -PARALLEL_MPY_FLAG}, \ - { "parallel-mpy", PARALLEL_MPY_FLAG}, \ - { "no-parallel-insns", -PARALLEL_PACK_FLAG}, \ - { "aliases", ALIASES_FLAG}, \ - { "no-aliases", -ALIASES_FLAG}, \ - { "", TARGET_DEFAULT} } - -/* Default target switches */ - -/* Play safe, not the fastest code. */ -#define TARGET_DEFAULT ALIASES_FLAG | PARALLEL_PACK_FLAG \ - | PARALLEL_MPY_FLAG | RPTB_FLAG - -/* Caveats: - Max iteration count for RPTB/RPTS is 2^31 + 1. - Max iteration count for DB is 2^31 + 1 for C40, but 2^23 + 1 for C30. - RPTS blocks interrupts. */ - - -extern int target_flags; - -#define TARGET_INLINE 1 /* Inline MPYI */ -#define TARGET_PARALLEL 1 /* Enable parallel insns in MD */ -#define TARGET_SMALL_REG_CLASS 0 - -#define TARGET_SMALL (target_flags & SMALL_MEMORY_FLAG) -#define TARGET_MPYI (!TARGET_C3X || (target_flags & MPYI_FLAG)) -#define TARGET_FAST_FIX (target_flags & FAST_FIX_FLAG) -#define TARGET_RPTS (target_flags & RPTS_FLAG) -#define TARGET_TI (target_flags & TI_FLAG) -#define TARGET_PARANOID (target_flags & PARANOID_FLAG) -#define TARGET_MEMPARM (target_flags & MEMPARM_FLAG) -#define TARGET_DEVEL (target_flags & DEVEL_FLAG) -#define TARGET_RPTB (target_flags & RPTB_FLAG \ - && optimize >= 2) -#define TARGET_BK (target_flags & BK_FLAG) -#define TARGET_DB (! TARGET_C3X || (target_flags & DB_FLAG)) -#define TARGET_DEBUG (target_flags & DEBUG_FLAG) -#define TARGET_HOIST (target_flags & HOIST_FLAG) -#define TARGET_LOOP_UNSIGNED (target_flags & LOOP_UNSIGNED_FLAG) -#define TARGET_FORCE (target_flags & FORCE_FLAG) -#define TARGET_PRESERVE_FLOAT (target_flags & PRESERVE_FLOAT_FLAG) -#define TARGET_PARALLEL_PACK (TARGET_RPTB \ - && (target_flags & PARALLEL_PACK_FLAG) \ - && optimize >= 2) -#define TARGET_PARALLEL_MPY (TARGET_PARALLEL_PACK \ - && (target_flags & PARALLEL_MPY_FLAG)) -#define TARGET_ALIASES (target_flags & ALIASES_FLAG) - -#define TARGET_C3X (target_flags & C3X_FLAG) -#define TARGET_C30 (target_flags & C30_FLAG) -#define TARGET_C31 (target_flags & C31_FLAG) -#define TARGET_C32 (target_flags & C32_FLAG) -#define TARGET_C40 (target_flags & C40_FLAG) -#define TARGET_C44 (target_flags & C44_FLAG) - -/* -mrpts allows the use of the RPTS instruction irregardless. - -mrpts=max-cycles will use RPTS if the number of cycles is constant - and less than max-cycles. */ - -#define TARGET_RPTS_CYCLES(CYCLES) (TARGET_RPTS || (CYCLES) < c4x_rpts_cycles) - -/* -mcpu=XX with XX = target DSP version number */ - -/* 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. - - Each subgrouping contains a string constant, that defines the - fixed part of the option name, and the address of a variable. - The variable, type `char *', is set to the variable part of the - given option if the fixed part matches. The actual option name - is made by appending `-m' to the specified name. - - Here is an example which defines `-mshort-data-NUMBER'. If the - given option is `-mshort-data-512', the variable `m88k_short_data' - will be set to the string `"512"'. - - extern char *m88k_short_data; - #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ - -extern char *c4x_rpts_cycles_string, *c4x_cpu_version_string; - -#define TARGET_OPTIONS \ -{ {"rpts=", &c4x_rpts_cycles_string},\ - {"cpu=", &c4x_cpu_version_string} } - -/* Sometimes certain combinations of command options do not make sense - on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. */ - -extern void c4x_override_options (); -#define OVERRIDE_OPTIONS c4x_override_options () - -/* Define this to change the optimizations performed by default. */ -extern void c4x_optimization_options (); -#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) c4x_optimization_options(LEVEL,SIZE) - -/* Run Time Target Specification */ - -#define TARGET_VERSION fprintf (stderr, " (TMS320C[34]x, TI syntax)" ); - -/* Storage Layout */ - -#define BITS_BIG_ENDIAN 0 -#define BYTES_BIG_ENDIAN 0 -#define WORDS_BIG_ENDIAN 0 - -/* Technically, we are little endian, but we put the floats out as - whole longs and this makes GCC put them out in the right order. */ - -#define FLOAT_WORDS_BIG_ENDIAN 1 - -/* Note the ANSI C standard requires sizeof(char) = 1. On the C[34]x - all integral and floating point data types are stored in memory as - 32-bits (floating point types can be stored as 40-bits in the - extended precision registers), so sizeof(char) = sizeof(short) = - sizeof(int) = sizeof(long) = sizeof(float) = sizeof(double) = 1. */ - -#define BITS_PER_UNIT 32 -#define BITS_PER_WORD 32 -#define UNITS_PER_WORD 1 -#define POINTER_SIZE 32 -#define PARM_BOUNDARY 32 -#define STACK_BOUNDARY 32 -#define FUNCTION_BOUNDARY 32 -#define BIGGEST_ALIGNMENT 32 -#define EMPTY_FIELD_BOUNDARY 32 -#define STRICT_ALIGNMENT 0 -#define TARGET_FLOAT_FORMAT C4X_FLOAT_FORMAT -#define MAX_FIXED_MODE_SIZE 64 /* HImode */ - -/* Use the internal floating point stuff in the compiler and not the - host floating point stuff. */ - -#define REAL_ARITHMETIC - -/* Define register numbers */ - -/* Extended-precision registers */ - -#define R0_REGNO 0 -#define R1_REGNO 1 -#define R2_REGNO 2 -#define R3_REGNO 3 -#define R4_REGNO 4 -#define R5_REGNO 5 -#define R6_REGNO 6 -#define R7_REGNO 7 - -/* Auxiliary (address) registers */ - -#define AR0_REGNO 8 -#define AR1_REGNO 9 -#define AR2_REGNO 10 -#define AR3_REGNO 11 -#define AR4_REGNO 12 -#define AR5_REGNO 13 -#define AR6_REGNO 14 -#define AR7_REGNO 15 - -/* Data page register */ - -#define DP_REGNO 16 - -/* Index registers */ - -#define IR0_REGNO 17 -#define IR1_REGNO 18 - -/* Block size register */ - -#define BK_REGNO 19 - -/* Stack pointer */ - -#define SP_REGNO 20 - -/* Status register */ - -#define ST_REGNO 21 - -/* Misc. interrupt registers */ - -#define DIE_REGNO 22 /* C4x only */ -#define IE_REGNO 22 /* C3x only */ -#define IIE_REGNO 23 /* C4x only */ -#define IF_REGNO 23 /* C3x only */ -#define IIF_REGNO 24 /* C4x only */ -#define IOF_REGNO 24 /* C3x only */ - -/* Repeat block registers */ - -#define RS_REGNO 25 -#define RE_REGNO 26 -#define RC_REGNO 27 - -/* Additional extended-precision registers */ - -#define R8_REGNO 28 /* C4x only */ -#define R9_REGNO 29 /* C4x only */ -#define R10_REGNO 30 /* C4x only */ -#define R11_REGNO 31 /* C4x only */ - -#define FIRST_PSEUDO_REGISTER 32 - -/* Extended precision registers (low set) */ - -#define IS_R0R1_REG(r) ((((r) >= R0_REGNO) && ((r) <= R1_REGNO))) -#define IS_R2R3_REG(r) ((((r) >= R2_REGNO) && ((r) <= R3_REGNO))) -#define IS_EXT_LOW_REG(r) ((((r) >= R0_REGNO) && ((r) <= R7_REGNO))) - -/* Extended precision registers (high set) */ - -#define IS_EXT_HIGH_REG(r) (! TARGET_C3X \ - && ((r) >= R8_REGNO) && ((r) <= R11_REGNO)) -/* Address registers */ - -#define IS_AUX_REG(r) (((r) >= AR0_REGNO) && ((r) <= AR7_REGNO)) -#define IS_ADDR_REG(r) IS_AUX_REG(r) -#define IS_DP_REG(r) ((r) == DP_REGNO) -#define IS_INDEX_REG(r) (((r) == IR0_REGNO) || ((r) == IR1_REGNO)) -#define IS_SP_REG(r) ((r) == SP_REGNO) -#define IS_BK_REG(r) (TARGET_BK && (r) == BK_REGNO) - -/* Misc registers */ - -#define IS_ST_REG(r) ((r) == ST_REGNO) -#define IS_RC_REG(r) ((r) == RC_REGNO) -#define IS_REPEAT_REG(r) (((r) >= RS_REGNO) && ((r) <= RC_REGNO)) - -/* Composite register sets */ - -#define IS_ADDR_OR_INDEX_REG(r) (IS_ADDR_REG(r) || IS_INDEX_REG(r)) -#define IS_EXT_REG(r) (IS_EXT_LOW_REG(r) || IS_EXT_HIGH_REG(r)) -#define IS_STD_REG(r) (IS_ADDR_OR_INDEX_REG(r) || IS_REPEAT_REG(r) \ - || IS_SP_REG(r) || IS_BK_REG(r)) -#define IS_INT_REG(r) (IS_EXT_REG(r) || IS_STD_REG(r)) -#define IS_GROUP1_REG(r) (IS_ADDR_OR_INDEX_REG(r) || IS_BK_REG(r)) - - -#define IS_PSEUDO_REG(r) ((r) >= FIRST_PSEUDO_REGISTER) -#define IS_R0R1_OR_PSEUDO_REG(r) (IS_R0R1_REG(r) || IS_PSEUDO_REG(r)) -#define IS_R2R3_OR_PSEUDO_REG(r) (IS_R2R3_REG(r) || IS_PSEUDO_REG(r)) -#define IS_EXT_OR_PSEUDO_REG(r) (IS_EXT_REG(r) || IS_PSEUDO_REG(r)) -#define IS_STD_OR_PSEUDO_REG(r) (IS_STD_REG(r) || IS_PSEUDO_REG(r)) -#define IS_INT_OR_PSEUDO_REG(r) (IS_INT_REG(r) || IS_PSEUDO_REG(r)) -#define IS_ADDR_OR_PSEUDO_REG(r) (IS_ADDR_REG(r) || IS_PSEUDO_REG(r)) -#define IS_INDEX_OR_PSEUDO_REG(r) (IS_INDEX_REG(r) || IS_PSEUDO_REG(r)) -#define IS_EXT_LOW_OR_PSEUDO_REG(r) (IS_EXT_LOW_REG(r) || IS_PSEUDO_REG(r)) -#define IS_DP_OR_PSEUDO_REG(r) (IS_DP_REG(r) || IS_PSEUDO_REG(r)) -#define IS_SP_OR_PSEUDO_REG(r) (IS_SP_REG(r) || IS_PSEUDO_REG(r)) -#define IS_ST_OR_PSEUDO_REG(r) (IS_ST_REG(r) || IS_PSEUDO_REG(r)) -#define IS_RC_OR_PSEUDO_REG(r) (IS_RC_REG(r) || IS_PSEUDO_REG(r)) - -#define IS_PSEUDO_REGNO(op) (IS_PSEUDO_REG(REGNO(op))) -#define IS_ADDR_REGNO(op) (IS_ADDR_REG(REGNO(op))) -#define IS_INDEX_REGNO(op) (IS_INDEX_REG(REGNO(op))) -#define IS_GROUP1_REGNO(r) (IS_GROUP1_REG(REGNO(op))) - -#define IS_R0R1_OR_PSEUDO_REGNO(op) (IS_R0R1_OR_PSEUDO_REG(REGNO(op))) -#define IS_R2R3_OR_PSEUDO_REGNO(op) (IS_R2R3_OR_PSEUDO_REG(REGNO(op))) -#define IS_EXT_OR_PSEUDO_REGNO(op) (IS_EXT_OR_PSEUDO_REG(REGNO(op))) -#define IS_STD_OR_PSEUDO_REGNO(op) (IS_STD_OR_PSEUDO_REG(REGNO(op))) -#define IS_EXT_LOW_OR_PSEUDO_REGNO(op) (IS_EXT_LOW_OR_PSEUDO_REG(REGNO(op))) -#define IS_INT_OR_PSEUDO_REGNO(op) (IS_INT_OR_PSEUDO_REG(REGNO(op))) - -#define IS_ADDR_OR_PSEUDO_REGNO(op) (IS_ADDR_OR_PSEUDO_REG(REGNO(op))) -#define IS_INDEX_OR_PSEUDO_REGNO(op) (IS_INDEX_OR_PSEUDO_REG(REGNO(op))) -#define IS_DP_OR_PSEUDO_REGNO(op) (IS_DP_OR_PSEUDO_REG(REGNO(op))) -#define IS_SP_OR_PSEUDO_REGNO(op) (IS_SP_OR_PSEUDO_REG(REGNO(op))) -#define IS_ST_OR_PSEUDO_REGNO(op) (IS_ST_OR_PSEUDO_REG(REGNO(op))) -#define IS_RC_OR_PSEUDO_REGNO(op) (IS_RC_OR_PSEUDO_REG(REGNO(op))) - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. */ - -#define FIXED_REGISTERS \ -{ \ -/* R0 R1 R2 R3 R4 R5 R6 R7 AR0 AR1 AR2 AR3 AR4 AR5 AR6 AR7 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -/* DP IR0 IR1 BK SP ST DIE IIE IIF RS RE RC R8 R9 R10 R11 */ \ - 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 \ -} - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. - - Note that the extended precision registers are only saved in some - modes. The macro HARD_REGNO_CALL_CLOBBERED specifies which modes - get clobbered for a given regno. */ - -#define CALL_USED_REGISTERS \ -{ \ -/* R0 R1 R2 R3 R4 R5 R6 R7 AR0 AR1 AR2 AR3 AR4 AR5 AR6 AR7 */ \ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, \ -/* DP IR0 IR1 BK SP ST DIE IIE IIF RS RE RC R8 R9 R10 R11 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1 \ -} - -/* Macro to conditionally modify fixed_regs/call_used_regs. */ - -#define CONDITIONAL_REGISTER_USAGE \ - { \ - if (! TARGET_BK) \ - { \ - fixed_regs[BK_REGNO] = 1; \ - call_used_regs[BK_REGNO] = 1; \ - c4x_regclass_map[BK_REGNO] = NO_REGS; \ - } \ - if (TARGET_C3X) \ - { \ - int i; \ - \ - reg_names[DIE_REGNO] = "ie"; /* clobber die */ \ - reg_names[IF_REGNO] = "if"; /* clobber iie */ \ - reg_names[IOF_REGNO] = "iof"; /* clobber iif */ \ - \ - for (i = R8_REGNO; i <= R11_REGNO; i++) \ - { \ - fixed_regs[i] = call_used_regs[i] = 1; \ - c4x_regclass_map[i] = NO_REGS; \ - } \ - } \ - if (TARGET_PRESERVE_FLOAT) \ - { \ - c4x_caller_save_map[R6_REGNO] = HFmode; \ - c4x_caller_save_map[R7_REGNO] = HFmode; \ - } \ - } - -/* Order of Allocation of Registers */ - -/* List the order in which to allocate registers. Each register must be - listed once, even those in FIXED_REGISTERS. - - First allocate registers that don't need preservation across calls, - except index and address registers. Then allocate data registers - that require preservation across calls (even though this invokes an - extra overhead of having to save/restore these registers). Next - allocate the address and index registers, since using these - registers for arithmetic can cause pipeline stalls. Finally - allocated the fixed registers which won't be allocated anyhow. */ - -#define REG_ALLOC_ORDER \ -{R0_REGNO, R1_REGNO, R2_REGNO, R3_REGNO, \ - R9_REGNO, R10_REGNO, R11_REGNO, \ - RS_REGNO, RE_REGNO, RC_REGNO, BK_REGNO, \ - R4_REGNO, R5_REGNO, R6_REGNO, R7_REGNO, R8_REGNO, \ - AR0_REGNO, AR1_REGNO, AR2_REGNO, AR3_REGNO, \ - AR4_REGNO, AR5_REGNO, AR6_REGNO, AR7_REGNO, \ - IR0_REGNO, IR1_REGNO, \ - SP_REGNO, DP_REGNO, ST_REGNO, IE_REGNO, IF_REGNO, IOF_REGNO} - - -/* Determine which register classes are very likely used by spill registers. - local-alloc.c won't allocate pseudos that have these classes as their - preferred class unless they are "preferred or nothing". */ - -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - ((CLASS) == INDEX_REGS) - -/* CCmode is wrongly defined in machmode.def It should have a size - of UNITS_PER_WORD. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ -(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : ((MODE) == HFmode) ? 1 : \ -((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) - - -/* A C expression that is nonzero if the hard register REGNO is preserved - across a call in mode MODE. This does not have to include the call used - registers. */ - -#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \ - ((((REGNO) == R6_REGNO || (REGNO) == R7_REGNO) && ! ((MODE) == QFmode)) \ - || (((REGNO) == R4_REGNO || (REGNO) == R5_REGNO || (REGNO == R8_REGNO)) \ - && ! ((MODE) == QImode || (MODE) == HImode || (MODE) == Pmode))) - -/* Specify the modes required to caller save a given hard regno. */ - -#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS) (c4x_caller_save_map[REGNO]) - -int c4x_hard_regno_mode_ok (); -#define HARD_REGNO_MODE_OK(REGNO, MODE) c4x_hard_regno_mode_ok(REGNO, MODE) - - -/* A C expression that is nonzero if it is desirable to choose - register allocation so as to avoid move instructions between a - value of mode MODE1 and a value of mode MODE2. - - 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) 0 - - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -enum reg_class - { - NO_REGS, - R0R1_REGS, /* 't' */ - R2R3_REGS, /* 'u' */ - EXT_LOW_REGS, /* 'q' */ - EXT_REGS, /* 'f' */ - ADDR_REGS, /* 'a' */ - INDEX_REGS, /* 'x' */ - BK_REG, /* 'k' */ - SP_REG, /* 'b' */ - RC_REG, /* 'v' */ - INT_REGS, /* 'c' */ - GENERAL_REGS, /* 'r' */ - DP_REG, /* 'z' */ - ST_REG, /* 'y' */ - ALL_REGS, - LIM_REG_CLASSES - }; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -#define REG_CLASS_NAMES \ -{ \ - "NO_REGS", \ - "R0R1_REGS", \ - "R2R3_REGS", \ - "EXT_LOW_REGS", \ - "EXT_REGS", \ - "ADDR_REGS", \ - "INDEX_REGS", \ - "BK_REG", \ - "SP_REG", \ - "RC_REG", \ - "INT_REGS", \ - "GENERAL_REGS", \ - "DP_REG", \ - "ST_REG", \ - "ALL_REGS" \ -} - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. RC is not included in GENERAL_REGS - since the register allocator will often choose a general register - in preference to RC for the decrement_and_branch_on_count pattern. */ - -#define REG_CLASS_CONTENTS \ -{ \ - {0x00000000}, /* No registers */ \ - {0x00000003}, /* 't' R0-R1 */ \ - {0x0000000c}, /* 'u' R2-R3 */ \ - {0x000000ff}, /* 'q' R0-R7 */ \ - {0xf00000ff}, /* 'f' R0-R11 */ \ - {0x0000ff00}, /* 'a' AR0-AR7 */ \ - {0x00060000}, /* 'x' IR0-IR1 */ \ - {0x00080000}, /* 'k' BK */ \ - {0x00100000}, /* 'b' SP */ \ - {0x08000000}, /* 'v' RC */ \ - {0x0e1eff00}, /* 'c' AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC */ \ - {0xfe1effff}, /* 'r' R0-R11, AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC */\ - {0x00010000}, /* 'z' DP */ \ - {0x00200000}, /* 'y' ST */ \ - {0xffffffff}, /* All registers */ \ -} - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) (c4x_regclass_map[REGNO]) - -/* When SMALL_REGISTER_CLASSES is defined, the lifetime of registers - explicitly used in the rtl is kept as short as possible. - - We only need to define SMALL_REGISTER_CLASSES if TARGET_PARALLEL_MPY - is defined since the MPY|ADD insns require the classes R0R1_REGS and - R2R3_REGS which are used by the function return registers (R0,R1) and - the register arguments (R2,R3), respectively. I'm reluctant to define - this macro since it stomps on many potential optimisations. Ideally - it should have a register class argument so that not all the register - classes gets penalised for the sake of a naughty few... For long - double arithmetic we need two additional registers that we can use as - spill registers. */ - -#define SMALL_REGISTER_CLASSES (TARGET_SMALL_REG_CLASS && TARGET_PARALLEL_MPY) - -#define BASE_REG_CLASS ADDR_REGS -#define INDEX_REG_CLASS INDEX_REGS - -/* - Register constraints for the C4x - - a - address reg (ar0-ar7) - b - stack reg (sp) - c - other gp int-only reg - d - data/int reg (equiv. to f) - f - data/float reg - h - data/long double reg (equiv. to f) - k - block count (bk) - q - r0-r7 - t - r0-r1 - u - r2-r3 - v - repeat count (rc) - x - index register (ir0-ir1) - y - status register (st) - z - dp reg (dp) - - Memory/constant constraints for the C4x - - G - short float 16-bit - I - signed 16-bit constant (sign extended) - J - signed 8-bit constant (sign extended) (C4x only) - K - signed 5-bit constant (sign extended) (C4x only for stik) - L - unsigned 16-bit constant - M - unsigned 8-bit constant (C4x only) - N - ones complement of unsigned 16-bit constant - Q - indirect arx + 9-bit signed displacement - (a *-arx(n) or *+arx(n) is used to account for the sign bit) - R - indirect arx + 5-bit unsigned displacement (C4x only) - S - indirect arx + 0, 1, or irn displacement - T - direct symbol ref - > - indirect with autoincrement - < - indirect with autodecrement - } - indirect with post-modify - { - indirect with pre-modify - */ - -#define REG_CLASS_FROM_LETTER(CC) \ - ( ((CC) == 'a') ? ADDR_REGS \ - : ((CC) == 'b') ? SP_REG \ - : ((CC) == 'c') ? INT_REGS \ - : ((CC) == 'd') ? EXT_REGS \ - : ((CC) == 'f') ? EXT_REGS \ - : ((CC) == 'h') ? EXT_REGS \ - : ((CC) == 'k') ? BK_REG \ - : ((CC) == 'q') ? EXT_LOW_REGS \ - : ((CC) == 't') ? R0R1_REGS \ - : ((CC) == 'u') ? R2R3_REGS \ - : ((CC) == 'v') ? RC_REG \ - : ((CC) == 'x') ? INDEX_REGS \ - : ((CC) == 'y') ? ST_REG \ - : ((CC) == 'z') ? DP_REG \ - : NO_REGS ) - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_BASE_P(REGNO) \ - (IS_ADDR_REG(REGNO) || IS_ADDR_REG((unsigned)reg_renumber[REGNO])) - -#define REGNO_OK_FOR_INDEX_P(REGNO) \ - (IS_INDEX_REG(REGNO) || IS_INDEX_REG((unsigned)reg_renumber[REGNO])) - -extern enum reg_class c4x_preferred_reload_class (); -#define PREFERRED_RELOAD_CLASS(X, CLASS) c4x_preferred_reload_class(X, CLASS) - -extern enum reg_class c4x_limit_reload_class (); -#define LIMIT_RELOAD_CLASS(X, CLASS) c4x_limit_reload_class(X, CLASS) - -extern enum reg_class c4x_secondary_memory_needed (); -#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ -c4x_secondary_memory_needed(CLASS1, CLASS2, MODE) - -#define CLASS_MAX_NREGS(CLASS, MODE) \ -(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : ((MODE) == HFmode) ? 1 : \ -((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) - -#define IS_INT5_CONST(VAL) (((VAL) <= 15) && ((VAL) >= -16)) /* 'K' */ - -#define IS_UINT5_CONST(VAL) (((VAL) <= 31) && ((VAL) >= 0)) /* 'R' */ - -#define IS_INT8_CONST(VAL) (((VAL) <= 127) && ((VAL) >= -128)) /* 'J' */ - -#define IS_UINT8_CONST(VAL) (((VAL) <= 255) && ((VAL) >= 0)) /* 'M' */ - -#define IS_INT16_CONST(VAL) (((VAL) <= 32767) && ((VAL) >= -32768)) /* 'I' */ - -#define IS_UINT16_CONST(VAL) (((VAL) <= 65535) && ((VAL) >= 0)) /* 'L' */ - -#define IS_NOT_UINT16_CONST(VAL) IS_UINT16_CONST(~(VAL)) /* 'N' */ - -#define IS_HIGH_CONST(VAL) (! TARGET_C3X && (((VAL) & 0xffff) == 0)) /* 'O' */ - - -#define IS_DISP1_CONST(VAL) (((VAL) <= 1) && ((VAL) >= -1)) /* 'S' */ - -#define IS_DISP8_CONST(VAL) (((VAL) <= 255) && ((VAL) >= -255)) /* 'Q' */ - -#define IS_DISP1_OFF_CONST(VAL) (IS_DISP1_CONST (VAL) \ - && IS_DISP1_CONST (VAL + 1)) - -#define IS_DISP8_OFF_CONST(VAL) (IS_DISP8_CONST (VAL) \ - && IS_DISP8_CONST (VAL + 1)) - -#define CONST_OK_FOR_LETTER_P(VAL, C) \ - ( ((C) == 'I') ? (IS_INT16_CONST (VAL)) \ - : ((C) == 'J') ? (! TARGET_C3X && IS_INT8_CONST (VAL)) \ - : ((C) == 'K') ? (! TARGET_C3X && IS_INT5_CONST (VAL)) \ - : ((C) == 'L') ? (IS_UINT16_CONST (VAL)) \ - : ((C) == 'M') ? (! TARGET_C3X && IS_UINT8_CONST (VAL)) \ - : ((C) == 'N') ? (IS_NOT_UINT16_CONST (VAL)) \ - : ((C) == 'O') ? (IS_HIGH_CONST (VAL)) \ - : 0 ) - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL, C) \ - ( ((C) == 'G') ? (fp_zero_operand (VAL)) \ - : ((C) == 'H') ? (c4x_H_constant (VAL)) \ - : 0 ) - -#define EXTRA_CONSTRAINT(VAL, C) \ - ( ((C) == 'Q') ? (c4x_Q_constraint (VAL)) \ - : ((C) == 'R') ? (c4x_R_constraint (VAL)) \ - : ((C) == 'S') ? (c4x_S_constraint (VAL)) \ - : ((C) == 'T') ? (c4x_T_constraint (VAL)) \ - : 0 ) - -#define SMALL_CONST(VAL, insn) \ - ( ((insn == NULL_RTX) || (get_attr_data (insn) == DATA_INT16)) \ - ? IS_INT16_CONST (VAL) \ - : ( (get_attr_data (insn) == DATA_NOT_UINT16) \ - ? IS_NOT_UINT16_CONST (VAL) \ - : ( (get_attr_data (insn) == DATA_HIGH_16) \ - ? IS_HIGH_CONST (VAL) \ - : IS_UINT16_CONST (VAL) \ - ) \ - ) \ - ) - -/* - I. Routine calling with arguments in registers - ---------------------------------------------- - - The TI C3x compiler has a rather unusual register passing algorithm. - Data is passed in the following registers (in order): - - AR2, R2, R3, RC, RS, RE - - However, the first and second floating point values are always in R2 - and R3 (and all other floats are on the stack). Structs are always - passed on the stack. If the last argument is an ellipsis, the - previous argument is passed on the stack so that its address can be - taken for the stdargs macros. - - Because of this, we have to pre-scan the list of arguments to figure - out what goes where in the list. - - II. Routine calling with arguments on stack - ------------------------------------------- - - Let the subroutine declared as "foo(arg0, arg1, arg2);" have local - variables loc0, loc1, and loc2. After the function prologue has - been executed, the stack frame will look like: - - [stack grows towards increasing addresses] - I-------------I - 5 I saved reg1 I <= SP points here - I-------------I - 4 I saved reg0 I - I-------------I - 3 I loc2 I - I-------------I - 2 I loc1 I - I-------------I - 1 I loc0 I - I-------------I - 0 I old FP I <= FP (AR3) points here - I-------------I - -1 I return PC I - I-------------I - -2 I arg0 I - I-------------I - -3 I arg1 I - I-------------I - -4 I arg2 I - I-------------I - - All local variables (locn) are accessible by means of +FP(n+1) - addressing, where n is the local variable number. - - All stack arguments (argn) are accessible by means of -FP(n-2). - - The stack pointer (SP) points to the last register saved in the - prologue (regn). - - Note that a push instruction performs a preincrement of the stack - pointer. (STACK_PUSH_CODE == PRE_INC) - - III. Registers used in function calling convention - -------------------------------------------------- - - Preserved across calls: R4...R5 (only by PUSH, i.e. lower 32 bits) - R6...R7 (only by PUSHF, i.e. upper 32 bits) - AR3...AR7 - - (Because of this model, we only assign FP values in R6, R7 and - only assign integer values in R4, R5.) - - These registers are saved at each function entry and restored at - the exit. Also it is expected any of these not affected by any - call to user-defined (not service) functions. - - Not preserved across calls: R0...R3 - R4...R5 (upper 8 bits) - R6...R7 (lower 8 bits) - AR0...AR2, IR0, IR1, BK, ST, RS, RE, RC - - These registers are used arbitrary in a function without being preserved. - It is also expected that any of these can be clobbered by any call. - - Not used by GCC (except for in user "asm" statements): - IE (DIE), IF (IIE), IOF (IIF) - - These registers are never used by GCC for any data, but can be used - with "asm" statements. */ - -#define C4X_ARG0 -2 -#define C4X_LOC0 1 - -/* Basic Stack Layout */ - -/* The stack grows upward, stack frame grows upward, and args grow - downward. */ - -#define STARTING_FRAME_OFFSET C4X_LOC0 -#define FIRST_PARM_OFFSET(FNDECL) (C4X_ARG0 + 1) -#define ARGS_GROW_DOWNWARD -#define STACK_POINTER_OFFSET 1 - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ - -/* #define STACK_GROWS_DOWNWARD */ -/* Like the dsp16xx, i370, i960, and we32k ports */ - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ - -/* #define FRAME_GROWS_DOWNWARD */ - - -/* Registers That Address the Stack Frame */ - -#define STACK_POINTER_REGNUM SP_REGNO /* SP */ -#define FRAME_POINTER_REGNUM AR3_REGNO /* AR3 */ -#define ARG_POINTER_REGNUM AR3_REGNO /* AR3 */ -#define STATIC_CHAIN_REGNUM AR0_REGNO /* AR0 */ - -/* Eliminating Frame Pointer and Arg Pointer */ - -#define FRAME_POINTER_REQUIRED 0 - -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ -{ \ - int regno; \ - int offset = 0; \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ - if (regs_ever_live[regno] && ! call_used_regs[regno]) \ - offset += TARGET_PRESERVE_FLOAT \ - && ((regno == R6_REGNO) || (regno == R7_REGNO)) \ - ? 2 : 1; \ - (DEPTH) = -(offset + get_frame_size ()); \ -} - -/* This is a hack... We need to specify a register. */ -#define ELIMINABLE_REGS \ - {{ FRAME_POINTER_REGNUM, FRAME_POINTER_REGNUM }} - -#define CAN_ELIMINATE(FROM, TO) \ - (! (((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - || ((FROM) == FRAME_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM))) - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ \ - int regno; \ - int offset = 0; \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ - if (regs_ever_live[regno] && ! call_used_regs[regno]) \ - offset += TARGET_PRESERVE_FLOAT \ - && ((regno == R6_REGNO) || (regno == R7_REGNO)) \ - ? 2 : 1; \ - (OFFSET) = -(offset + get_frame_size ()); \ -} - - -/* Passing Function Arguments on the Stack */ - -#if 0 -#define PUSH_ROUNDING(BYTES) (BYTES) -#endif -#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 - -/* The following structure is used by calls.c, function.c, c4x.c */ - -typedef struct c4x_args -{ - int floats; - int ints; - int maxfloats; - int maxints; - int init; - int var; - int prototype; - int args; -} -CUMULATIVE_ARGS; - -extern void c4x_init_cumulative_args(); - -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ - (c4x_init_cumulative_args (&CUM, FNTYPE, LIBNAME)) - -extern void c4x_function_arg_advance(); - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - (c4x_function_arg_advance (&CUM, MODE, TYPE, NAMED)) - -extern struct rtx_def *c4x_function_arg(); - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - (c4x_function_arg(&CUM, MODE, TYPE, NAMED)) - -/* Define the profitability of saving registers around calls. - NOTE: For now we turn this off because caller-save assumes - that a register with a QFmode quantity can be saved/restored - using QImode. */ - -/* #define CALLER_SAVE_PROFITABLE(REFS,CALLS) 0 */ - -/* Never pass data by reference. */ - -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0 - -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0 - -/* 1 if N is a possible register number for function argument passing. */ - -#define FUNCTION_ARG_REGNO_P(REGNO) \ - ( ( ((REGNO) == AR2_REGNO) /* AR2 */ \ - || ((REGNO) == R2_REGNO) /* R2 */ \ - || ((REGNO) == R3_REGNO) /* R3 */ \ - || ((REGNO) == RC_REGNO) /* RC */ \ - || ((REGNO) == RS_REGNO) /* RS */ \ - || ((REGNO) == RE_REGNO)) /* RE */ \ - ? 1 \ - : 0) - -/* How Scalar Function Values Are Returned */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx(REG, TYPE_MODE(VALTYPE), R0_REGNO) /* Return in R0 */ - -#define LIBCALL_VALUE(MODE) \ - gen_rtx(REG, MODE, R0_REGNO) /* Return in R0 */ - -#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == R0_REGNO) - -/* How Large Values Are Returned */ - -#define DEFAULT_PCC_STRUCT_RETURN 0 -#define STRUCT_VALUE_REGNUM AR0_REGNO /* AR0 */ - - -/* Function Entry and Exit */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) c4x_function_prologue(FILE, SIZE) -#define FUNCTION_EPILOGUE(FILE, SIZE) c4x_function_epilogue(FILE, SIZE) - - -/* Generating Code for Profiling */ - -/* Note that the generated assembly uses the ^ operator to load the 16 - MSBs of the address. This is not supported by the TI assembler. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tldhi\t^LP%d,ar2\n", (LABELNO)); \ - fprintf (FILE, "\tor\t#LP%d,ar2\n", (LABELNO)); \ - fprintf (FILE, "\tcall\tmcount\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tldiu\t^LP%d,ar2\n", (LABELNO)); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#LP%d,ar2\n", (LABELNO)); \ - fprintf (FILE, "\tcall\tmcount\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - } - -/* There are three profiling modes for basic blocks available. - The modes are selected at compile time by using the options - -a or -ax of the gnu compiler. - The variable `profile_block_flag' will be set according to the - selected option. - - profile_block_flag == 0, no option used: - - No profiling done. - - profile_block_flag == 1, -a option used. - - Count frequency of execution of every basic block. - - profile_block_flag == 2, -ax option used. - - Generate code to allow several different profiling modes at run time. - Available modes are: - Produce a trace of all basic blocks. - Count frequency of jump instructions executed. - In every mode it is possible to start profiling upon entering - certain functions and to disable profiling of some other functions. - - The result of basic-block profiling will be written to a file `bb.out'. - If the -ax option is used parameters for the profiling will be read - from file `bb.in'. - -*/ - -#define FUNCTION_BLOCK_PROFILER(FILE, BLOCKNO) \ - if (profile_block_flag == 2) \ - { \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tr2\n"); \ - fprintf (FILE, "\tldhi\t^LPBX0,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \ - if (BLOCKNO > 32767) \ - { \ - fprintf (FILE, "\tldhi\t%d,r2\n", (BLOCKNO) >> 16); \ - fprintf (FILE, "\tor\t%d,r2\n", (BLOCKNO)); \ - } \ - else \ - { \ - fprintf (FILE, "\tldiu\t%d,r2\n", (BLOCKNO)); \ - } \ - fprintf (FILE, "\tcall\t___bb_init_trace_func\n"); \ - fprintf (FILE, "\tpop\tr2\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tr2\n"); \ - fprintf (FILE, "\tldiu\t^LPBX0,ar2\n"); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \ - if (BLOCKNO > 32767) \ - { \ - fprintf (FILE, "\tldi\t%d,r2\n", (BLOCKNO) >> 16); \ - fprintf (FILE, "\tlsh\t16,r2\n"); \ - fprintf (FILE, "\tor\t%d,r2\n", (BLOCKNO)); \ - } \ - else \ - { \ - fprintf (FILE, "\tldiu\t%d,r2\n", (BLOCKNO)); \ - } \ - fprintf (FILE, "\tcall\t___bb_init_trace_func\n"); \ - fprintf (FILE, "\tpop\tr2\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - } \ - else \ - { \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tldhi\t^LPBX0,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \ - fprintf (FILE, "\tcmpi\t0,*ar2\n"); \ - fprintf (FILE, "\tbne\t$+2\n"); \ - fprintf (FILE, "\tcall\t___bb_init_func\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tr2\n"); \ - fprintf (FILE, "\tldiu\t^LPBX0,ar2\n"); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar2\n"); \ - fprintf (FILE, "\tldi\t*ar2,r2\n"); \ - fprintf (FILE, "\tbne\t$+2\n"); \ - fprintf (FILE, "\tcall\t___bb_init_func\n"); \ - fprintf (FILE, "\tpop\tr2\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - } - -#define BLOCK_PROFILER(FILE, BLOCKNO) \ - if (profile_block_flag == 2) \ - { \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tar0\n"); \ - fprintf (FILE, "\tldhi\t^___bb,ar2\n"); \ - fprintf (FILE, "\tor\t#___bb,ar2\n"); \ - if (BLOCKNO > 32767) \ - { \ - fprintf (FILE, "\tldhi\t%d,ar0\n", (BLOCKNO) >> 16);\ - fprintf (FILE, "\tor\t%d,ar0\n", (BLOCKNO)); \ - } \ - else \ - { \ - fprintf (FILE, "\tldiu\t%d,ar0\n", (BLOCKNO)); \ - } \ - fprintf (FILE, "\tsti\tar0,*ar2\n"); \ - fprintf (FILE, "\tldhi\t^LPBX0,ar0\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar0\n"); \ - fprintf (FILE, "\tsti\tar0,*+ar2(1)\n"); \ - fprintf (FILE, "\tcall\t___bb_trace_func\n"); \ - fprintf (FILE, "\tpop\tar0\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tar0\n"); \ - fprintf (FILE, "\tldiu\t^___bb,ar2\n"); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#___bb,ar2\n"); \ - if (BLOCKNO > 32767) \ - { \ - fprintf (FILE, "\tldi\t%d,ar0\n", (BLOCKNO) >> 16); \ - fprintf (FILE, "\tlsh\t16,ar0\n"); \ - fprintf (FILE, "\tor\t%d,ar0\n", (BLOCKNO)); \ - } \ - else \ - { \ - fprintf (FILE, "\tldiu\t%d,ar0\n", (BLOCKNO)); \ - } \ - fprintf (FILE, "\tsti\tar0,*ar2\n"); \ - fprintf (FILE, "\tldiu\t^LPBX0,ar0\n"); \ - fprintf (FILE, "\tlsh\t16,ar0\n"); \ - fprintf (FILE, "\tor\t#LPBX0,ar0\n"); \ - fprintf (FILE, "\tsti\tar0,*+ar2(1)\n"); \ - fprintf (FILE, "\tcall\t___bb_trace_func\n"); \ - fprintf (FILE, "\tpop\tar0\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } \ - } \ - else \ - { \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tar0\n"); \ - fprintf (FILE, "\tldhi\t^LPBX2+%d,ar2\n", (BLOCKNO)); \ - fprintf (FILE, "\tor\t#LPBX2+%d,ar2\n", (BLOCKNO)); \ - fprintf (FILE, "\taddi3\t1,*ar2,ar0\n"); \ - fprintf (FILE, "\tsti\tar0,*ar2\n"); \ - fprintf (FILE, "\tpop\tar0\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tpush\tar0\n"); \ - fprintf (FILE, "\tldiu\t^LPBX2+%d,ar2\n", (BLOCKNO)); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#LPBX2+%d,ar2\n", (BLOCKNO)); \ - fprintf (FILE, "\tldiu\t*ar2,ar0\n"); \ - fprintf (FILE, "\taddi\t1,ar0\n"); \ - fprintf (FILE, "\tsti\tar0,*ar2\n"); \ - fprintf (FILE, "\tpop\tar0\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - } \ - } - -#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \ - { \ - fprintf (FILE, "\tpush\tst\n"); \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tcall\t___bb_trace_ret\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - fprintf (FILE, "\tpop\tst\n"); \ - } - -#define MACHINE_STATE_SAVE(ID) \ - asm(" push r0"); \ - asm(" pushf r0"); \ - asm(" push r1"); \ - asm(" pushf r1"); \ - asm(" push r2"); \ - asm(" pushf r2"); \ - asm(" push r3"); \ - asm(" pushf r3"); \ - asm(" push ar0"); \ - asm(" push ar1"); \ - asm(" .if .BIGMODEL"); \ - asm(" push dp"); \ - asm(" .endif"); \ - asm(" push ir0"); \ - asm(" push ir1"); \ - asm(" push bk"); \ - asm(" push rs"); \ - asm(" push re"); \ - asm(" push rc"); \ - asm(" .if .tms320C40"); \ - asm(" push r9"); \ - asm(" pushf r9"); \ - asm(" push r10"); \ - asm(" pushf r10"); \ - asm(" push r11"); \ - asm(" pushf r11"); \ - asm(" .endif"); - -#define MACHINE_STATE_RESTORE(ID) \ - asm(" .if .tms320C40"); \ - asm(" popf r11"); \ - asm(" pop r11"); \ - asm(" popf r10"); \ - asm(" pop r10"); \ - asm(" popf r9"); \ - asm(" pop r9"); \ - asm(" .endif"); \ - asm(" pop rc"); \ - asm(" pop re"); \ - asm(" pop rs"); \ - asm(" pop bk"); \ - asm(" pop ir1"); \ - asm(" pop ir0"); \ - asm(" .if .BIGMODEL"); \ - asm(" pop dp"); \ - asm(" .endif"); \ - asm(" pop ar1"); \ - asm(" pop ar0"); \ - asm(" popf r3"); \ - asm(" pop r3"); \ - asm(" popf r2"); \ - asm(" pop r2"); \ - asm(" popf r1"); \ - asm(" pop r1"); \ - asm(" popf r0"); \ - asm(" pop r0"); \ - -/* Implicit Calls to Library Routines */ - -#define MULQI3_LIBCALL "__mulqi3" -#define DIVQI3_LIBCALL "__divqi3" -#define UDIVQI3_LIBCALL "__udivqi3" -#define MODQI3_LIBCALL "__modqi3" -#define UMODQI3_LIBCALL "__umodqi3" - -#define DIVQF3_LIBCALL "__divqf3" - -#define MULHF3_LIBCALL "__mulhf3" -#define DIVHF3_LIBCALL "__divhf3" - -#define MULHI3_LIBCALL "__mulhi3" -#define SMULHI3_LIBCALL "__smulhi3_high" -#define UMULHI3_LIBCALL "__umulhi3_high" -#define DIVHI3_LIBCALL "__divhi3" -#define UDIVHI3_LIBCALL "__udivhi3" -#define MODHI3_LIBCALL "__modhi3" -#define UMODHI3_LIBCALL "__umodhi3" - -#define FLOATHIQF2_LIBCALL "__floathiqf2" -#define FLOATUNSHIQF2_LIBCALL "__ufloathiqf2" -#define FIX_TRUNCQFHI2_LIBCALL "__fix_truncqfhi2" -#define FIXUNS_TRUNCQFHI2_LIBCALL "__ufix_truncqfhi2" - -#define FLOATHIHF2_LIBCALL "__floathihf2" -#define FLOATUNSHIHF2_LIBCALL "__ufloathihf2" -#define FIX_TRUNCHFHI2_LIBCALL "__fix_trunchfhi2" -#define FIXUNS_TRUNCHFHI2_LIBCALL "__ufix_trunchfhi2" - -#define FFS_LIBCALL "__ffs" - -#define TARGET_MEM_FUNCTIONS - -/* Add any extra modes needed to represent the condition code. - - On the C4x, we have a "no-overflow" mode which is used when an ADD, - SUB, NEG, or MPY insn is used to set the condition code. This is - to prevent the combiner from optimising away a following CMP of the - result with zero when a signed conditional branch or load insn - follows. - - The problem is a subtle one and deals with the manner in which the - negative condition (N) flag is used on the C4x. This flag does not - reflect the status of the actual result but of the ideal result had - no overflow occured (when considering signed operands). - - For example, 0x7fffffff + 1 => 0x80000000 Z=0 V=1 N=0 C=0. Here - the flags reflect the untruncated result, not the actual result. - While the actual result is less than zero, the N flag is not set - since the ideal result of the addition without truncation would - have been positive. - - Note that the while the N flag is handled differently to most other - architectures, the use of it is self consistent and is not the - cause of the problem. - - Logical operations set the N flag to the MSB of the result so if - the result is negative, N is 1. However, integer and floating - point operations set the N flag to be the MSB of the result - exclusive ored with the overflow (V) flag. Thus if an overflow - occurs and the result does not have the MSB set (i.e., the result - looks like a positive number), the N flag is set. Conversely, if - an overflow occurs and the MSB of the result is set, N is set to 0. - Thus the N flag represents the sign of the result if it could have - been stored without overflow but does not represent the apparent - sign of the result. Note that most architectures set the N flag to - be the MSB of the result. - - The C4x approach to setting the N flag simplifies signed - conditional branches and loads which only have to test the state of - the N flag, whereas most architectures have to look at both the N - and V flags. The disadvantage is that there is no flag giving the - status of the sign bit of the operation. However, there are no - conditional load or branch instructions that make use of this - feature (e.g., BMI---branch minus) instruction. Note that BN and - BLT are identical in the C4x. - - To handle the problem where the N flag is set differently whenever - there is an overflow we use a different CC mode, CC_NOOVmode which - says that the CC reflects the comparison of the result against zero - if no overflow occured. - - For example, - - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "") - (minus:QI (match_dup 1) - (match_dup 2)))] - - Note that there is no problem for insns that don't return a result - like CMP, since the CC reflects the effect of operation. - - An example of a potential problem is when GCC - converts (LTU (MINUS (0x80000000) (0x7fffffff) (0x80000000))) - to (LEU (MINUS (0x80000000) (0x7fffffff) (0x7fffffff))) - to (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000))) - - Now (MINUS (0x80000000) (0x7fffffff)) returns 0x00000001 but the - C4x sets the N flag since the result without overflow would have - been 0xffffffff when treating the operands as signed integers. - Thus (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000))) sets the N - flag but (GE (0x00000001)) does not set the N flag. - - The upshot is that we can not use signed branch and conditional - load instructions after an add, subtract, neg, abs or multiply. - We must emit a compare insn to check the result against 0. */ - -#define EXTRA_CC_MODES CC_NOOVmode - -/* Define the names for the modes specified above. */ - -#define EXTRA_CC_NAMES "CC_NOOV" - -/* CC_NOOVmode should be used when the first operand is a PLUS, MINUS, NEG - or MULT. - CCmode should be used when no special processing is needed. */ -#define SELECT_CC_MODE(OP,X,Y) \ - ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ - || GET_CODE (X) == NEG || GET_CODE (X) == MULT \ - || GET_MODE (X) == ABS \ - || GET_CODE (Y) == PLUS || GET_CODE (Y) == MINUS \ - || GET_CODE (Y) == NEG || GET_CODE (Y) == MULT \ - || GET_MODE (Y) == ABS) \ - ? CC_NOOVmode : CCmode) - -extern struct rtx_def *c4x_gen_compare_reg (); - -/* Addressing Modes */ - -#define HAVE_POST_INCREMENT 1 -#define HAVE_PRE_INCREMENT 1 -#define HAVE_POST_DECREMENT 1 -#define HAVE_PRE_DECREMENT 1 -#define HAVE_PRE_MODIFY_REG 1 -#define HAVE_POST_MODIFY_REG 1 -#define HAVE_PRE_MODIFY_DISP 1 -#define HAVE_POST_MODIFY_DISP 1 - -#define HAVE_MULTIPLE_PACK 2 - -/* What about LABEL_REF? */ -#define CONSTANT_ADDRESS_P(X) (GET_CODE (X) == SYMBOL_REF) - -#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 unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -extern int c4x_check_legit_addr (); - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard or pseudo reg that can be used as an base. */ - -#define REG_OK_FOR_BASE_P(X) IS_ADDR_OR_PSEUDO_REG(REGNO(X)) - -/* Nonzero if X is a hard or pseudo reg that can be used as an index. */ - -#define REG_OK_FOR_INDEX_P(X) IS_INDEX_OR_PSEUDO_REG(REGNO(X)) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - if (c4x_check_legit_addr (MODE, X, 0)) \ - goto ADDR; \ -} - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ - -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) - -/* Nonzero if X is a hard reg that can be used as a base reg. */ - -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - if (c4x_check_legit_addr (MODE, X, 1)) \ - goto ADDR; \ -} - -#endif - -extern struct rtx_def *c4x_legitimize_address (); -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -{ \ - rtx new; \ - new = c4x_legitimize_address (X, MODE); \ - if (new != NULL_RTX) \ - { \ - (X) = new; \ - goto WIN; \ - } \ -} - - -/* No mode-dependent addresses on the C4x are autoincrements. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ - if (GET_CODE (ADDR) == PRE_DEC \ - || GET_CODE (ADDR) == POST_DEC \ - || GET_CODE (ADDR) == PRE_INC \ - || GET_CODE (ADDR) == POST_INC \ - || GET_CODE (ADDR) == POST_MODIFY \ - || GET_CODE (ADDR) == PRE_MODIFY) \ - goto LABEL - - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. - - The C4x can only load 16-bit immediate values, so we only allow - a restricted subset of CONST_INT and CONST_DOUBLE and reject - LABEL_REF, SYMBOL_REF, CONST, and HIGH codes. */ - -#define LEGITIMATE_CONSTANT_P(X) \ - ((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X)) \ - || (GET_CODE (X) == CONST_INT && c4x_I_constant (X))) - - -#define LEGITIMATE_DISPLACEMENT_P(X) IS_DISP8_CONST (INTVAL (X)) - -/* Descripting Relative Cost of Operations */ - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. - - Note that we return, rather than break so that rtx_cost doesn't - include CONST_COSTS otherwise expand_mult will think that it is - cheaper to synthesise a multiply rather than to use a multiply - instruction. I think this is because the algorithm synth_mult - doesn't take into account the loading of the operands, whereas the - calculation of mult_cost does. -*/ - - -#define RTX_COSTS(RTX, CODE, OUTER_CODE) \ - case MULT: \ - return COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT \ - || TARGET_MPYI ? 1 : 14); \ - case DIV: case UDIV: case MOD: case UMOD: \ - return COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT \ - ? 15 : 50); - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. - - An insn is assumed to cost 4 units. - COSTS_N_INSNS (N) is defined as (N) * 4 - 2. - - Some small integers are effectively free for the C40. We should - also consider if we are using the small memory model. With - the big memory model we require an extra insn for a constant - loaded from memory. */ - -#define SHIFT_CODE_P(C) ((C) == ASHIFT || (C) == ASHIFTRT || (C) == LSHIFTRT) - -#define LOGICAL_CODE_P(C) ((C) == NOT || (C) == AND \ - || (C) == IOR || (C) == XOR) - -#define NON_COMMUTATIVE_CODE_P ((C) == MINUS || (C) == COMPARE) - -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - if (c4x_J_constant (RTX)) \ - return 0; \ - if (TARGET_C3X && SHIFT_CODE_P (OUTER_CODE)) \ - return 3; \ - if (LOGICAL_CODE_P (OUTER_CODE) \ - ? c4x_L_constant (RTX) : c4x_I_constant (RTX)) \ - return 2; \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - return 4; \ - case CONST_DOUBLE: \ - if (c4x_H_constant (RTX)) \ - return 2; \ - if (GET_MODE (RTX) == QFmode) \ - return 4; \ - else \ - return 8; - -/* Compute the cost of an address. This is meant to approximate the size - and/or execution delay of an insn using that address. If the cost is - approximated by the RTL complexity, including CONST_COSTS above, as - is usually the case for CISC machines, this macro should not be defined. - For aggressively RISCy machines, only one insn format is allowed, so - this macro should be a constant. The value of this macro only matters - for valid addresses. We handle the most common address without - a call to c4x_address_cost. */ - -extern int c4x_address_cost (); - -#define ADDRESS_COST(ADDR) (REG_P (ADDR) ? 1 : c4x_address_cost (ADDR)) - -#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \ -if (REG_P (OP1) && ! REG_P (OP0)) \ -{ \ - rtx tmp = OP0; OP0 = OP1 ; OP1 = tmp; \ - CODE = swap_condition (CODE); \ -} - -#define EXT_CLASS_P(CLASS) (reg_class_subset_p (CLASS, EXT_REGS)) -#define ADDR_CLASS_P(CLASS) (reg_class_subset_p (CLASS, ADDR_REGS)) -#define INDEX_CLASS_P(CLASS) (reg_class_subset_p (CLASS, INDEX_REGS)) -#define EXPENSIVE_CLASS_P(CLASS) (ADDR_CLASS_P(CLASS) \ - || INDEX_CLASS_P(CLASS) || (CLASS) == SP_REG) - -/* Compute extra cost of moving data between one register class - and another. */ - -#define REGISTER_MOVE_COST(FROM, TO) 2 - -/* Memory move cost is same as fast register move. Maybe this should - be bumped up? */ - -#define MEMORY_MOVE_COST(M,C,I) 4 - -/* Branches are kind of expensive (even with delayed branching) so - make their cost higher. */ - -#define BRANCH_COST 8 - -/* Adjust the cost of dependencies. */ - -#define ADJUST_COST(INSN,LINK,DEP,COST) \ - (COST) = c4x_adjust_cost (INSN, LINK, DEP, COST) - -#define WORD_REGISTER_OPERATIONS - -/* Dividing the Output into Sections */ - -#define TEXT_SECTION_ASM_OP "\t.text" - -#define DATA_SECTION_ASM_OP "\t.data" - -#define USE_CONST_SECTION 1 - -#define CONST_SECTION_ASM_OP "\t.sect\t\".const\"" - -/* Do not use .init section so __main will be called on startup. This will - call __do_global_ctors and prepare for __do_global_dtors on exit. */ - -#if 0 -#define INIT_SECTION_ASM_OP "\t.sect\t\".init\"" -#endif - -#define FINI_SECTION_ASM_OP "\t.sect\t\".fini\"" - -/* Support const sections and the ctors and dtors sections for g++. - Note that there appears to be two different ways to support const - sections at the moment. You can either #define the symbol - READONLY_DATA_SECTION (giving it some code which switches to the - readonly data section) or else you can #define the symbols - EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and - SELECT_RTX_SECTION. We do both here just to be on the safe side. */ - -/* Define a few machine-specific details of the implementation of - constructors. - - The __CTORS_LIST__ goes in the .ctors section. Define CTOR_LIST_BEGIN - and CTOR_LIST_END to contribute to the .ctors section an instruction to - push a word containing 0 (or some equivalent of that). - - Define ASM_OUTPUT_CONSTRUCTOR to push the address of the constructor. */ - -#define CTORS_SECTION_ASM_OP "\t.sect\t\".ctors\"" -#define DTORS_SECTION_ASM_OP "\t.sect\t\".dtors\"" - -/* Constructor list on stack is in reverse order. Go to the end of the - list and go backwards to call constructors in the right order. */ - -#define DO_GLOBAL_CTORS_BODY \ -do { \ - extern func_ptr __CTOR_LIST__[]; \ - func_ptr *p, *beg = __CTOR_LIST__ + 1; \ - for (p = beg; *p ; p++) ; \ - while (p != beg) \ - (*--p) (); \ -} while (0) - -/* The TI tooling uses atexit. */ -#define HAVE_ATEXIT - -#undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_const, in_init, in_fini, in_ctors, in_dtors - -#undef EXTRA_SECTION_FUNCTIONS -#define EXTRA_SECTION_FUNCTIONS \ - CONST_SECTION_FUNCTION \ - INIT_SECTION_FUNCTION \ - FINI_SECTION_FUNCTION \ - CTORS_SECTION_FUNCTION \ - DTORS_SECTION_FUNCTION - -#define INIT_SECTION_FUNCTION \ -void \ -init_section () \ -{ \ - if (in_section != in_init) \ - { \ - fprintf (asm_out_file, ";\t.init\n"); \ - in_section = in_init; \ - } \ -} - -#define FINI_SECTION_FUNCTION \ -void \ -fini_section () \ -{ \ - if (in_section != in_fini) \ - { \ - fprintf (asm_out_file, "\t%s\n", FINI_SECTION_ASM_OP); \ - in_section = in_fini; \ - } \ -} - -#define READONLY_DATA_SECTION() const_section () - -#define CONST_SECTION_FUNCTION \ -void \ -const_section () \ -{ \ - extern void text_section(); \ - if (! USE_CONST_SECTION) \ - text_section(); \ - else if (in_section != in_const) \ - { \ - fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \ - in_section = in_const; \ - } \ -} - -#define ASM_STABS_OP "\t.stabs" - -/* The ctors and dtors sections are not normally put into use - by EXTRA_SECTIONS and EXTRA_SECTION_FUNCTIONS as defined in svr3.h, - but it can't hurt to define these macros for whatever systems use them. */ - -#define CTORS_SECTION_FUNCTION \ -void \ -ctors_section () \ -{ \ - if (in_section != in_ctors) \ - { \ - fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ - in_section = in_ctors; \ - } \ -} - -#define DTORS_SECTION_FUNCTION \ -void \ -dtors_section () \ -{ \ - if (in_section != in_dtors) \ - { \ - fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ - in_section = in_dtors; \ - } \ -} - -#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ - fprintf (FILE, "\t.sect\t\"%s\"\n", NAME); - -/* This is machine-dependent because it needs to push something - on the stack. */ - -/* A C statement (sans semicolon) to output an element in the table of - global constructors. */ -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - ctors_section (); \ - fprintf (FILE, "\t.word\t "); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - dtors_section (); \ - fprintf (FILE, "\t.word\t "); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* 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. */ - -#define SELECT_SECTION(DECL, RELOC) \ -{ \ - if (TREE_CODE (DECL) == STRING_CST) \ - { \ - if (! flag_writable_strings) \ - const_section (); \ - else \ - data_section (); \ - } \ - else if (TREE_CODE (DECL) == VAR_DECL) \ - { \ - if ((0 && RELOC) /* should be (flag_pic && RELOC) */ \ - || ! TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ - || ! DECL_INITIAL (DECL) \ - || (DECL_INITIAL (DECL) != error_mark_node \ - && ! TREE_CONSTANT (DECL_INITIAL (DECL)))) \ - data_section (); \ - else \ - const_section (); \ - } \ - else \ - const_section (); \ -} - -/* A C statement or statements to switch to the appropriate - section for output of RTX in mode MODE. RTX is some kind - of constant in RTL. The argument MODE is redundant except - in the case of a `const_int' rtx. Currently, these always - go into the const section. */ - -#define SELECT_RTX_SECTION(MODE, RTX) const_section() - - -/* Overall Framework of an Assembler File */ - -#define ASM_FILE_START(FILE) \ -{ \ - int dspversion = 0; \ - if (TARGET_C30) dspversion = 30; \ - if (TARGET_C31) dspversion = 31; \ - if (TARGET_C32) dspversion = 32; \ - if (TARGET_C40) dspversion = 40; \ - if (TARGET_C44) dspversion = 44; \ - fprintf (FILE, "\t.version\t%d\n", dspversion); \ - fprintf (FILE, "\t.file\t"); \ - if (TARGET_TI) \ - { \ - char *p; \ - char *after_dir = main_input_filename; \ - for (p = main_input_filename; *p; p++) \ - if (*p == '/') \ - after_dir = p + 1; \ - output_quoted_string (FILE, after_dir); \ - } \ - else \ - output_quoted_string (FILE, main_input_filename); \ - fprintf (FILE, "\n"); \ -} - -#define ASM_FILE_END(FILE) fprintf (FILE, "\t.end\n") - -/* We need to have a data section we can identify so that we can set - the DP register back to a data pointer in the small memory model. - This is only required for ISRs if we are paranoid that someone - may have quietly changed this register on the sly. */ - -#define ASM_IDENTIFY_GCC(FILE) \ - if (! TARGET_TI) fputs ("gcc2_compiled.:\n", FILE); \ - fputs ("\t.data\ndata_sec:\n", FILE); - -#define ASM_COMMENT_START ";" - -#define ASM_APP_ON "" -#define ASM_APP_OFF "" - -/* Output float/double constants QFmode. */ - -#define ASM_OUTPUT_BYTE_FLOAT(FILE, VALUE) \ -{ long l; \ - char str[30]; \ - REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ - REAL_VALUE_TO_DECIMAL (VALUE, "%20lf", str); \ - if (sizeof (int) == sizeof (long)) \ - fprintf (FILE, "\t.word\t0%08xh\t; %s\n", l, str);\ - else \ - fprintf (FILE, "\t.word\t0%08lxh\t; %s\n", l, str);\ -} - -/* Output long double constants HFmode. - The first word contains the exponent and first part of the mantissa - in the same manner as QFmode. The second word contains the full - mantissa. We should ensure that the two words are allocated within - the same page for the large memory model since we only output a single - LDP instruction. FIXME. The simplest solution probably is to output - a LDP for each load. */ - -#define ASM_OUTPUT_SHORT_FLOAT(FILE, VALUE) \ -{ long l[2]; \ - char str[30]; \ - REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \ - REAL_VALUE_TO_DECIMAL (VALUE, "%20lf", str); \ - l[1] = (l[0] << 8) | ((l[1] >> 24) & 0xff); \ - if (sizeof (int) == sizeof (long)) \ - fprintf (FILE, "\t.word\t0%08xh\t; %s\n\t.word\t0%08xh\n", \ - l[0], str, l[1]); \ - else \ - fprintf (FILE, "\t.word\t0%08lxh\t; %s\n\t.word\t0%08lxh\n", \ - l[0], str, l[1]); \ -} - -#define ASM_OUTPUT_CHAR(FILE, VALUE) \ -{ fprintf (FILE, "\t.word\t"); \ - output_addr_const (FILE, VALUE); \ - if (GET_CODE (VALUE) != SYMBOL_REF) \ - fprintf (FILE, " ; 0%08xh\n", INTVAL (VALUE)); \ - else \ - fputc ('\n', FILE); \ -} - -#define ASM_OUTPUT_BYTE(FILE, VALUE) \ - fprintf (FILE, "\t.word\t0%xh\n", (VALUE)) - -extern void c4x_output_ascii (); -#define ASM_OUTPUT_ASCII(FILE, PTR, LEN) c4x_output_ascii (FILE, PTR, LEN) - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - - -/* Output and Generation of Labels */ - -#define NO_DOT_IN_LABEL /* Only required for TI format */ - -#define ASM_OUTPUT_LABEL(FILE, NAME) \ -{ assemble_name (FILE, NAME); fputs (":\n", FILE); } - -#define ASM_GLOBALIZE_LABEL(FILE, NAME) \ -{ \ - fprintf (FILE, "\t.global\t"); \ - assemble_name (FILE, NAME); \ - fputs ("\n", FILE); \ -} - -#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ -{ \ - fprintf (FILE, "\t.ref\t"); \ - assemble_name (FILE, NAME); \ - fputc ('\n', FILE); \ -} - -/* A C statement to output on FILE an assembler pseudo-op to - declare a library function named external. - (Only needed to keep asm30 happy for ___divqf3 etc.) */ - -#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ -{ \ - fprintf (FILE, "\t.ref\t"); \ - assemble_name (FILE, XSTR (FUN, 0)); \ - fprintf (FILE, "\n"); \ -} - -/* The prefix to add to user-visible assembler symbols. */ - -#define USER_LABEL_PREFIX "_" - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ - -#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \ -asm_fprintf (FILE, "%s%d:\n", 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. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(BUFFER, PREFIX, NUM) \ - sprintf (BUFFER, "*%s%d", PREFIX, NUM) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s%d", (NAME), (LABELNO))) - - -/* Output of Dispatch Tables */ - -/* This is how to output an element of a case-vector that is absolute. */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.long\tL%d\n", VALUE); - -/* This is how to output an element of a case-vector that is relative. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\t.long\tL%d-L%d\n", VALUE, REL); - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "long int" - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 32 - -#define INT_TYPE_SIZE 32 -#define LONG_LONG_TYPE_SIZE 64 -#define FLOAT_TYPE_SIZE 32 -#define DOUBLE_TYPE_SIZE 32 -#define LONG_DOUBLE_TYPE_SIZE 64 /* actually only 40 */ - -/* Allow #sccs in preprocessor. */ - -#define SCCS_DIRECTIVE - -/* Output #ident as a .ident. */ - -#define ASM_OUTPUT_IDENT(FILE, NAME) \ - fprintf (FILE, "\t.ident \"%s\"\n", NAME); - -#define CPP_PREDEFINES "" - -/* This says how to output an assembler line - to define a local common symbol. */ - -#undef ASM_OUTPUT_LOCAL -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -( fputs ("\t.bss\t", FILE), \ - assemble_name (FILE, (NAME)), \ - fprintf (FILE, ",%u\n", (ROUNDED))) - -/* Output of Uninitialized Variables */ - -#undef ASM_OUTPUT_COMMON -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs ("\t.globl\t", FILE), \ - assemble_name (FILE, (NAME)), \ - fputs ("\n\t.bss\t", FILE), \ - assemble_name (FILE, (NAME)), \ - fprintf (FILE, ",%u\n", (ROUNDED))) - -/* Macros Controlling Initialization Routines */ - -#define OBJECT_FORMAT_COFF -#define REAL_NM_FILE_NAME "c4x-nm" - -/* Output of Assembler Instructions */ - -/* Register names when used for integer modes. */ - -#define REGISTER_NAMES \ -{ \ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "ar0", "ar1", "ar2", "ar3", "ar4", "ar5", "ar6", "ar7", \ - "dp", "ir0", "ir1", "bk", "sp", "st", "die", "iie", \ - "iif", "rs", "re", "rc", "r8", "r9", "r10", "r11" \ -} - -/* Alternate register names when used for floating point modes. */ - -#define FLOAT_REGISTER_NAMES \ -{ \ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ - "ar0", "ar1", "ar2", "ar3", "ar4", "ar5", "ar6", "ar7", \ - "dp", "ir0", "ir1", "bk", "sp", "st", "die", "iie", \ - "iif", "rs", "re", "rc", "f8", "f9", "f10", "f11" \ -} - - -extern void c4x_print_operand (); -#define PRINT_OPERAND(FILE, X, CODE) c4x_print_operand(FILE, X, CODE) - -/* Determine which codes are valid without a following integer. These must - not be alphabetic. */ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '#') - -extern void c4x_print_operand_address (); -#define PRINT_OPERAND_ADDRESS(FILE, X) c4x_print_operand_address(FILE, X) - -/* Define this macro if you want to implement any pragmas. If defined, it - should be a C expression to be executed when #pragma is seen. The - argument STREAM is the stdio input stream from which the source - text can be read. CH is the first character after the #pragma. The - result of the expression is the terminating character found - (newline or EOF). */ -extern int c4x_handle_pragma (); -#define HANDLE_PRAGMA(GETC, UNGETC, NAME) \ - c4x_handle_pragma (GETC, UNGETC, NAME) - -extern void c4x_set_default_attributes (); -#define SET_DEFAULT_DECL_ATTRIBUTES(DECL, ATTRIBUTES) \ - c4x_set_default_attributes (DECL, &ATTRIBUTES) - -extern int c4x_valid_type_attribute_p (); -#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS) \ - (c4x_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS)) - -/* Assembler Commands for Alignment */ - -#define ASM_OUTPUT_SKIP(FILE, SIZE) \ -{ int c = SIZE; \ - for (; c > 0; --c) \ - fprintf (FILE,"\t.word\t0\n"); \ -} - -#define ASM_NO_SKIP_IN_TEXT 1 - -/* I'm not sure about this one. FIXME. */ - -#define ASM_OUTPUT_ALIGN(FILE, LOG) \ - if ((LOG) != 0) \ - fprintf (FILE, "\t.align\t%d\n", (1 << (LOG))) - - -/* Macros for SDB and DWARF Output (use .sdef instead of .def - to avoid conflict with TI's use of .def) */ - -#define SDB_DELIM "\n" -#define SDB_DEBUGGING_INFO - -#define PUT_SDB_DEF(A) \ -do { fprintf (asm_out_file, "\t.sdef\t"); \ - ASM_OUTPUT_LABELREF (asm_out_file, A); \ - fprintf (asm_out_file, SDB_DELIM); } while (0) - -#define PUT_SDB_PLAIN_DEF(A) \ - fprintf (asm_out_file,"\t.sdef\t.%s%s", A, SDB_DELIM) - -#define PUT_SDB_BLOCK_START(LINE) \ - fprintf (asm_out_file, \ - "\t.sdef\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) - -#define PUT_SDB_BLOCK_END(LINE) \ - fprintf (asm_out_file, \ - "\t.sdef\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) - -#define PUT_SDB_FUNCTION_START(LINE) \ - fprintf (asm_out_file, \ - "\t.sdef\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) - -#define PUT_SDB_FUNCTION_END(LINE) \ - fprintf (asm_out_file, \ - "\t.sdef\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) - -#define PUT_SDB_EPILOGUE_END(NAME) \ -do { fprintf (asm_out_file, "\t.sdef\t"); \ - ASM_OUTPUT_LABELREF (asm_out_file, NAME); \ - fprintf (asm_out_file, \ - "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0) - - -/* Define results of standard character escape sequences. */ - -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - -/* This is the kind of divide that is easiest to do in the general case. */ - -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Define this as 1 if `char' should by default be signed; else as 0. */ - -#define DEFAULT_SIGNED_CHAR 1 - -/* A function address in a call instruction is a byte address (for - indexing purposes) so give the MEM rtx a byte's mode. */ - -#define FUNCTION_MODE QImode - -#define SLOW_BYTE_ACCESS 0 - -/* Specify the machine mode that pointers have. After generation of - RTL, the compiler makes no further distinction between pointers and - any other objects of this machine mode. */ - -#define Pmode QImode - -/* On the C4x we can write the following code. We have to clear the cache - every time we execute it because the data in the stack could change. - - laj $+4 - addi3 4,r11,ar0 - lda *ar0,ar1 - lda *+ar0(1),ar0 - bud ar1 - nop - nop - or 1000h,st - .word FNADDR - .word CXT - - On the c3x this is a bit more difficult. We have to write self - modifying code here. So we have to clear the cache every time - we execute it because the data in the stack could change. - - ldiu TOP_OF_FUNCTION,ar1 - lsh 16,ar1 - or BOTTOM_OF_FUNCTION,ar1 - ldiu TOP_OF_STATIC,ar0 - bud ar1 - lsh 16,ar0 - or BOTTOM_OF_STATIC,ar0 - or 1000h,st - - */ - -#define TRAMPOLINE_SIZE (TARGET_C3X ? 8 : 10) - -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - if (TARGET_C3X) \ - { \ - asm_fprintf (FILE, "\tldiu\t0,ar1\n"); \ - asm_fprintf (FILE, "\tlsh\t16,ar1\n"); \ - asm_fprintf (FILE, "\tor\t0,ar1\n"); \ - asm_fprintf (FILE, "\tldiu\t0,ar0\n"); \ - asm_fprintf (FILE, "\tbud\tar1\n"); \ - asm_fprintf (FILE, "\tlsh\t16,ar0\n"); \ - asm_fprintf (FILE, "\tor\t0,ar0\n"); \ - asm_fprintf (FILE, "\tor\t1000h,st\n"); \ - } \ - else \ - { \ - asm_fprintf (FILE, "\tlaj\t$+4\n"); \ - asm_fprintf (FILE, "\taddi3\t4,r11,ar0\n"); \ - asm_fprintf (FILE, "\tlda\t*ar0,ar1\n"); \ - asm_fprintf (FILE, "\tlda\t*+ar0(1),ar0\n"); \ - asm_fprintf (FILE, "\tbud\tar1\n"); \ - asm_fprintf (FILE, "\tnop\n"); \ - asm_fprintf (FILE, "\tnop\n"); \ - asm_fprintf (FILE, "\tor\t1000h,st\n"); \ - asm_fprintf (FILE, "\t.word\t0\n"); \ - asm_fprintf (FILE, "\t.word\t0\n"); \ - } \ -} - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - if (TARGET_C3X) \ - { \ - rtx tmp1, tmp2; \ - tmp1 = expand_shift (RSHIFT_EXPR, QImode, FNADDR, \ - size_int (16), 0, 1); \ - tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ - gen_rtx (CONST_INT, VOIDmode, 0x5069), \ - size_int (16), 0, 1); \ - emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ - emit_move_insn (gen_rtx (MEM, QImode, \ - plus_constant (tramp, 0)), tmp1); \ - tmp1 = expand_and (FNADDR, gen_rtx (CONST_INT, VOIDmode, \ - 0xffff), 0); \ - tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ - gen_rtx (CONST_INT, VOIDmode, 0x1069), \ - size_int (16), 0, 1); \ - emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ - emit_move_insn (gen_rtx (MEM, QImode, \ - plus_constant (tramp, 2)), tmp1); \ - tmp1 = expand_shift (RSHIFT_EXPR, QImode, CXT, \ - size_int (16), 0, 1); \ - tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ - gen_rtx (CONST_INT, VOIDmode, 0x5068), \ - size_int (16), 0, 1); \ - emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ - emit_move_insn (gen_rtx (MEM, QImode, \ - plus_constant (tramp, 3)), tmp1); \ - tmp1 = expand_and (CXT, gen_rtx (CONST_INT, VOIDmode, \ - 0xffff), 0); \ - tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ - gen_rtx (CONST_INT, VOIDmode, 0x1068), \ - size_int (16), 0, 1); \ - emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ - emit_move_insn (gen_rtx (MEM, QImode, \ - plus_constant (tramp, 6)), tmp1); \ - } \ - else \ - { \ - emit_move_insn (gen_rtx (MEM, QImode, \ - plus_constant (TRAMP, 8)), FNADDR); \ - emit_move_insn (gen_rtx (MEM, QImode, \ - plus_constant (TRAMP, 9)), CXT); \ - } \ -} - -/* Specify the machine mode that this machine uses for the index in - the tablejump instruction. */ - -#define CASE_VECTOR_MODE Pmode - -/* Max number of (32-bit) bytes we can move from memory to memory - in one reasonably fast instruction. */ - -#define MOVE_MAX 1 - -/* MOVE_RATIO is the number of move instructions that is better than a - block move. */ - -#define MOVE_RATIO 2 /* Default value */ - -#define BSS_SECTION_ASM_OP ".bss" - -#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \ - asm_fprintf (FILE, "\tpush\t%s\n", reg_names[REGNO]) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE, REGNO) \ - asm_fprintf (FILE, "\tpop\t%s\n", reg_names[REGNO]) - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ - -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* We need to use direct addressing for large constants and addresses - that cannot fit within an instruction. We must check for these - after after the final jump optimisation pass, since this may - introduce a local_move insn for a SYMBOL_REF. This pass - must come before delayed branch slot filling since it can generate - additional instructions. */ - -#define MACHINE_DEPENDENT_REORG(INSNS) c4x_process_after_reload(INSNS) - -#define MACHINE_DEPENDENT_COMBINE(INSNS) c4x_combine_parallel(INSNS) - -#define DBR_OUTPUT_SEQEND(FILE) \ -if (final_sequence != NULL_RTX) \ -{ \ - int count; \ - int laj = GET_CODE (XEXP (XEXP (final_sequence, 0), 0)) == CALL_INSN; \ - \ - count = dbr_sequence_length(); \ - while (count < (laj ? 2 : 3)) \ - { \ - fputs("\tnop\n", FILE); \ - count++; \ - } \ - if (laj) \ - fputs("\tpush\tr11\n", FILE); \ -} - -#define NO_FUNCTION_CSE - -/* We don't want a leading tab. */ - -#define ASM_OUTPUT_ASM(FILE, STRING) fprintf (FILE, "%s\n", STRING) - -/* Define the codes that are matched by predicates in c4x.c. */ - -#define PREDICATE_CODES \ - {"fp_zero_operand", {CONST_DOUBLE}}, \ - {"const_operand", {CONST_INT, CONST_DOUBLE}}, \ - {"stik_const_operand", {CONST_INT}}, \ - {"not_const_operand", {CONST_INT}}, \ - {"reg_operand", {REG, SUBREG}}, \ - {"reg_or_const_operand", {REG, SUBREG, CONST_INT, CONST_DOUBLE}},\ - {"r0r1_reg_operand", {REG, SUBREG}}, \ - {"r2r3_reg_operand", {REG, SUBREG}}, \ - {"ext_low_reg_operand", {REG, SUBREG}}, \ - {"ext_reg_operand", {REG, SUBREG}}, \ - {"std_reg_operand", {REG, SUBREG}}, \ - {"addr_reg_operand", {REG, SUBREG}}, \ - {"index_reg_operand", {REG, SUBREG}}, \ - {"dp_reg_operand", {REG}}, \ - {"sp_reg_operand", {REG}}, \ - {"st_reg_operand", {REG}}, \ - {"rc_reg_operand", {REG}}, \ - {"call_operand", {REG, SYMBOL_REF}}, \ - {"src_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \ - {"src_hi_operand", {SUBREG, REG, MEM, CONST_DOUBLE}}, \ - {"lsrc_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \ - {"tsrc_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \ - {"any_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \ - {"par_ind_operand", {MEM}}, \ - {"parallel_operand", {SUBREG, REG, MEM}}, \ - {"mem_operand", {MEM}}, \ - - -/* Variables in c4x.c */ - -extern enum reg_class c4x_regclass_map[];/* smallest class containing REGNO */ -extern enum machine_mode c4x_caller_save_map[]; - -extern struct rtx_def *c4x_compare_op0; /* operand 0 for comparisons */ -extern struct rtx_def *c4x_compare_op1; /* operand 1 for comparisons */ - -extern int c4x_rpts_cycles; /* max cycles for RPTS */ -extern int c4x_cpu_version; /* cpu version C30/31/32/40/44 */ - -/* Functions in c4x.c */ - -extern void c4x_function_prologue (); - -extern void c4x_function_epilogue (); - -extern struct rtx_def *c4x_operand_subword (); - -extern struct rtx_def *c4x_adj_offsettable_operand (); - -extern char *c4x_output_cbranch (); - -extern int c4x_null_epilogue_p (); - -extern int c4x_autoinc_operand (); - -extern int c4x_label_conflict (); - -extern int c4x_address_conflict (); - -extern int c4x_adjust_cost (); - -extern void c4x_process_after_reload (); - -extern void c4x_combine_parallel (); - -extern int c4x_rptb_nop_p (); - -extern int c4x_rptb_rpts_p (); - -extern int fp_zero_operand (); - -extern int const_operand (); - -extern int stik_const_operand (); - -extern int not_const_operand (); - -extern int parallel_operand (); - -extern int reg_or_const_operand (); - -extern int reg_operand (); - -extern int reg_imm_operand (); - -extern int r0r1_reg_operand (); - -extern int r2r3_reg_operand (); - -extern int ext_low_reg_operand (); - -extern int ext_reg_operand (); - -extern int std_reg_operand (); - -extern int src_operand (); - -extern int src_hi_operand (); - -extern int lsrc_operand (); - -extern int tsrc_operand (); - -extern int addr_reg_operand (); - -extern int index_reg_operand (); - -extern int dp_reg_operand (); - -extern int sp_reg_operand (); - -extern int rc_reg_operand (); - -extern int st_reg_operand (); - -extern int ar0_reg_operand (); - -extern int ar0_mem_operand (); - -extern int ar1_reg_operand (); - -extern int ar1_mem_operand (); - -extern int ar2_reg_operand (); - -extern int ar2_mem_operand (); - -extern int ar3_reg_operand (); - -extern int ar3_mem_operand (); - -extern int ar4_reg_operand (); - -extern int ar4_mem_operand (); - -extern int ar5_reg_operand (); - -extern int ar5_mem_operand (); - -extern int ar6_reg_operand (); - -extern int ar6_mem_operand (); - -extern int ar7_reg_operand (); - -extern int ar7_mem_operand (); - -extern int ir0_reg_operand (); - -extern int ir0_mem_operand (); - -extern int ir1_reg_operand (); - -extern int ir1_mem_operand (); - -extern int group1_reg_operand (); - -extern int group1_mem_operand (); - -extern int arx_reg_operand (); - -extern int call_operand (); - -extern int par_ind_operand (); - -extern int not_rc_reg (); - -extern int not_modify_reg (); - -extern int c4x_H_constant (); - -extern int c4x_I_constant (); - -extern int c4x_J_constant (); - -extern int c4x_L_constant (); - -extern int c4x_Q_constraint (); - -extern int c4x_R_constraint (); - -extern int c4x_S_constraint (); - -extern int c4x_T_constraint (); - -extern void c4x_emit_libcall (); - -extern void c4x_emit_libcall3 (); - -extern void c4x_emit_libcall_mulhi (); - -extern int legitimize_operands (); - -extern int valid_operands (); - -extern int valid_parallel_load_store (); - -extern int valid_parallel_operands_4 (); - -extern int valid_parallel_operands_5 (); - -extern int valid_parallel_operands_6 (); diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md deleted file mode 100755 index 1e3d343..0000000 --- a/gcc/config/c4x/c4x.md +++ /dev/null @@ -1,6877 +0,0 @@ -;; Machine description for the TMS320C[34]x for GNU C compiler -;; Copyright (C) 1994-98, 1999 Free Software Foundation, Inc. - -;; Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) -;; and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl) - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -; -; TODO : -; Set up addressing macros to handle direct memory references properly. -; Try using PQImode again for addresses since C30 only uses -; 24-bit addresses. Ideally GCC would emit different insns -; for QImode and Pmode, whether Pmode was QImode or PQImode. -; For addresses we wouldn't have to have a clobber of the CC -; associated with each insn and we could use MPYI in address -; calculations without having to synthesise a proper 32 bit multiply. - -; Additional C30/C40 instructions not coded: -; CALLcond, IACK, IDLE, LDE, LDFI, LDII, LDM, NORM, RETIcond -; ROLC, RORC, SIGI, STFI, STII, SUBC, SWI, TRAPcond - -; Additional C40 instructions not coded: -; LDEP, LDPE, LWRct, FRIEEE, TOIEEE, LAJcond, LATcond, RETIcondD - -; -; C4x MODES -; -; QImode char, short, int, long (32-bits) -; HImode long long (64-bits) -; QFmode float, double (32-bits) -; HFmode long double (40-bits) -; CCmode -; CC_NOOVmode - -; -; C4x PREDICATES: -; -; comparison_operator LT, GT, LE, GE, LTU, GTU, LEU, GEU, EQ, NE -; memory_operand memory [m] -; immediate_operand immediate constant [IKN] -; register_operand register [rf] -; general_operand register, memory, constant [rfmI] - -; addr_reg_operand AR0-AR7, pseudo reg [a] -; sp_reg_operand SP [b] -; std_reg_operand AR0-AR7, IR0-IR1, RC, RS, RE, SP, pseudo [c] -; ext_reg_operand R0-R11, pseudo reg [f] -; ext_low_reg_operand R0-R7, pseudo reg [q] -; index_reg_operand IR0-IR1, pseudo reg [x] -; st_reg_operand ST [y] -; dp_reg_operand DP [z] -; stik_const_operand 5-bit const [K] -; src_operand general operand [rfmHI] -; par_ind_operand indirect S mode (ARx + 0, 1, IRx) [S<>] -; parallel_operand par_ind_operand or ext_low_reg_operand - -; ADDI src2, src1, dst three operand op -; ADDI src, dst two operand op - -; Note that the predicates are only used when selecting a pattern -; to determine if an operand is valid. - -; The constraints then select which of the possible valid operands -; is present (and guide register selection). The actual assembly -; instruction is then selected on the basis of the constraints. - -; The extra constraint (valid_operands) is used to determine if -; the combination of operands is legitimate for the pattern. - -; -; C4x CONSTRAINTS: -; -; a address reg AR0-AR7 -; b stack pointer SP -; c other int reg AR0-AR7, IR0-IR1, RC, RS, RE -; d fp reg R0-R11 (sets CC when dst) -; e -; f fp reg R0-R11 (sets CC when dst) -; g general reg, memory, constant -; h fp reg (HFmode) R0-R11 (sets CC when dst) -; i immediate int constant -; j -; k block count BK -; l -; m memory -; n immediate int constant with known numeric value -; o offsettable memory -; p memory address -; q low fp reg R0-R7 (sets CC when dst) -; r general reg R0-R11, AR0-AR7, IR0-IR1, RC, RS, RE -; s immediate int constant (value not explicit) -; t R0-R1 -; u R2-R3 -; v repeat count reg RC -; w -; x index reg IR0-IR1 -; y status (CC) reg ST -; z data pointer DP - -; G fp zero -; H fp 16-bit constant -; I signed 16-bit -; J signed 8-bit (C4x only) -; K signed 5-bit (C4x only) -; L unsigned 16-bit -; M unsigned 8-bit (C4x only) -; N ones complement of unsigned 16-bit -; O 16 bit high constant -; Q ARx + 9-bit signed disp -; R ARx + 5-bit unsigned disp (C4x only) -; S ARx + 0, 1, IRx disp -; T symbol ref (direct) -; V non offsettable memory -; X any operand -; < memory operand with autodecrement addressing -; > memory operand with autoincrement addressing -; { memory operand with pre-modify addressing -; } memory operand with post-modify addressing - -; Note that the d, f, and h constraints are equivalent. -; The m constraint is equivalent to QT<>{} - -; Note that the constraints are used to select the operands -; for a chosen pattern. The constraint that requires the fewest -; instructions to load an operand is chosen. - -; Note that the 'r' constraint is mostly only used for src integer register -; operands, while 'c' and 'd' constraints are generally only used for dst -; integer register operands (the 'r' constraint is the union of the 'c' and -; 'd' constraints). When a register satisfying the 'd' constraint -; is used as a dst operand, the CC gets clobbered (except for LDIcond)---but -; not for 'c'. - -; The 'f' constraint is only for float register operands---when -; a register satisying the 'f' constraint is used as a dst operand, -; the CC gets clobbered (except for LDFcond). - -; The ! in front of the 'b' constaint says to GCC to disparage the -; use of this constraint. The 'b' constraint applies only to the SP. - -; Note that we deal with the condition code CC like some of the RISC -; architectures (arm, sh, sparc) where it is stored in a general register, -; in this case the hard register ST (21). Unlike these other architectures -; that do not set the CC with many instructions, the C[34]x architectures -; sets the CC for many instructions when the destination register is -; an extended precision register. While it would have been easier -; to use the generic cc0 register to store the CC, as with most of -; the other ported architectures, this constrains the setting and testing -; of the CC to be consecutive insns. Thus we would reduce the benefit -; of scheduling instructions to avoid pipeline conflicts and filling of -; delayed branch slots. - -; Since the C[34]x has many instructions that set the CC, we pay the -; price of having to explicity define which insns clobber the CC -; (rather than using the macro NOTICE_UPDATE_CC). - -; Note that many patterns say that the CC is clobbered when in fact -; that it may not be (depending on the destination register). -; We have to cover ourselves if an extended precision register -; is allocated to the destination register. -; Unfortunately, it is not easy to tell GCC that the clobbering of CC -; is register dependent. If we could tolerate the ST register being -; copied about, then we could store the CC in a pseudo register and -; use constructs such as (clobber (match_scratch:CC N "&y,X")) to -; indicate that the 'y' class (ST register) is clobbered for the -; first combination of operands, but not with the second. -; I tried this approach for a while but reload got unhappy since I -; didn't allow it to move the CC around. - -; Note that fundamental operations, such as moves, must not clobber the -; CC. Thus movqi choses a move instruction that doesn't clobber the CC. -; If GCC wants to combine a move with a compare, it is smart enough to -; chose the move instruction that sets the CC. - -; Unfortunately, the C[34]x instruction set does not have arithmetic or -; logical operations that never touch the CC. We thus have to assume -; that the CC may be clobbered at all times. If we define patterns -; such as addqi without the clobber of CC, then GCC will be forced -; to use registers such as the auxiliary registers which can cause -; horrible pipeline conflicts. The tradeoff is that GCC can't now -; sneak in an add instruction between setting and testing of the CC. - -; Most of the C[34]x instructions require operands of the following formats, -; where imm represents an immediate constant, dir a direct memory reference, -; ind an indirect memory reference, and reg a register: - -; src2 (op2) src1 (op1) dst (op0) -; imm dir ind reg | imm dir ind reg | reg Notes -;---------------------+----------------------+------ -; ILH T Q<> r | - - - 0 | r 2 operand -; - - S<> r | - - S<> r | r -; J - R - | - - R r | r C4x - -; Arithmetic operations use the I, J constraints for immediate constants, -; while logical operations use the L, J constraints. Floating point -; operations use the H constraint for immediate constants. - -; With most instructions the src2 and src1 operands are commutative -; (except for SUB, SUBR, ANDN). The assembler considers -; ADDI 10, R0, R1 and ADDI R0, 10, R1 to be equivalent. -; We thus match src2 and src1 with the src_operand predicate and -; use valid_operands as the extra constraint to reject invalid -; operand combinations. For example, ADDI @foo, @bar, R0. - -; Note that we use the ? modifier so that reload doesn't preferentially -; try the alternative where three registers are acceptable as -; operands (whenever an operand requires reloading). Instead it will try -; the 2 operand form which will produce better code since it won't require -; a new spill register. - -; Note that the floating point representation of 0.0 on the C4x -; is 0x80000000 (-2147483648). This value produces an warning -; message on 32-bit machines about the decimal constant being so large -; that it is unsigned. - -; With two operand instructions patterns having two sets, -; the compare set must come first to keep the combiner happy. -; While the combiner seems to cope most of the time with the -; compare set coming second, it's best to have it first. - -; -; C4x CONSTANT attributes -; -(define_attr "cpu" "c4x,c3x" - (const - (cond [(symbol_ref "TARGET_C3X") (const_string "c3x")] - (const_string "c4x")))) - -; -; C4x INSN ATTRIBUTES: -; -; lda load address, non-clobber CC -; store memory store, non-clobber CC -; load_load parallel memory loads, non-clobber CC -; load_store parallel memory load and store, non-clobber CC -; store_load parallel memory store and load, non-clobber CC -; store_store parallel memory stores, non-clobber CC -; unary two operand arithmetic, non-clobber CC -; unarycc two operand arithmetic, clobber CC -; binary three operand arithmetic, non-clobber CC -; binarycc three operand arithmetic, clobber CC -; compare compare, clobber CC -; call function call -; rets return from subroutine -; jump unconditional branch -; jmpc conditional branch -; db decrement and branch (unconditional) -; dbc decrement and branch (conditional) -; ldp load DP -; push stack push -; pop stack pop -; repeat block repeat -; repeat_top block repeat top -; laj link and jump -; multi multiple instruction -; misc nop (default) - -; The only real instructions that affect things are the ones that modify -; address registers and ones that call or jump. Note that the number -; of operands refers to the RTL insn pattern, not the number of explicit -; operands in the machine instruction. -; -(define_attr "type" "lda,store,unary,unarycc,binary,binarycc,compare,call,rets,jump,jmpc,db,dbc,misc,ldp,repeat,repeat_top,laj,load_load,load_store,store_load,store_store,push,pop,multi" - (const_string "misc")) - - -; Some instructions operate on unsigned data constants, some on signed data -; constants, or the ones complement of unsigned constants. -; This differentiates them. Default to signed. This attribute -; is used by the macro SMALL_CONST () (defined in c4x.h) to determine -; whether an immediate integer constant will fit within the instruction, -; or will have to be loaded using direct addressing from memory. -; Note that logical operations assume unsigned integers whereas -; arithmetic operations assume signed integers. Note that the C4x -; small immediate constant (J) used as src2 in three operand instructions -; is always signed. not_uint16 refers to a number that fits into 16-bits -; when one's complemented. -; -(define_attr "data" "int16,uint16,high_16,not_uint16" (const_string "int16")) - -(define_asm_attributes - [(set_attr "type" "multi")]) - -; -; C4x DELAY SLOTS -; -; Define delay slot scheduling for branch and call instructions. -; The C[34]x has three delay slots. Note that none of the three instructions -; that follow a delayed branch can be a Bcond, BcondD, BR, BRD, DBcond, -; DBcondD, CALL, CALLcond, TRAPcond, RETIcond, RETScond, RPTB, RPTS, or IDLE. -; -; Annulled branches are a bit difficult because the next instructions -; are preprocessed. -; The table below shows what phase of the c4x is executed. -; BccA[TF] label -; op1 fetch, decode and read executed -; op2 fetch and decode executed -; op3 fetch executed -; This means that we can allow any instruction in the last delay slot -; and only instructions which modify registers in the first two. -; lda can not be executed in the first delay slot -; and ldpk can not be executed in the first two delay slots. - -(define_attr "onlyreg" "false,true" - (cond [(eq_attr "type" "unary,unarycc") - (if_then_else (and (match_operand 0 "reg_imm_operand" "") - (match_operand 1 "reg_imm_operand" "")) - (const_string "true") (const_string "false")) - (eq_attr "type" "binary,binarycc") - (if_then_else (and (match_operand 0 "reg_imm_operand" "") - (and (match_operand 1 "reg_imm_operand" "") - (match_operand 2 "reg_imm_operand" ""))) - (const_string "true") (const_string "false"))] - (const_string "false"))) - -(define_attr "onlyreg_nomod" "false,true" - (cond [(eq_attr "type" "unary,unarycc,compare,lda,store") - (if_then_else (and (match_operand 0 "not_modify_reg" "") - (match_operand 1 "not_modify_reg" "")) - (const_string "true") (const_string "false")) - (eq_attr "type" "binary,binarycc") - (if_then_else (and (match_operand 0 "not_modify_reg" "") - (and (match_operand 1 "not_modify_reg" "") - (match_operand 2 "not_modify_reg" ""))) - (const_string "true") (const_string "false"))] - (const_string "false"))) - -(define_attr "not_repeat_reg" "false,true" - (cond [(eq_attr "type" "unary,unarycc,compare,lda,store") - (if_then_else (and (match_operand 0 "not_rc_reg" "") - (match_operand 1 "not_rc_reg" "")) - (const_string "true") (const_string "false")) - (eq_attr "type" "binary,binarycc") - (if_then_else (and (match_operand 0 "not_rc_reg" "") - (and (match_operand 1 "not_rc_reg" "") - (match_operand 2 "not_rc_reg" ""))) - (const_string "true") (const_string "false"))] - (const_string "false"))) - -(define_attr "in_annul_slot_1" "false,true" - (if_then_else (and (and (eq_attr "cpu" "c4x") - (eq_attr "type" "!jump,call,rets,jmpc,compare,db,dbc,repeat,repeat_top,laj,push,pop,lda,ldp,multi")) - (eq_attr "onlyreg" "true")) - (const_string "true") - (const_string "false"))) - -(define_attr "in_annul_slot_2" "false,true" - (if_then_else (and (and (eq_attr "cpu" "c4x") - (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,ldp,multi")) - (eq_attr "onlyreg_nomod" "true")) - (const_string "true") - (const_string "false"))) - -(define_attr "in_annul_slot_3" "false,true" - (if_then_else (and (eq_attr "cpu" "c4x") - (eq_attr "type" "!jump,call,rets,jmpc,unarycc,binarycc,db,dbc,repeat,repeat_top,laj,push,pop,multi")) - (const_string "true") - (const_string "false"))) - -(define_attr "in_delay_slot" "false,true" - (if_then_else (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,multi") - (const_string "true") - (const_string "false"))) - -(define_attr "in_repeat_slot" "false,true" - (if_then_else (and (eq_attr "cpu" "c4x") - (and (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,multi") - (eq_attr "not_repeat_reg" "true"))) - (const_string "true") - (const_string "false"))) - -(define_attr "in_dbc_slot" "false,true" - (if_then_else (eq_attr "type" "!jump,call,rets,jmpc,unarycc,binarycc,compare,db,dbc,repeat,repeat_top,laj,multi") - (const_string "true") - (const_string "false"))) - -(define_delay (eq_attr "type" "jmpc") - [(eq_attr "in_delay_slot" "true") - (eq_attr "in_annul_slot_1" "true") - (eq_attr "in_annul_slot_1" "true") - - (eq_attr "in_delay_slot" "true") - (eq_attr "in_annul_slot_2" "true") - (eq_attr "in_annul_slot_2" "true") - - (eq_attr "in_delay_slot" "true") - (eq_attr "in_annul_slot_3" "true") - (eq_attr "in_annul_slot_3" "true") ]) - - -(define_delay (eq_attr "type" "repeat_top") - [(eq_attr "in_repeat_slot" "true") (nil) (nil) - (eq_attr "in_repeat_slot" "true") (nil) (nil) - (eq_attr "in_repeat_slot" "true") (nil) (nil)]) - -(define_delay (eq_attr "type" "jump,db") - [(eq_attr "in_delay_slot" "true") (nil) (nil) - (eq_attr "in_delay_slot" "true") (nil) (nil) - (eq_attr "in_delay_slot" "true") (nil) (nil)]) - - -; Decrement and branch conditional instructions cannot modify the -; condition codes for the cycles in the delay slots. -; -(define_delay (eq_attr "type" "dbc") - [(eq_attr "in_dbc_slot" "true") (nil) (nil) - (eq_attr "in_dbc_slot" "true") (nil) (nil) - (eq_attr "in_dbc_slot" "true") (nil) (nil)]) - -; The LAJ instruction has three delay slots but the last slot is -; used for pushing the return address. Thus we can only use two slots. -; -(define_delay (eq_attr "type" "laj") - [(eq_attr "in_delay_slot" "true") (nil) (nil) - (eq_attr "in_delay_slot" "true") (nil) (nil)]) - -; -; C4x UNSPEC NUMBERS -; -; 1 BU/BUD -; 2 RPTS -; 3 LSH -; 4 cmphi -; 5 RCPF -; 6 RND -; 7 repeat block filler -; 8 loadhf_int -; 9 storehf_int -; 10 RSQRF - - -; -; C4x FUNCTIONAL UNITS -; -; Define functional units for instruction scheduling to minimise -; pipeline conflicts. -; -; With the C3x, an external memory write (with no wait states) takes -; two cycles and an external memory read (with no wait states) takes -; one cycle. However, an external read following an external write -; takes two cycles. With internal memory, reads and writes take -; half a cycle. -; -; When a C4x address register is loaded it will not be available for -; an extra machine cycle. Calculating with a C4x address register -; makes it unavailable for 2 machine cycles. To notify GCC of these -; pipeline delays, each of the auxiliary and index registers are declared -; as separate functional units. -; -; (define_function_unit NAME MULTIPLICITY SIMULTANEITY -; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) -; -; MULTIPLICITY 1 (C4x has no independent identical function units) -; SIMULTANEITY 0 (C4x is pipelined) -; READY_DELAY 1 (Results usually ready after every cyle) -; ISSUE_DELAY 1 (Can issue insns every cycle) - -; Just some dummy definitions. The real work is done in c4x_adjust_cost. -; These are needed so the min/max READY_DELAY is known. - -(define_function_unit "dummy" 1 0 (const_int 0) 1 1) -(define_function_unit "dummy" 1 0 (const_int 0) 2 1) -(define_function_unit "dummy" 1 0 (const_int 0) 3 1) - -;(define_function_unit "ar0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar0" "1") -; (eq_attr "usear0" "1"))) -; 3 1 ) - -;(define_function_unit "ar0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar0" "1") -; (eq_attr "usear0" "1"))) -; 2 1 ) - -;(define_function_unit "ar0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear0" "1") -; (eq_attr "readar0" "1"))) -; 2 1 ) - -; The attribute setar0 is set to 1 for insns where ar0 is a dst operand. -; Note that the attributes unarycc and binarycc do not apply -; if ar0 is a dst operand (only loading an ext. prec. reg. sets CC) -(define_attr "setar0" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar0" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -; The attribute usear0 is set to 1 for insns where ar0 is used -; for addressing, as a src operand, or as a dst operand. -(define_attr "usear0" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -; The attribute readar0 is set to 1 for insns where ar0 is a src operand. -(define_attr "readar0" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar0_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar0_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -;(define_function_unit "ar1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar1" "1") -; (eq_attr "usear1" "1"))) -; 3 1 ) - -;(define_function_unit "ar1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar1" "1") -; (eq_attr "usear1" "1"))) -; 2 1 ) - -;(define_function_unit "ar1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear1" "1") -; (eq_attr "readar1" "1"))) -; 2 1 ) - -(define_attr "setar1" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar1" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear1" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar1" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar1_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar1_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -;(define_function_unit "ar2" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar2" "1") -; (eq_attr "usear2" "1"))) -; 3 1 ) - -;(define_function_unit "ar2" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar2" "1") -; (eq_attr "usear2" "1"))) -; 2 1 ) - -;(define_function_unit "ar2" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear2" "1") -; (eq_attr "readar2" "1"))) -; 2 1 ) - -(define_attr "setar2" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar2_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar2" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar2_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear2" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar2_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar2_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar2_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar2_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar2" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar2_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar2_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar2_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -;(define_function_unit "ar3" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar3" "1") -; (eq_attr "usear3" "1"))) -; 3 1 ) - -;(define_function_unit "ar3" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar3" "1") -; (eq_attr "usear3" "1"))) -; 2 1 ) - -;(define_function_unit "ar3" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear3" "1") -; (eq_attr "readar3" "1"))) -; 2 1 ) - -(define_attr "setar3" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar3_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar3" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar3_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear3" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar3_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar3_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar3_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar3_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar3" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar3_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar3_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar3_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -;(define_function_unit "ar4" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar4" "1") -; (eq_attr "usear4" "1"))) -; 3 1 ) - -;(define_function_unit "ar4" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar4" "1") -; (eq_attr "usear4" "1"))) -; 2 1 ) - -;(define_function_unit "ar4" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear4" "1") -; (eq_attr "readar4" "1"))) -; 2 1 ) - -(define_attr "setar4" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar4_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar4" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar4_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear4" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar4_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar4_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar4_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar4_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar4" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar4_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar4_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar4_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -;(define_function_unit "ar5" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar5" "1") -; (eq_attr "usear5" "1"))) -; 3 1 ) - -;(define_function_unit "ar5" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar5" "1") -; (eq_attr "usear5" "1"))) -; 2 1 ) - -;(define_function_unit "ar5" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear5" "1") -; (eq_attr "readar5" "1"))) -; 2 1 ) - -(define_attr "setar5" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar5_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar5" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar5_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear5" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar5_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar5_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar5_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar5_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar5" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar5_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar5_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar5_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -;(define_function_unit "ar6" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar6" "1") -; (eq_attr "usear6" "1"))) -; 3 1 ) - -;(define_function_unit "ar6" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar6" "1") -; (eq_attr "usear6" "1"))) -; 2 1 ) - -;(define_function_unit "ar6" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear6" "1") -; (eq_attr "readar6" "1"))) -; 2 1 ) - -(define_attr "setar6" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar6_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar6" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar6_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear6" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar6_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar6_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar6_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar6_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar6" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar6_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar6_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar6_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -;(define_function_unit "ar7" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setar7" "1") -; (eq_attr "usear7" "1"))) -; 3 1 ) - -;(define_function_unit "ar7" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ar7" "1") -; (eq_attr "usear7" "1"))) -; 2 1 ) - -;(define_function_unit "ar7" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "usear7" "1") -; (eq_attr "readar7" "1"))) -; 2 1 ) - -(define_attr "setar7" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar7_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar7" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar7_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear7" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar7_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar7_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar7_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar7_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar7" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar7_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar7_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar7_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -;(define_function_unit "ir0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setir0" "1") -; (eq_attr "useir0" "1"))) -; 3 1 ) - -;(define_function_unit "ir0" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ir0" "1") -; (eq_attr "useir0" "1"))) -; 2 1 ) - -(define_attr "setir0" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ir0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ir0" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ir0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "useir0" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ir0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ir0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ir0_mem_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -;(define_function_unit "ir1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setir1" "1") -; (eq_attr "useir1" "1"))) -; 3 1 ) - -;(define_function_unit "ir1" 1 0 -; (and (eq_attr "cpu" "c4x") -; (and (eq_attr "setlda_ir1" "1") -; (eq_attr "useir1" "1"))) -; 2 1 ) - -(define_attr "setir1" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ir1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ir1" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ir1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "useir1" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ir1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ir1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ir1_mem_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -; With the C3x, things are simpler, but slower, i.e. more pipeline conflicts :( -; There are three functional groups: -; (1) AR0-AR7, IR0-IR1, BK -; (2) DP -; (3) SP -; -; When a register in one of these functional groups is loaded, -; the contents of that or any other register in its group -; will not be available to the next instruction for 2 machine cycles. -; Similarly, when a register in one of the functional groups is read -; excepting (IR0-IR1, BK, DP) the contents of that or any other register -; in its group will not be available to the next instruction for -; 1 machine cycle. -; -; Let's ignore functional groups 2 and 3 for now, since they are not -; so important. - -;(define_function_unit "group1" 1 0 -; (and (eq_attr "cpu" "c3x") -; (and (eq_attr "setgroup1" "1") -; (eq_attr "usegroup1" "1"))) -; 3 1) - -;(define_function_unit "group1" 1 0 -; (and (eq_attr "cpu" "c3x") -; (and (eq_attr "usegroup1" "1") -; (eq_attr "readarx" "1"))) -; 2 1) - -(define_attr "setgroup1" "" - (cond [(eq_attr "type" "lda,unary,binary") - (if_then_else (match_operand 0 "group1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usegroup1" "" - (cond [(eq_attr "type" "compare,store,store_store,store_load") - (if_then_else (match_operand 0 "group1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc,load_load,load_store") - (if_then_else (match_operand 1 "group1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "store_store,load_store") - (if_then_else (match_operand 2 "group1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "load_load,store_load") - (if_then_else (match_operand 3 "group1_mem_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readarx" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "arx_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "arx_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "arx_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - - -; -; C4x INSN PATTERNS: -; -; Note that the movMM and addP patterns can be called during reload -; so we need to take special care with theses patterns since -; we cannot blindly clobber CC or generate new pseudo registers. - -; -; TWO OPERAND INTEGER INSTRUCTIONS -; - -; -; LDP/LDPK -; -(define_insn "set_ldp" - [(set (match_operand:QI 0 "dp_reg_operand" "=z") - (high:QI (match_operand:QI 1 "" "")))] - "! TARGET_SMALL" - "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";" - [(set_attr "type" "ldp")]) - - -; Used when moving a constant label reference to an external -; location, this will make sure the original label is still -; used so the optimizer will not optimize it away. -; -(define_insn "set_ldp_use" - [(parallel [(set (match_operand:QI 0 "dp_reg_operand" "=z") - (high:QI (match_operand:QI 1 "" ""))) - (use (match_operand 2 "" ""))])] - "! TARGET_SMALL" - "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";" - [(set_attr "type" "ldp")]) - -(define_insn "set_high_use" - [(parallel [(set (match_operand:QI 0 "std_reg_operand" "=c") - (high:QI (match_operand:QI 1 "" ""))) - (use (match_operand 2 "" ""))])] - "! TARGET_C3X && ! TARGET_SMALL" - "ldhi\\t^%H1,%0" - [(set_attr "type" "unary")]) - -(define_insn "set_ior_lo_use" - [(parallel [(set (match_operand:QI 0 "std_reg_operand" "=c") - (ior:QI (match_dup 0) - (and:QI (match_operand:QI 1 "" "") - (const_int 65535)))) - (use (match_operand 2 "" ""))])] - "! TARGET_C3X && ! TARGET_SMALL" - "or\\t#%H1,%0" - [(set_attr "type" "unary")]) - -; -; LDIU/LDA/STI/STIK -; -; The following moves will not set the condition codes register. -; - -; This must come before the general case -(define_insn "*movqi_stik" - [(set (match_operand:QI 0 "memory_operand" "=m") - (match_operand:QI 1 "stik_const_operand" "K"))] - "! TARGET_C3X" - "stik\\t%1,%0" - [(set_attr "type" "store")]) - -; We must provide an alternative to store to memory in case we have to -; spill a register. -(define_insn "movqi_noclobber" - [(set (match_operand:QI 0 "src_operand" "=d,*c,m,r") - (match_operand:QI 1 "src_hi_operand" "rmI,rmI,r,O"))] - "reg_operand (operands[0], QImode) - || reg_operand (operands[1], QImode)" - "* - if (which_alternative == 2) - return \"sti\\t%1,%0\"; - - if (! TARGET_C3X && which_alternative == 3) - { - operands[1] = GEN_INT ((INTVAL (operands[1]) >> 16) & 0xffff); - return \"ldhi\\t%1,%0\"; - } - - /* The lda instruction cannot use the same register as source - and destination. */ - if (! TARGET_C3X && which_alternative == 1 - && ( IS_ADDR_REG (REGNO (operands[0])) - || IS_INDEX_REG (REGNO (operands[0])) - || IS_SP_REG (REGNO (operands[0]))) - && (REGNO (operands[0]) != REGNO (operands[1]))) - return \"lda\\t%1,%0\"; - return \"ldiu\\t%1,%0\"; - " - [(set_attr "type" "unary,lda,store,unary") - (set_attr "data" "int16,int16,int16,high_16")]) - -; -; LDI -; - -; We shouldn't need these peepholes, but the combiner seems to miss them... -(define_peephole - [(set (match_operand:QI 0 "ext_reg_operand" "=d") - (match_operand:QI 1 "src_operand" "g")) - (set (reg:CC 21) - (compare:CC (match_dup 0) (const_int 0)))] - "" - "@ - ldi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -(define_insn "*movqi_set" - [(set (reg:CC 21) - (compare:CC (match_operand:QI 1 "src_operand" "g") - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (match_dup 1))] - "" - "@ - ldi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -; This pattern probably gets in the way and requires a scratch register -; when a simple compare with zero will suffice. -;(define_insn "*movqi_test" -; [(set (reg:CC 21) -; (compare:CC (match_operand:QI 1 "src_operand" "g") -; (const_int 0))) -; (clobber (match_scratch:QI 0 "=d"))] -; "" -; "@ -; ldi\\t%1,%0" -; [(set_attr "type" "unarycc") -; (set_attr "data" "int16")]) - -; If one of the operands is not a register, then we should -; emit two insns, using a scratch register. This will produce -; better code in loops if the source operand is invariant, since -; the source reload can be optimised out. During reload we cannot -; use change_address or force_reg which will allocate new pseudo regs. - -; 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 "movqi" - [(set (match_operand:QI 0 "src_operand" "") - (match_operand:QI 1 "src_operand" ""))] - "" - " - /* We shouldn't have to do this, since reload is supposed to - be able to do this if we have a memory constraint. */ - if (CONSTANT_P (operands[1]) - && ! const_operand (operands[1], QImode)) - { - operands[1] = force_const_mem (QImode, operands[1]); - if (! memory_address_p (QImode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], QImode, - XEXP (operands[1], 0)); - } - - if (! reload_in_progress - && ! reg_operand (operands[0], QImode) - && ! reg_operand (operands[1], QImode) - && ! (stik_const_operand (operands[1], QImode) - && ! push_operand (operands[0], QImode))) - operands[1] = force_reg (QImode, operands[1]);") - -(define_insn "*movqi_update" - [(set (match_operand:QI 0 "reg_operand" "=r") - (mem:QI (plus:QI (match_operand:QI 1 "addr_reg_operand" "a") - (match_operand:QI 2 "index_reg_operand" "x")))) - (set (match_dup 1) - (plus:QI (match_dup 1) (match_dup 2)))] - "" - "ldiu\\t*%1++(%2),%0" - [(set_attr "type" "unary") - (set_attr "data" "int16")]) - -(define_insn "movqi_parallel" - [(set (match_operand:QI 0 "parallel_operand" "=q,S<>,q,S<>") - (match_operand:QI 1 "parallel_operand" "S<>,q,S<>,q")) - (set (match_operand:QI 2 "parallel_operand" "=q,S<>,S<>,q") - (match_operand:QI 3 "parallel_operand" "S<>,q,q,S<>"))] - "valid_parallel_load_store (operands, QImode)" - "@ - ldi1\\t%1,%0\\n||\\tldi2\\t%3,%2 - sti1\\t%1,%0\\n||\\tsti2\\t%3,%2 - ldi\\t%1,%0\\n||\\tsti\\t%3,%2 - ldi\\t%3,%2\\n||\\tsti\\t%1,%0" - [(set_attr "type" "load_load,store_store,load_store,store_load")]) - -; -; PUSH/POP -; -(define_insn "*pushqi" - [(set (mem:QI (pre_inc:QI (reg:QI 20))) - (match_operand:QI 0 "reg_operand" "r"))] - "" - "push\\t%0" - [(set_attr "type" "push")]) - -(define_insn "*popqi" - [(set (match_operand:QI 0 "reg_operand" "=r") - (mem:QI (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))] - "" - "pop\\t%0" - [(set_attr "type" "pop")]) - -; -; ABSI -; -(define_expand "absqi2" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (abs:QI (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "") - -(define_insn "*absqi2_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (abs:QI (match_operand:QI 1 "src_operand" "g,g"))) - (clobber (reg:CC_NOOV 21))] - "" - "absi\\t%1,%0" - [(set_attr "type" "unarycc,unary") - (set_attr "data" "int16,int16")]) - -(define_insn "*absqi2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "g")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "" - "absi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -(define_insn "*absqi2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "g")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (abs:QI (match_dup 1)))] - "" - "absi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -; -; NEGI -; -(define_expand "negqi2" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (neg:QI (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] -"" -"") - -(define_insn "*negqi2_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (neg:QI (match_operand:QI 1 "src_operand" "g,g"))) - (clobber (reg:CC_NOOV 21))] - "" - "negi\\t%1,%0" - [(set_attr "type" "unarycc,unary") - (set_attr "data" "int16,int16")]) - -(define_insn "*negqi2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "g")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "" - "negi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -(define_insn "*negqi2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "g")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (neg:QI (match_dup 1)))] - "" - "negi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -(define_insn "*negbqi2_clobber" - [(set (match_operand:QI 0 "ext_reg_operand" "=d") - (neg:QI (match_operand:QI 1 "src_operand" "g"))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))] - "" - "negb\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -; -; NOT -; -(define_expand "one_cmplqi2" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (not:QI (match_operand:QI 1 "lsrc_operand" ""))) - (clobber (reg:CC 21))])] - "" - "") - -(define_insn "*one_cmplqi2_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (not:QI (match_operand:QI 1 "lsrc_operand" "g,g"))) - (clobber (reg:CC 21))] - "" - "not\\t%1,%0" - [(set_attr "type" "unarycc,unary") - (set_attr "data" "uint16,uint16")]) - -(define_insn "*one_cmplqi2_test" - [(set (reg:CC 21) - (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "g")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "" - "not\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "uint16")]) - -(define_insn "*one_cmplqi2_set" - [(set (reg:CC 21) - (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "g")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (not:QI (match_dup 1)))] - "" - "not\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "uint16")]) - -(define_insn "*one_cmplqi2_const_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (match_operand:QI 1 "not_const_operand" "N,N")) - (clobber (reg:CC 21))] - "" - "@ - not\\t%N1,%0 - not\\t%N1,%0" - [(set_attr "type" "unarycc,unary") - (set_attr "data" "not_uint16,not_uint16")]) - -; movqi can use this for loading an integer that can't normally -; fit into a 16-bit signed integer. The drawback is that it cannot -; go into R0-R11 since that will clobber the CC and movqi shouldn't -; do that. This can cause additional reloading but in most cases -; this will cause only an additional register move. With the large -; memory model we require an extra instruction to load DP anyway, -; if we're loading the constant from memory. The big advantage of -; allowing constants that satisfy not_const_operand in movqi, is that -; it allows andn to be generated more often. -; However, there is a problem if GCC has decided that it wants -; to use R0-R11, since we won't have a matching pattern... -; In interim, we prevent immed_const allowing `N' constants. -(define_insn "*one_cmplqi2_const_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c") - (match_operand:QI 1 "not_const_operand" "N"))] - "" - "not\\t%N1,%0" - [(set_attr "type" "unary") - (set_attr "data" "not_uint16")]) - -; -; ROL -; -(define_expand "rotlqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (rotate:QI (match_operand:QI 1 "reg_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (INTVAL (operands[2]) > 4) - FAIL; /* Open code as two shifts and an or */ - if (INTVAL (operands[2]) > 1) - { - int i; - rtx tmp; - - /* If we have 4 or fewer shifts, then it is probably faster - to emit separate ROL instructions. A C3x requires - at least 4 instructions (a C4x requires at least 3), to - perform a rotation by shifts. */ - - tmp = operands[1]; - for (i = 0; i < INTVAL (operands[2]) - 1; i++) - { - tmp = gen_reg_rtx (QImode); - emit_insn (gen_rotl_1_clobber (tmp, operands[1])); - operands[1] = tmp; - } - emit_insn (gen_rotl_1_clobber (operands[0], tmp)); - DONE; - }") - -(define_insn "rotl_1_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (rotate:QI (match_operand:QI 1 "reg_operand" "0,0") - (const_int 1))) - (clobber (reg:CC 21))] - "" - "rol\\t%0" - [(set_attr "type" "unarycc,unary")]) -; Default to int16 data attr. - -; -; ROR -; -(define_expand "rotrqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (rotatert:QI (match_operand:QI 1 "reg_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (INTVAL (operands[2]) > 4) - FAIL; /* Open code as two shifts and an or */ - if (INTVAL (operands[2]) > 1) - { - int i; - rtx tmp; - - /* If we have 4 or fewer shifts, then it is probably faster - to emit separate ROL instructions. A C3x requires - at least 4 instructions (a C4x requires at least 3), to - perform a rotation by shifts. */ - - tmp = operands[1]; - for (i = 0; i < INTVAL (operands[2]) - 1; i++) - { - tmp = gen_reg_rtx (QImode); - emit_insn (gen_rotr_1_clobber (tmp, operands[1])); - operands[1] = tmp; - } - emit_insn (gen_rotr_1_clobber (operands[0], tmp)); - DONE; - }") - -(define_insn "rotr_1_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (rotatert:QI (match_operand:QI 1 "reg_operand" "0,0") - (const_int 1))) - (clobber (reg:CC 21))] - "" - "ror\\t%0" - [(set_attr "type" "unarycc,unary")]) -; Default to int16 data attr. - - -; -; THREE OPERAND INTEGER INSTRUCTIONS -; - -; -; ADDI -; -; This is used by reload when it calls gen_add2_insn for address arithmetic -; so we must emit the pattern that doesn't clobber CC. -; -(define_expand "addqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (plus:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (PLUS, operands, QImode); - if (reload_in_progress - || (! IS_PSEUDO_REGNO (operands[0]) - && ! IS_EXT_REG (REGNO (operands[0])))) - { - emit_insn (gen_addqi3_noclobber (operands[0], operands[1], operands[2])); - DONE; - }") - -(define_insn "*addqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0 - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0 - addi\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*addqi3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,?d,d"))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0 - addi\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -; gcc does this in combine.c we just reverse it here -(define_insn "*cmp_neg" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (neg: QI (match_operand:QI 2 "src_operand" "JR,rS<>,g")))) - (clobber (match_scratch:QI 0 "=d,?d,d"))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0 - addi\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d") - (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g"))) - (clobber (reg:CC_NOOV 21))]) - (set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_dup 0) (const_int 0)))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0 - addi\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*addqi3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d") - (plus:QI (match_dup 1) (match_dup 2)))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0 - addi\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -; This pattern is required primarily for manipulating the stack pointer -; where GCC doesn't expect CC to be clobbered or for calculating -; addresses during reload. -(define_insn "addqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,?c,c") - (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0 - addi\\t%2,%0" - [(set_attr "type" "binary,binary,binary")]) -; Default to int16 data attr. - - -; This pattern is required during reload when eliminate_regs_in_insn -; effectively converts a move insn into an add insn when the src -; operand is the frame pointer plus a constant. Without this -; pattern, gen_addqi3 can be called with a register for operand0 -; that can clobber CC. -; For example, we may have (set (mem (reg ar0)) (reg 99)) -; with (set (reg 99) (plus (reg ar3) (const_int 8))) -; Now since ar3, the frame pointer, is unchanging within the function, -; (plus (reg ar3) (const_int 8)) is considered a constant. -; eliminate_regs_in_insn substitutes this constant to give -; (set (mem (reg ar0)) (plus (reg ar3) (const_int 8))). -; This is an invalid C4x insn but if we don't provide a pattern -; for it, it will be considered to be a move insn for reloading. -; The nasty bit is that a GENERAL_REGS class register, say r0, -; may be allocated to reload the PLUS and thus gen_reload will -; emit an add insn that may clobber CC. -(define_insn "*addqi3_noclobber_reload" - [(set (match_operand:QI 0 "general_operand" "=c,?c,c") - (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")))] - "reload_in_progress" - "@ - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0 - addi\\t%2,%0" - [(set_attr "type" "binary,binary,binary")]) -; Default to int16 data attr. - - -(define_insn "*addqi3_carry_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))] - "valid_operands (PLUS, operands, QImode)" - "@ - addc3\\t%2,%1,%0 - addc3\\t%2,%1,%0 - addc\\t%2,%0 - addc3\\t%2,%1,%0 - addc3\\t%2,%1,%0 - addc\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - - -; -; SUBI/SUBRI -; -(define_expand "subqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (minus:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MINUS, operands, QImode);") - -(define_insn "*subqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c") - (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g,rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0,JR,rS<>,g,0"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, QImode)" - "@ - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0 - subi\\t%2,%0 - subri\\t%1,%0 - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0 - subi\\t%2,%0 - subri\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc,binary,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*subqi3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,?d,d,d"))] - "valid_operands (MINUS, operands, QImode)" - "@ - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0 - subi\\t%2,%0 - subri\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d") - (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0"))) - (clobber (reg:CC_NOOV 21))]) - (set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_dup 0) (const_int 0)))] - "valid_operands (MINUS, operands, QImode)" - "@ - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0 - subi\\t%2,%0 - subri\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -(define_insn "*subqi3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d") - (minus:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (MINUS, operands, QImode)" - "@ - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0 - subi\\t%2,%0 - subri\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -(define_insn "*subqi3_carry_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c") - (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g,rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0,JR,rS<>,g,0"))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, QImode)" - "@ - subb3\\t%2,%1,%0 - subb3\\t%2,%1,%0 - subb\\t%2,%0 - subrb\\t%1,%0 - subb3\\t%2,%1,%0 - subb3\\t%2,%1,%0 - subb\\t%2,%0 - subrb\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc,binary,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*subqi3_carry_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,0")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d") - (minus:QI (match_dup 1) - (match_dup 2))) - (use (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, QImode)" - "@ - subb3\\t%2,%1,%0 - subb3\\t%2,%1,%0 - subb\\t%2,%0 - subrb\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -; -; MPYI -; -(define_expand "mulqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (mult:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "if (TARGET_MPYI || (GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2])) >= 0)) - legitimize_operands (MULT, operands, QImode); - else - { - if (GET_CODE (operands[2]) == CONST_INT) - { - /* Let GCC try to synthesise the multiplication using shifts - and adds. In most cases this will be more profitable than - using the C3x MPYI. */ - FAIL; - } - if (operands[1] == operands[2]) - { - /* Do the squaring operation in-line. */ - emit_insn (gen_sqrqi2_inline (operands[0], operands[1])); - DONE; - } - if (TARGET_INLINE) - { - emit_insn (gen_mulqi3_inline (operands[0], operands[1], - operands[2])); - DONE; - } - c4x_emit_libcall3 (MULQI3_LIBCALL, MULT, QImode, operands); - DONE; - } - ") - -(define_insn "*mulqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MULT, operands, QImode)" - "* - if (which_alternative == 2 || which_alternative == 5) - { - if (TARGET_C3X - && GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2])) >= 0) - return \"ash\\t%L2,%0\"; - else - return \"mpyi\\t%2,%0\"; - } - else - return \"mpyi3\\t%2,%1,%0\";" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*mulqi3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,?d,d"))] - "valid_operands (MULT, operands, QImode)" - "* - if (which_alternative == 2) - { - if (TARGET_C3X - && GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2])) >= 0) - return \"ash\\t%L2,%0\"; - else - return \"mpyi\\t%2,%0\"; - } - else - return \"mpyi3\\t%2,%1,%0\";" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -(define_insn "*mulqi3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d") - (mult:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (MULT, operands, QImode)" - "* - if (which_alternative == 2) - { - if (TARGET_C3X - && GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2])) >= 0) - return \"ash\\t%L2,%0\"; - else - return \"mpyi\\t%2,%0\"; - } - else - return \"mpyi3\\t%2,%1,%0\";" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -; The C3x multiply instruction assumes 24-bit signed integer operands -; and the 48-bit result is truncated to 32-bits. -(define_insn "*mulqi3_24_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (mult:QI - (sign_extend:QI - (and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") - (const_int 16777215))) - (sign_extend:QI - (and:QI (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g") - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))] - "TARGET_C3X && valid_operands (MULT, operands, QImode)" - "@ - mpyi3\\t%2,%1,%0 - mpyi3\\t%2,%1,%0 - mpyi\\t%2,%0 - mpyi3\\t%2,%1,%0 - mpyi3\\t%2,%1,%0 - mpyi\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - - -; Fast square function for C3x where TARGET_MPYI not asserted -(define_expand "sqrqi2_inline" - [(set (match_dup 7) (match_operand:QI 1 "src_operand" "")) - (parallel [(set (match_dup 3) - (lshiftrt:QI (match_dup 7) (const_int 16))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 2) - (and:QI (match_dup 7) (const_int 65535))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 4) - (mult:QI (sign_extend:QI (and:QI (match_dup 2) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 2) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 5) - (mult:QI (sign_extend:QI (and:QI (match_dup 2) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 3) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 6) - (ashift:QI (match_dup 5) (const_int 17))) - (clobber (reg:CC 21))]) - (parallel [(set (match_operand:QI 0 "reg_operand" "") - (plus:QI (match_dup 4) (match_dup 6))) - (clobber (reg:CC_NOOV 21))])] - "" - " - operands[2] = gen_reg_rtx (QImode); /* a = val & 0xffff */ - operands[3] = gen_reg_rtx (QImode); /* b = val >> 16 */ - operands[4] = gen_reg_rtx (QImode); /* a * a */ - operands[5] = gen_reg_rtx (QImode); /* a * b */ - operands[6] = gen_reg_rtx (QImode); /* (a * b) << 17 */ - operands[7] = gen_reg_rtx (QImode); /* val */ - ") - -; Inlined integer multiply for C3x -(define_expand "mulqi3_inline" - [(set (match_dup 12) (const_int -16)) - (set (match_dup 13) (match_operand:QI 1 "src_operand" "")) - (set (match_dup 14) (match_operand:QI 2 "src_operand" "")) - (parallel [(set (match_dup 4) - (lshiftrt:QI (match_dup 13) (neg:QI (match_dup 12)))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 6) - (lshiftrt:QI (match_dup 14) (neg:QI (match_dup 12)))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 3) - (and:QI (match_dup 13) - (const_int 65535))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 5) - (and:QI (match_dup 14) - (const_int 65535))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 7) - (mult:QI (sign_extend:QI (and:QI (match_dup 4) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 5) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 8) - (mult:QI (sign_extend:QI (and:QI (match_dup 3) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 5) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 9) - (mult:QI (sign_extend:QI (and:QI (match_dup 3) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 6) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 10) - (plus:QI (match_dup 7) (match_dup 9))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 11) - (ashift:QI (match_dup 10) (const_int 16))) - (clobber (reg:CC 21))]) - (parallel [(set (match_operand:QI 0 "reg_operand" "") - (plus:QI (match_dup 8) (match_dup 11))) - (clobber (reg:CC_NOOV 21))])] - "TARGET_C3X" - " - operands[3] = gen_reg_rtx (QImode); /* a = arg1 & 0xffff */ - operands[4] = gen_reg_rtx (QImode); /* b = arg1 >> 16 */ - operands[5] = gen_reg_rtx (QImode); /* a = arg2 & 0xffff */ - operands[6] = gen_reg_rtx (QImode); /* b = arg2 >> 16 */ - operands[7] = gen_reg_rtx (QImode); /* b * c */ - operands[8] = gen_reg_rtx (QImode); /* a * c */ - operands[9] = gen_reg_rtx (QImode); /* a * d */ - operands[10] = gen_reg_rtx (QImode); /* b * c + a * d */ - operands[11] = gen_reg_rtx (QImode); /* (b *c + a * d) << 16 */ - operands[12] = gen_reg_rtx (QImode); /* -16 */ - operands[13] = gen_reg_rtx (QImode); /* arg1 */ - operands[14] = gen_reg_rtx (QImode); /* arg2 */ - ") - -; -; MPYSHI (C4x only) -; -(define_expand "smulqi3_highpart" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (truncate:QI - (lshiftrt:HI - (mult:HI - (sign_extend:HI (match_operand:QI 1 "src_operand" "")) - (sign_extend:HI (match_operand:QI 2 "src_operand" ""))) - (const_int 32)))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MULT, operands, QImode); - if (TARGET_C3X) - { - c4x_emit_libcall_mulhi (SMULHI3_LIBCALL, SIGN_EXTEND, QImode, operands); - DONE; - } - ") - -(define_insn "*smulqi3_highpart_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (truncate:QI - (lshiftrt:HI - (mult:HI - (sign_extend:HI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")) - (sign_extend:HI (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) - (const_int 32)))) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X && valid_operands (MULT, operands, QImode)" - "@ - mpyshi3\\t%2,%1,%0 - mpyshi3\\t%2,%1,%0 - mpyshi\\t%2,%0 - mpyshi3\\t%2,%1,%0 - mpyshi3\\t%2,%1,%0 - mpyshi\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "int16,int16,int16,int16,int16,int16")]) - -; -; MPYUHI (C4x only) -; -(define_expand "umulqi3_highpart" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (truncate:QI - (lshiftrt:HI - (mult:HI - (zero_extend:HI (match_operand:QI 1 "src_operand" "")) - (zero_extend:HI (match_operand:QI 2 "lsrc_operand" ""))) - (const_int 32)))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MULT, operands, QImode); - if (TARGET_C3X) - { - c4x_emit_libcall_mulhi (UMULHI3_LIBCALL, ZERO_EXTEND, QImode, operands); - DONE; - } - ") - -(define_insn "*umulqi3_highpart_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (truncate:QI - (lshiftrt:HI - (mult:HI - (zero_extend:HI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")) - (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,g,JR,rS<>,g"))) - (const_int 32)))) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X && valid_operands (MULT, operands, QImode)" - "@ - mpyuhi3\\t%2,%1,%0 - mpyuhi3\\t%2,%1,%0 - mpyuhi\\t%2,%0 - mpyuhi3\\t%2,%1,%0 - mpyuhi3\\t%2,%1,%0 - mpyuhi\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "uint16,uint16,uint16,uint16,uint16,uint16")]) - -; -; AND -; -(define_expand "andqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (and:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "tsrc_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (AND, operands, QImode);") - -(define_insn "*andqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c") - (and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,0,rR,rS<>,0,0") - (match_operand:QI 2 "tsrc_operand" "JR,rS<>,N,rLm,JR,rS<>,N,rLm"))) - (clobber (reg:CC 21))] - "valid_operands (AND, operands, QImode)" - "@ - and3\\t%2,%1,%0 - and3\\t%2,%1,%0 - andn\\t%N2,%0 - and\\t%2,%0 - and3\\t%2,%1,%0 - and3\\t%2,%1,%0 - andn\\t%N2,%0 - and\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc,binary,binary,binary,binary") - (set_attr "data" "int16,uint16,not_uint16,uint16,int16,uint16,not_uint16,uint16")]) - -(define_insn "*andqi3_test" - [(set (reg:CC 21) - (compare:CC (and:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,r") - (match_operand:QI 2 "tsrc_operand" "JR,rS<>,N,rLm")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=X,X,d,X"))] - "valid_operands (AND, operands, QImode)" - "@ - tstb3\\t%2,%1 - tstb3\\t%2,%1 - andn\\t%N2,%0 - tstb\\t%2,%1" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,not_uint16,uint16")]) - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d") - (and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,0") - (match_operand:QI 2 "tsrc_operand" "JR,rS<>,N,rLm"))) - (clobber (reg:CC 21))]) - (set (reg:CC 21) - (compare:CC (match_dup 0) (const_int 0)))] - "valid_operands (AND, operands, QImode)" - "@ - and3\\t%2,%1,%0 - and3\\t%2,%1,%0 - andn\\t%N2,%0 - and\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,not_uint16,uint16")]) - -(define_insn "*andqi3_set" - [(set (reg:CC 21) - (compare:CC (and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,0") - (match_operand:QI 2 "tsrc_operand" "JR,rS<>,N,rLm")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d") - (and:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (AND, operands, QImode)" - "@ - and3\\t%2,%1,%0 - and3\\t%2,%1,%0 - andn\\t%N2,%0 - and\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,not_uint16,uint16")]) - -; -; ANDN -; -; NB, this insn doesn't have commutative operands, but valid_operands -; assumes that the code AND does. We might have to kludge this if -; we make valid_operands stricter. -(define_insn "*andnqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm,JR,rS<>,rLm")) - (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0"))) - (clobber (reg:CC 21))] - "valid_operands (AND, operands, QImode)" - "@ - andn3\\t%2,%1,%0 - andn3\\t%2,%1,%0 - andn\\t%2,%0 - andn3\\t%2,%1,%0 - andn3\\t%2,%1,%0 - andn\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "int16,uint16,uint16,int16,uint16,uint16")]) - -(define_insn "*andnqi3_test" - [(set (reg:CC 21) - (compare:CC (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm")) - (match_operand:QI 1 "src_operand" "rR,rS<>,0")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,?d,d"))] - "valid_operands (AND, operands, QImode)" - "@ - andn3\\t%2,%1,%0 - andn3\\t%2,%1,%0 - andn\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,uint16")]) - -(define_insn "*andnqi3_set" - [(set (reg:CC 21) - (compare:CC (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm")) - (match_operand:QI 1 "src_operand" "rR,rS<>,0")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d") - (and:QI (not:QI (match_dup 2)) - (match_dup 1)))] - "valid_operands (AND, operands, QImode)" - "@ - andn3\\t%2,%1,%0 - andn3\\t%2,%1,%0 - andn\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,uint16")]) - -; -; OR -; -(define_expand "iorqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (ior:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "lsrc_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (IOR, operands, QImode);") - -(define_insn "*iorqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm,JR,rS<>,rLm"))) - (clobber (reg:CC 21))] - "valid_operands (IOR, operands, QImode)" - "@ - or3\\t%2,%1,%0 - or3\\t%2,%1,%0 - or\\t%2,%0 - or3\\t%2,%1,%0 - or3\\t%2,%1,%0 - or\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "int16,uint16,uint16,int16,uint16,uint16")]) - -(define_insn "*iorqi3_test" - [(set (reg:CC 21) - (compare:CC (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,?d,d"))] - "valid_operands (IOR, operands, QImode)" - "@ - or3\\t%2,%1,%0 - or3\\t%2,%1,%0 - or\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,uint16")]) - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d") - (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm"))) - (clobber (reg:CC 21))]) - (set (reg:CC 21) - (compare:CC (match_dup 0) (const_int 0)))] - "valid_operands (IOR, operands, QImode)" - "@ - or3\\t%2,%1,%0 - or3\\t%2,%1,%0 - or\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,uint16")]) - -(define_insn "*iorqi3_set" - [(set (reg:CC 21) - (compare:CC (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d") - (ior:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (IOR, operands, QImode)" - "@ - or3\\t%2,%1,%0 - or3\\t%2,%1,%0 - or\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,uint16")]) - -; This pattern is used for loading symbol references in several parts. -(define_insn "iorqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,?c,c") - (ior:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm")))] - "valid_operands (IOR, operands, QImode)" - "@ - or3\\t%2,%1,%0 - or3\\t%2,%1,%0 - or\\t%2,%0" - [(set_attr "type" "binary,binary,binary") - (set_attr "data" "int16,uint16,uint16")]) - -; -; XOR -; -(define_expand "xorqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (xor:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "lsrc_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (XOR, operands, QImode);") - -(define_insn "*xorqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (xor:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm,JR,rS<>,rLm"))) - (clobber (reg:CC 21))] - "valid_operands (XOR, operands, QImode)" - "@ - xor3\\t%2,%1,%0 - xor3\\t%2,%1,%0 - xor\\t%2,%0 - xor3\\t%2,%1,%0 - xor3\\t%2,%1,%0 - xor\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "int16,uint16,uint16,int16,uint16,uint16")]) - -(define_insn "*xorqi3_test" - [(set (reg:CC 21) - (compare:CC (xor:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,?d,d"))] - "valid_operands (XOR, operands, QImode)" - "@ - xor3\\t%2,%1,%0 - xor3\\t%2,%1,%0 - xor\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,uint16")]) - -(define_insn "*xorqi3_set" - [(set (reg:CC 21) - (compare:CC (xor:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0") - (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d") - (xor:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (XOR, operands, QImode)" - "@ - xor3\\t%2,%1,%0 - xor3\\t%2,%1,%0 - xor\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "int16,uint16,uint16")]) - -; -; LSH/ASH (left) -; -; The C3x and C4x have two shift instructions ASH and LSH -; If the shift count is positive, a left shift is performed -; otherwise a right shift is performed. The number of bits -; shifted is determined by the seven LSBs of the shift count. -; If the absolute value of the count is 32 or greater, the result -; using the LSH instruction is zero; with the ASH insn the result -; is zero or negative 1. Note that the ISO C standard allows -; the result to be machine dependent whenever the shift count -; exceeds the size of the object. -(define_expand "ashlqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (ashift:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (ASHIFT, operands, QImode);") - -(define_insn "*ashlqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g"))) - (clobber (reg:CC 21))] - "valid_operands (ASHIFT, operands, QImode)" - "@ - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0 - ash\\t%2,%0 - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0 - ash\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*ashlqi3_set" - [(set (reg:CC 21) - (compare:CC - (ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0") - (match_operand:QI 2 "src_operand" "JR,rS<>,g")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=d,?d,d") - (ashift:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (ASHIFT, operands, QImode)" - "@ - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0 - ash\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -; This is only used by lshrhi3_reg where we need a LSH insn that will -; shift both ways. -(define_insn "*lshlqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0") - (unspec [(match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")] 3))) - (clobber (reg:CC 21))] - "valid_operands (ASHIFT, operands, QImode)" - "@ - lsh3\\t%2,%1,%0 - lsh3\\t%2,%1,%0 - lsh\\t%2,%0 - lsh3\\t%2,%1,%0 - lsh3\\t%2,%1,%0 - lsh\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -; -; LSH (right) -; -; Logical right shift on the C[34]x works by negating the shift count, -; then emitting a right shift with the shift count negated. This means -; that all actual shift counts in the RTL will be positive. -; -(define_expand "lshrqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (LSHIFTRT, operands, QImode);") - -; When the shift count is greater than the size of the word -; the result can be implementation specific -(define_insn "*lshrqi3_const_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c,?d,?c") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "0,0,r,r") - (match_operand:QI 2 "const_int_operand" "n,n,J,J"))) - (clobber (reg:CC 21))] - "valid_operands (LSHIFTRT, operands, QImode)" - "@ - lsh\\t%n2,%0 - lsh\\t%n2,%0 - lsh3\\t%n2,%1,%0 - lsh3\\t%n2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -; When the shift count is greater than the size of the word -; the result can be implementation specific -(define_insn "*lshrqi3_const_set" - [(set (reg:CC 21) - (compare:CC - (lshiftrt:QI (match_operand:QI 1 "src_operand" "0,r") - (match_operand:QI 2 "const_int_operand" "n,J")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=?d,d") - (lshiftrt:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (LSHIFTRT, operands, QImode)" - "@ - lsh\\t%n2,%0 - lsh3\\t%n2,%1,%0" - [(set_attr "type" "binarycc,binarycc")]) - -(define_insn "*lshrqi3_nonconst_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0") - (neg:QI (match_operand:QI 2 "src_operand" "R,rS<>,rm,R,rS<>,rm")))) - (clobber (reg:CC 21))] - "valid_operands (LSHIFTRT, operands, QImode)" - "@ - lsh3\\t%2,%1,%0 - lsh3\\t%2,%1,%0 - lsh\\t%2,%0 - lsh3\\t%2,%1,%0 - lsh3\\t%2,%1,%0 - lsh\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -; -; ASH (right) -; -; Arithmetic right shift on the C[34]x works by negating the shift count, -; then emitting a right shift with the shift count negated. This means -; that all actual shift counts in the RTL will be positive. - -(define_expand "ashrqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (ASHIFTRT, operands, QImode);") - -; When the shift count is greater than the size of the word -; the result can be implementation specific -(define_insn "*ashrqi3_const_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c,?d,?c") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "0,0,r,r") - (match_operand:QI 2 "const_int_operand" "n,n,J,J"))) - (clobber (reg:CC 21))] - "valid_operands (ASHIFTRT, operands, QImode)" - "@ - ash\\t%n2,%0 - ash\\t%n2,%0 - ash3\\t%n2,%1,%0 - ash3\\t%n2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -; When the shift count is greater than the size of the word -; the result can be implementation specific -(define_insn "*ashrqi3_const_set" - [(set (reg:CC 21) - (compare:CC - (ashiftrt:QI (match_operand:QI 1 "src_operand" "0,r") - (match_operand:QI 2 "const_int_operand" "n,J")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=?d,d") - (ashiftrt:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (ASHIFTRT, operands, QImode)" - "@ - ash\\t%n2,%0 - ash3\\t%n2,%1,%0" - [(set_attr "type" "binarycc,binarycc")]) - -(define_insn "*ashrqi3_nonconst_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0") - (neg:QI (match_operand:QI 2 "src_operand" "R,rS<>,rm,R,rS<>,rm")))) - (clobber (reg:CC 21))] - "valid_operands (ASHIFTRT, operands, QImode)" - "@ - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0 - ash\\t%2,%0 - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0 - ash\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -; -; CMPI -; -; Unfortunately the C40 doesn't allow cmpi3 7, *ar0++ so the next best -; thing would be to get the small constant loaded into a register (say r0) -; so that it could be hoisted out of the loop so that we only -; would need to do cmpi3 *ar0++, r0. Now the loop optimisation pass -; comes before the flow pass (which finds autoincrements) so we're stuck. -; Ideally, GCC requires another loop optimisation pass (preferably after -; reload) so that it can hoist invariants out of loops. -; The current solution modifies legitimize_operands () so that small -; constants are forced into a pseudo register. -; -(define_expand "cmpqi" - [(set (reg:CC 21) - (compare:CC (match_operand:QI 0 "src_operand" "") - (match_operand:QI 1 "src_operand" "")))] - "" - "legitimize_operands (COMPARE, operands, QImode); - c4x_compare_op0 = operands[0]; - c4x_compare_op1 = operands[1]; - DONE;") - -(define_insn "*cmpqi_test" - [(set (reg:CC 21) - (compare:CC (match_operand:QI 0 "src_operand" "rR,?rS<>,r") - (match_operand:QI 1 "src_operand" "JR,rS<>,g")))] - "valid_operands (COMPARE, operands, QImode)" - "@ - cmpi3\\t%1,%0 - cmpi3\\t%1,%0 - cmpi\\t%1,%0" - [(set_attr "type" "compare,compare,compare")]) - -(define_insn "*cmpqi_test_noov" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:QI 0 "src_operand" "rR,?rS<>,r") - (match_operand:QI 1 "src_operand" "JR,rS<>,g")))] - "valid_operands (COMPARE, operands, QImode)" - "@ - cmpi3\\t%1,%0 - cmpi3\\t%1,%0 - cmpi\\t%1,%0" - [(set_attr "type" "compare,compare,compare")]) - -(define_expand "udivqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (udiv:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (UDIVQI3_LIBCALL, UDIV, QImode, operands); - DONE;") - -(define_expand "divqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (div:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (DIVQI3_LIBCALL, DIV, QImode, operands); - DONE;") - -(define_expand "umodqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (umod:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (UMODQI3_LIBCALL, UMOD, QImode, operands); - DONE;") - -(define_expand "modqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (mod:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (MODQI3_LIBCALL, MOD, QImode, operands); - DONE;") - -(define_expand "ffsqi2" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (ffs:QI (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FFS_LIBCALL, FFS, QImode, QImode, 2, operands); - DONE;") - -; -; BIT-FIELD INSTRUCTIONS -; - -; -; LBx/LHw (C4x only) -; -(define_expand "extv" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (sign_extract:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "const_int_operand" "") - (match_operand:QI 3 "const_int_operand" ""))) - (clobber (reg:CC 21))])] - "! TARGET_C3X" - "if ((INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16) - || (INTVAL (operands[3]) % INTVAL (operands[2]) != 0)) - FAIL; - ") - -(define_insn "*extv_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (sign_extract:QI (match_operand:QI 1 "src_operand" "g,g") - (match_operand:QI 2 "const_int_operand" "n,n") - (match_operand:QI 3 "const_int_operand" "n,n"))) - (clobber (reg:CC 21))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lb%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lh%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc,binary") - (set_attr "data" "int16,int16")]) - -(define_insn "*extv_clobber_test" - [(set (reg:CC 21) - (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "g") - (match_operand:QI 2 "const_int_operand" "n") - (match_operand:QI 3 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lb%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lh%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "int16")]) - -(define_insn "*extv_clobber_set" - [(set (reg:CC 21) - (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "g") - (match_operand:QI 2 "const_int_operand" "n") - (match_operand:QI 3 "const_int_operand" "n")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=d") - (sign_extract:QI (match_dup 1) - (match_dup 2) - (match_dup 3)))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lb%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lh%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "int16")]) - -; -; LBUx/LHUw (C4x only) -; -(define_expand "extzv" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (zero_extract:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "const_int_operand" "") - (match_operand:QI 3 "const_int_operand" ""))) - (clobber (reg:CC 21))])] - "! TARGET_C3X" - "if ((INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16) - || (INTVAL (operands[3]) % INTVAL (operands[2]) != 0)) - FAIL; - ") - -(define_insn "*extzv_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (zero_extract:QI (match_operand:QI 1 "src_operand" "g,g") - (match_operand:QI 2 "const_int_operand" "n,n") - (match_operand:QI 3 "const_int_operand" "n,n"))) - (clobber (reg:CC 21))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lbu%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lhu%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc,binary") - (set_attr "data" "uint16,uint16")]) - -(define_insn "*extzv_test" - [(set (reg:CC 21) - (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "g") - (match_operand:QI 2 "const_int_operand" "n") - (match_operand:QI 3 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lbu%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lhu%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "uint16")]) - -(define_insn "*extzv_set" - [(set (reg:CC 21) - (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "g") - (match_operand:QI 2 "const_int_operand" "n") - (match_operand:QI 3 "const_int_operand" "n")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=d") - (zero_extract:QI (match_dup 1) - (match_dup 2) - (match_dup 3)))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lbu%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lhu%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "uint16")]) - -; -; MBx/MHw (C4x only) -; -(define_expand "insv" - [(parallel [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" "") - (match_operand:QI 2 "const_int_operand" "")) - (match_operand:QI 3 "src_operand" "")) - (clobber (reg:CC 21))])] - "! TARGET_C3X" - "if (! (((INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) - && (INTVAL (operands[2]) % INTVAL (operands[1]) == 0)) - || (INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8))) - FAIL; - ") - -(define_insn "*insv_clobber" - [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d,c") - (match_operand:QI 1 "const_int_operand" "n,n") - (match_operand:QI 2 "const_int_operand" "n,n")) - (match_operand:QI 3 "src_operand" "g,g")) - (clobber (reg:CC 21))] - "! TARGET_C3X - && (((INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) - && (INTVAL (operands[2]) % INTVAL (operands[1]) == 0)) - || (INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8))" - "* - if (INTVAL (operands[1]) == 8) - { - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); - return \"mb%2\\t%3,%0\"; - } - else if (INTVAL (operands[1]) == 16) - { - operands[2] = GEN_INT (INTVAL (operands[2]) / 16); - return \"mh%2\\t%3,%0\"; - } - return \"lwl1\\t%3,%0\"; - " - [(set_attr "type" "binarycc,binary") - (set_attr "data" "uint16,uint16")]) - -(define_peephole - [(parallel [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d") - (match_operand:QI 1 "const_int_operand" "n") - (match_operand:QI 2 "const_int_operand" "n")) - (match_operand:QI 3 "src_operand" "g")) - (clobber (reg:CC 21))]) - (set (reg:CC 21) - (compare:CC (match_dup 0) (const_int 0)))] - "! TARGET_C3X - && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) - && (INTVAL (operands[2]) % INTVAL (operands[1]) == 0)" - "* - if (INTVAL (operands[1]) == 8) - { - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); - return \"mb%2\\t%3,%0\"; - } - operands[2] = GEN_INT (INTVAL (operands[2]) / 16); - return \"mh%2\\t%3,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "uint16")]) - -; -; TWO OPERAND FLOAT INSTRUCTIONS -; - -; -; LDF/STF -; -; If one of the operands is not a register, then we should -; emit two insns, using a scratch register. This will produce -; better code in loops if the source operand is invariant, since -; the source reload can be optimised out. During reload we cannot -; use change_address or force_reg. -(define_expand "movqf" - [(set (match_operand:QF 0 "src_operand" "") - (match_operand:QF 1 "src_operand" ""))] - "" - " - if (CONSTANT_P (operands[1]) && ! const_operand (operands[1], QFmode)) - { - operands[1] = force_const_mem (QFmode, operands[1]); - if (! memory_address_p (QFmode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], QFmode, - XEXP (operands[1], 0)); - } - - if (! reload_in_progress - && ! reg_operand (operands[0], QFmode) - && ! reg_operand (operands[1], QFmode)) - operands[1] = force_reg (QFmode, operands[1]); - ") - -; We must provide an alternative to store to memory in case we have to -; spill a register. -(define_insn "*movqf_noclobber" - [(set (match_operand:QF 0 "src_operand" "=f,m") - (match_operand:QF 1 "src_operand" "fmH,f"))] - "reg_operand (operands[0], QFmode) - || reg_operand (operands[1], QFmode)" - "@ - ldfu\\t%1,%0 - stf\\t%1,%0" - [(set_attr "type" "unary,store")]) - -;(define_insn "*movqf_clobber" -; [(set (match_operand:QF 0 "reg_operand" "=f") -; (match_operand:QF 1 "src_operand" "fmH")) -; (clobber (reg:CC 21))] -; "0" -; "ldf\\t%1,%0" -; [(set_attr "type" "unarycc")]) - -(define_insn "*movqf_test" - [(set (reg:CC 21) - (compare:CC (match_operand:QF 1 "src_operand" "fmH") - (const_int 0))) - (clobber (match_scratch:QF 0 "=f"))] - "" - "ldf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*movqf_set" - [(set (reg:CC 21) - (compare:CC (match_operand:QF 1 "src_operand" "fmH") - (match_operand:QF 2 "fp_zero_operand" "G"))) - (set (match_operand:QF 0 "reg_operand" "=f") - (match_dup 1))] - "" - "ldf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*movqf_update" - [(set (match_operand:QF 0 "reg_operand" "=r") - (mem:QF (plus:QI (match_operand:QI 1 "addr_reg_operand" "a") - (match_operand:QI 2 "index_reg_operand" "x")))) - (set (match_dup 1) - (plus:QI (match_dup 1) (match_dup 2)))] - "" - "ldfu\\t*%1++(%2),%0" - [(set_attr "type" "unary")]) - -(define_insn "*movqf_parallel" - [(set (match_operand:QF 0 "parallel_operand" "=q,S<>,q,S<>") - (match_operand:QF 1 "parallel_operand" "S<>,q,S<>,q")) - (set (match_operand:QF 2 "parallel_operand" "=q,S<>,S<>,q") - (match_operand:QF 3 "parallel_operand" "S<>,q,q,S<>"))] - "valid_parallel_load_store (operands, QFmode)" - "@ - ldf1\\t%1,%0\\n||\\tldf2\\t%3,%2 - stf1\\t%1,%0\\n||\\tstf2\\t%3,%2 - ldf\\t%1,%0\\n||\\tstf\\t%3,%2 - ldf\\t%3,%2\\n||\\tstf\\t%1,%0" - [(set_attr "type" "load_load,store_store,load_store,store_load")]) - - -; -; PUSH/POP -; -(define_insn "*pushqf" - [(set (mem:QF (pre_inc:QI (reg:QI 20))) - (match_operand:QF 0 "reg_operand" "f"))] - "" - "pushf\\t%0" - [(set_attr "type" "push")]) - -(define_insn "*popqf" - [(set (match_operand:QF 0 "reg_operand" "=f") - (mem:QF (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))] - "" - "popf\\t%0" - [(set_attr "type" "pop")]) - - -; -; ABSF -; -(define_expand "absqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (abs:QF (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] -"" -"") - -(define_insn "*absqf2_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (abs:QF (match_operand:QF 1 "src_operand" "fmH"))) - (clobber (reg:CC_NOOV 21))] - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*absqf2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fmH")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (clobber (match_scratch:QF 0 "=f"))] - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*absqf2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fmH")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (set (match_operand:QF 0 "reg_operand" "=f") - (abs:QF (match_dup 1)))] - - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; NEGF -; -(define_expand "negqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (neg:QF (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] -"" -"") - -(define_insn "*negqf2_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (neg:QF (match_operand:QF 1 "src_operand" "fmH"))) - (clobber (reg:CC_NOOV 21))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*negqf2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fmH")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (clobber (match_scratch:QF 0 "=f"))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*negqf2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fmH")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (set (match_operand:QF 0 "reg_operand" "=f") - (neg:QF (match_dup 1)))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; FLOAT -; -(define_insn "floatqiqf2" - [(set (match_operand:QF 0 "reg_operand" "=f") - (float:QF (match_operand:QI 1 "src_operand" "g"))) - (clobber (reg:CC 21))] - "" - "float\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*floatqiqf2_set" - [(set (reg:CC 21) - (compare:CC (float:QF (match_operand:QI 1 "src_operand" "g")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (set (match_operand:QF 0 "reg_operand" "=f") - (float:QF (match_dup 1)))] - - "" - "float\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; Unsigned conversions are a little tricky because we need to -; add the value for the high bit if necessary. -; -(define_expand "floatunsqiqf2" - [(set (match_dup 2) (match_dup 3)) - (parallel [(set (reg:CC 21) - (compare:CC (float:QF (match_operand:QI 1 "src_operand" "")) - (match_dup 3))) - (set (match_dup 4) - (float:QF (match_dup 1)))]) - (set (match_dup 2) - (if_then_else:QF (lt (reg:CC 21) (const_int 0)) - (mem:QF (symbol_ref:QF "*___unsfltconst")) - (match_dup 2))) - (parallel [(set (match_operand:QF 0 "reg_operand" "") - (plus:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))])] - "" - "operands[2] = gen_reg_rtx (QFmode); - operands[3] = CONST0_RTX (QFmode); - operands[4] = gen_reg_rtx (QFmode); - ") - -(define_insn "floatqihf2" - [(set (match_operand:HF 0 "reg_operand" "=h") - (float:HF (match_operand:QI 1 "src_operand" "g"))) - (clobber (reg:CC 21))] - "" - "float\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; FIX -; -(define_insn "fixqfqi_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (fix:QI (match_operand:QF 1 "src_operand" "fmH,fmH"))) - (clobber (reg:CC 21))] - "" - "fix\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*fixqfqi_set" - [(set (reg:CC 21) - (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fmH")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=d") - (fix:QI (match_dup 1)))] - "" - "fix\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; The C[34]x fix instruction implements a floor, not a straight trunc, -; so we have to invert the number, fix it, and reinvert it if negative -; -(define_expand "fix_truncqfqi2" - [(parallel [(set (match_dup 2) - (fix:QI (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 3) (neg:QF (match_dup 1))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (fix:QI (match_dup 3))) - (clobber (reg:CC 21))]) - (parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_dup 4)) (const_int 0))) - (set (match_dup 5) (neg:QI (match_dup 4)))]) - (set (match_dup 2) - (if_then_else:QI (le (reg:CC 21) (const_int 0)) - (match_dup 5) - (match_dup 2))) - (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 2))] - "" - "if (TARGET_FAST_FIX) - { - emit_insn (gen_fixqfqi_clobber (operands[0], operands[1])); - DONE; - } - operands[2] = gen_reg_rtx (QImode); - operands[3] = gen_reg_rtx (QFmode); - operands[4] = gen_reg_rtx (QImode); - operands[5] = gen_reg_rtx (QImode); - ") - -(define_expand "fix_truncqfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (fix:HI (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FIX_TRUNCQFHI2_LIBCALL, FIX, HImode, QFmode, 2, operands); - DONE;") - -(define_expand "fixuns_truncqfqi2" - [(set (match_dup 2) (match_dup 4)) - (set (reg:CC 21) - (compare:CC (match_operand:QF 1 "reg_operand" "") - (mem:QF (symbol_ref "*___unsfltcompare")))) - (set (match_dup 2) - (if_then_else:QF (ge (reg:CC 21) (const_int 0)) - (mem:QF (symbol_ref "*___unsfltconst")) - (match_dup 2))) - (parallel [(set (match_dup 3) - (minus:QF (match_dup 1) (match_dup 2))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:QI 0 "reg_operand" "") - (fix:QI (match_dup 3))) - (clobber (reg:CC 21))])] - "" - "operands[2] = gen_reg_rtx (QFmode); - operands[3] = gen_reg_rtx (QFmode); - operands[4] = CONST0_RTX (QFmode); - ") - -(define_expand "fixuns_truncqfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (unsigned_fix:HI (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FIXUNS_TRUNCQFHI2_LIBCALL, UNSIGNED_FIX, - HImode, QFmode, 2, operands); - DONE;") - -; -; RCPF -; -(define_insn "*rcpfqf_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec [(match_operand:QF 1 "src_operand" "fmH")] 5)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rcpf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RSQRF -; -(define_insn "*rsqrfqf_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec [(match_operand:QF 1 "src_operand" "fmH")] 10)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rsqrf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RNDF -; -(define_insn "*rndqf_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec [(match_operand:QF 1 "src_operand" "fmH")] 6)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rnd\\t%1,%0" - [(set_attr "type" "unarycc")]) - - -; Inlined float square root for C4x -(define_expand "sqrtqf2_inline" - [(parallel [(set (match_dup 2) - (unspec [(match_operand:QF 1 "src_operand" "")] 10)) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:QF (match_dup 5) (match_dup 1))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:QF (match_dup 6) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 2) (mult:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:QF (match_dup 6) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 2) (mult:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 1))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:QF 0 "reg_operand" "") - (unspec [(match_dup 4)] 6)) - (clobber (reg:CC_NOOV 21))])] - "! TARGET_C3X" - "if (! reload_in_progress - && ! reg_operand (operands[1], QFmode)) - operands[1] = force_reg (QFmode, operands[1]); - operands[2] = gen_reg_rtx (QFmode); - operands[3] = gen_reg_rtx (QFmode); - operands[4] = gen_reg_rtx (QFmode); - operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", QFmode), - QFmode); - operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", QFmode), - QFmode);") - -(define_expand "sqrtqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (sqrt:QF (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (TARGET_C3X || ! TARGET_INLINE) - FAIL; - else - { - emit_insn (gen_sqrtqf2_inline (operands[0], operands[1])); - DONE; - } - ") - -; -; THREE OPERAND FLOAT INSTRUCTIONS -; - -; -; ADDF -; -(define_expand "addqf3" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (plus:QF (match_operand:QF 1 "src_operand" "") - (match_operand:QF 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (PLUS, operands, QFmode);") - -(define_insn "*addqf3_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f,?f,f") - (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (PLUS, operands, QFmode)" - "@ - addf3\\t%2,%1,%0 - addf3\\t%2,%1,%0 - addf\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*addqf3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) - (clobber (match_scratch:QF 0 "=f,?f,f"))] - "valid_operands (PLUS, operands, QFmode)" - "@ - addf3\\t%2,%1,%0 - addf3\\t%2,%1,%0 - addf\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*addqf3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) - (set (match_operand:QF 0 "reg_operand" "=f,?f,f") - (plus:QF (match_dup 1) - (match_dup 2)))] - "valid_operands (PLUS, operands, QFmode)" - "@ - addf3\\t%2,%1,%0 - addf3\\t%2,%1,%0 - addf\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -; -; SUBF/SUBRF -; -(define_expand "subqf3" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (minus:QF (match_operand:QF 1 "src_operand" "") - (match_operand:QF 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MINUS, operands, QFmode);") - -(define_insn "*subqf3_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f,?f,f,f") - (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, QFmode)" - "@ - subf3\\t%2,%1,%0 - subf3\\t%2,%1,%0 - subf\\t%2,%0 - subrf\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -(define_insn "*subqf3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G,G"))) - (clobber (match_scratch:QF 0 "=f,?f,f,f"))] - "valid_operands (MINUS, operands, QFmode)" - "@ - subf3\\t%2,%1,%0 - subf3\\t%2,%1,%0 - subf\\t%2,%0 - subrf\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -(define_insn "*subqf3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G,G"))) - (set (match_operand:QF 0 "reg_operand" "=f,?f,f,f") - (minus:QF (match_dup 1) - (match_dup 2)))] - "valid_operands (MINUS, operands, QFmode)" - "@ - subf3\\t%2,%1,%0 - subf3\\t%2,%1,%0 - subf\\t%2,%0 - subrf\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -; -; MPYF -; -(define_expand "mulqf3" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (mult:QF (match_operand:QF 1 "src_operand" "") - (match_operand:QF 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MULT, operands, QFmode);") - -(define_insn "*mulqf3_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f,?f,f") - (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MULT, operands, QFmode)" - "@ - mpyf3\\t%2,%1,%0 - mpyf3\\t%2,%1,%0 - mpyf\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*mulqf3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) - (clobber (match_scratch:QF 0 "=f,?f,f"))] - "valid_operands (MULT, operands, QFmode)" - "@ - mpyf3\\t%2,%1,%0 - mpyf3\\t%2,%1,%0 - mpyf\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*mulqf3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0") - (match_operand:QF 2 "src_operand" "R,fS<>,fmH")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) - (set (match_operand:QF 0 "reg_operand" "=f,?f,f") - (mult:QF (match_dup 1) - (match_dup 2)))] - "valid_operands (MULT, operands, QFmode)" - "@ - mpyf3\\t%2,%1,%0 - mpyf3\\t%2,%1,%0 - mpyf\\t%2,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -; -; CMPF -; -(define_expand "cmpqf" - [(set (reg:CC 21) - (compare:CC (match_operand:QF 0 "src_operand" "") - (match_operand:QF 1 "src_operand" "")))] - "" - "legitimize_operands (COMPARE, operands, QFmode); - c4x_compare_op0 = operands[0]; - c4x_compare_op1 = operands[1]; - DONE;") - -(define_insn "*cmpqf" - [(set (reg:CC 21) - (compare:CC (match_operand:QF 0 "src_operand" "fR,?fS<>,f") - (match_operand:QF 1 "src_operand" "R,fS<>,fmH")))] - "valid_operands (COMPARE, operands, QFmode)" - "@ - cmpf3\\t%1,%0 - cmpf3\\t%1,%0 - cmpf\\t%1,%0" - [(set_attr "type" "compare,compare,compare")]) - -(define_insn "*cmpqf_noov" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:QF 0 "src_operand" "fR,?fS<>,f") - (match_operand:QF 1 "src_operand" "R,fS<>,fmH")))] - "valid_operands (COMPARE, operands, QFmode)" - "@ - cmpf3\\t%1,%0 - cmpf3\\t%1,%0 - cmpf\\t%1,%0" - [(set_attr "type" "compare,compare,compare")]) - -; Inlined float divide for C4x -(define_expand "divqf3_inline" - [(parallel [(set (match_dup 3) - (unspec [(match_operand:QF 2 "src_operand" "")] 5)) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:QF (match_dup 5) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:QF (match_dup 3) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:QF (match_dup 5) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:QF (match_dup 3) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) - (mult:QF (match_operand:QF 1 "src_operand" "") - (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:QF 0 "reg_operand" "") - (unspec [(match_dup 3)] 6)) - (clobber (reg:CC_NOOV 21))])] - "! TARGET_C3X" - "if (! reload_in_progress - && ! reg_operand (operands[2], QFmode)) - operands[2] = force_reg (QFmode, operands[2]); - operands[3] = gen_reg_rtx (QFmode); - operands[4] = gen_reg_rtx (QFmode); - operands[5] = CONST2_RTX (QFmode);") - -(define_expand "divqf3" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (div:QF (match_operand:QF 1 "src_operand" "") - (match_operand:QF 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (TARGET_C3X || ! TARGET_INLINE) - { - c4x_emit_libcall3 (DIVQF3_LIBCALL, DIV, QFmode, operands); - DONE; - } - else - { - emit_insn (gen_divqf3_inline (operands[0], operands[1], operands[2])); - DONE; - } - ") - -; -; CONDITIONAL MOVES -; - -(define_insn "*ldi_conditional" - [(set (match_operand:QI 0 "reg_operand" "=r,r") - (if_then_else:QI (match_operator 1 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (match_operand:QI 2 "src_operand" "g,0") - (match_operand:QI 3 "src_operand" "0,g")))] - "" - "@ - ldi%1\\t%2,%0 - ldi%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -(define_insn "*ldi_conditional_noov" - [(set (match_operand:QI 0 "reg_operand" "=r,r") - (if_then_else:QI (match_operator 1 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (match_operand:QI 2 "src_operand" "g,0") - (match_operand:QI 3 "src_operand" "0,g")))] - "GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE - && GET_CODE (operands[1]) != LT - && GET_CODE (operands[1]) != GT" - "@ - ldi%1\\t%2,%0 - ldi%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -; Move operand 2 to operand 0 if condition (operand 1) is true -; else move operand 3 to operand 0. -; The temporary register is required below because some of the operands -; might be identical (namely 0 and 2). -; -(define_expand "movqicc" - [(set (match_operand:QI 0 "reg_operand" "") - (if_then_else:QI (match_operand 1 "comparison_operator" "") - (match_operand:QI 2 "src_operand" "") - (match_operand:QI 3 "src_operand" "")))] - "" - "{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1); - if (ccreg == NULL_RTX) FAIL; - emit_insn (gen_rtx_SET (QImode, operands[0], - gen_rtx_IF_THEN_ELSE (QImode, - gen_rtx (code, VOIDmode, ccreg, const0_rtx), - operands[2], operands[3]))); - DONE;}") - -(define_insn "*ldf_conditional" - [(set (match_operand:QF 0 "reg_operand" "=f,f") - (if_then_else:QF (match_operator 1 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (match_operand:QF 2 "src_operand" "fmH,0") - (match_operand:QF 3 "src_operand" "0,fmH")))] - "" - "@ - ldf%1\\t%2,%0 - ldf%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -(define_insn "*ldf_conditional_noov" - [(set (match_operand:QF 0 "reg_operand" "=f,f") - (if_then_else:QF (match_operator 1 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (match_operand:QF 2 "src_operand" "fmH,0") - (match_operand:QF 3 "src_operand" "0,fmH")))] - "GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE - && GET_CODE (operands[1]) != LT - && GET_CODE (operands[1]) != GT" - "@ - ldf%1\\t%2,%0 - ldf%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -(define_expand "movqfcc" - [(set (match_operand:QF 0 "reg_operand" "") - (if_then_else:QF (match_operand 1 "comparison_operator" "") - (match_operand:QF 2 "src_operand" "") - (match_operand:QF 3 "src_operand" "")))] - "" - "{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1); - if (ccreg == NULL_RTX) FAIL; - emit_insn (gen_rtx_SET (QFmode, operands[0], - gen_rtx_IF_THEN_ELSE (QFmode, - gen_rtx (code, VOIDmode, ccreg, const0_rtx), - operands[2], operands[3]))); - DONE;}") - -(define_expand "seq" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (eq (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (EQ, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "sne" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (ne (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (NE, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "slt" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (lt (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (LT, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "sltu" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (ltu (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (LTU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "sgt" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (gt (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (GT, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "sgtu" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (gtu (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (GTU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "sle" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (le (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (LE, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "sleu" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (leu (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (LEU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "sge" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (ge (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (GE, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "sgeu" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (geu (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (GEU, c4x_compare_op0, c4x_compare_op1);") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operator 1 "comparison_operator" [(reg:CC 21) (const_int 0)]))] - "reload_completed" - [(set (match_dup 0) (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (match_op_dup 1 [(reg:CC 21) (const_int 0)]) - (const_int 1) - (match_dup 0)))] - "") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operator 1 "comparison_operator" [(reg:CC_NOOV 21) (const_int 0)]))] - "reload_completed" - [(set (match_dup 0) (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (match_op_dup 1 [(reg:CC_NOOV 21) (const_int 0)]) - (const_int 1) - (match_dup 0)))] - "") - -(define_insn "*bu" - [(set (pc) - (unspec [(match_operand:QI 0 "reg_operand" "r")] 1))] - "" - "bu%#\\t%0" - [(set_attr "type" "jump")]) - -(define_expand "caseqi" - [(parallel [(set (match_dup 5) - (minus:QI (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (reg:CC 21) - (compare:CC (match_dup 5) - (match_operand:QI 2 "src_operand" ""))) - (set (pc) - (if_then_else (gtu (reg:CC 21) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (parallel [(set (match_dup 6) - (plus:QI (match_dup 5) - (label_ref:QI (match_operand 3 "" "")))) - (clobber (reg:CC_NOOV 21))]) - (set (match_dup 7) - (mem:QI (match_dup 6))) - (set (pc) (match_dup 7))] - "" - "operands[5] = gen_reg_rtx (QImode); - operands[6] = gen_reg_rtx (QImode); - operands[7] = gen_reg_rtx (QImode);") - -; -; PARALLEL FLOAT INSTRUCTIONS -; -; This patterns are under development - -; -; ABSF/STF -; - -(define_insn "*absqf2_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (abs:QF (match_operand:QF 1 "par_ind_operand" "S<>"))) - (set (match_operand:QF 2 "par_ind_operand" "=S<>") - (match_operand:QF 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC_NOOV 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" - "absf\\t%1,%0\\n||\\tstf\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; ADDF/STF -; - -(define_insn "*addqf3_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (plus:QF (match_operand:QF 1 "parallel_operand" "%q") - (match_operand:QF 2 "parallel_operand" "S<>"))) - (set (match_operand:QF 3 "par_ind_operand" "=S<>") - (match_operand:QF 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QFmode)" - "addf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; FLOAT/STF -; - -(define_insn "*floatqiqf2_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (float:QF (match_operand:QI 1 "par_ind_operand" "S<>"))) - (set (match_operand:QF 2 "par_ind_operand" "=S<>") - (match_operand:QF 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" - "float\\t%1,%0\\n||\\tstf\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; MPYF/ADDF -; - -(define_insn "*mulqf3_addqf3_clobber" - [(set (match_operand:QF 0 "r0r1_reg_operand" "=t") - (mult:QF (match_operand:QF 1 "parallel_operand" "%S<>q") - (match_operand:QF 2 "parallel_operand" "S<>q"))) - (set (match_operand:QF 3 "r2r3_reg_operand" "=u") - (plus:QF (match_operand:QF 4 "parallel_operand" "%S<>q") - (match_operand:QF 5 "parallel_operand" "S<>q"))) - (clobber (reg:CC 21))] - "TARGET_PARALLEL_MPY && valid_parallel_operands_6 (operands, QFmode)" - "mpyf3\\t%2,%1,%0\\n||\\taddf3\\t%5,%4,%3" - [(set_attr "type" "binarycc")]) - - -; -; MPYF/STF -; - -(define_insn "*mulqf3_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (mult:QF (match_operand:QF 1 "parallel_operand" "%q") - (match_operand:QF 2 "parallel_operand" "S<>"))) - (set (match_operand:QF 3 "par_ind_operand" "=S<>") - (match_operand:QF 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QFmode)" - "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; MPYF/SUBF -; - -(define_insn "*mulqf3_subqf3_clobber" - [(set (match_operand:QF 0 "r0r1_reg_operand" "=t") - (mult:QF (match_operand:QF 1 "parallel_operand" "S<>q") - (match_operand:QF 2 "parallel_operand" "S<>q"))) - (set (match_operand:QF 3 "r2r3_reg_operand" "=u") - (minus:QF (match_operand:QF 4 "parallel_operand" "S<>q") - (match_operand:QF 5 "parallel_operand" "S<>q"))) - (clobber (reg:CC 21))] - "TARGET_PARALLEL_MPY && valid_parallel_operands_6 (operands, QFmode)" - "mpyf3\\t%2,%1,%0\\n||\\tsubf3\\t%5,%4,%3" - [(set_attr "type" "binarycc")]) - -; -; NEGF/STF -; - -(define_insn "*negqf2_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (neg:QF (match_operand:QF 1 "par_ind_operand" "S<>"))) - (set (match_operand:QF 2 "par_ind_operand" "=S<>") - (match_operand:QF 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" - "negf\\t%1,%0\\n||\\tstf\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; SUBF/STF -; - -(define_insn "*subqf3_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (minus:QF (match_operand:QF 1 "ext_low_reg_operand" "q") - (match_operand:QF 2 "par_ind_operand" "S<>"))) - (set (match_operand:QF 3 "par_ind_operand" "=S<>") - (match_operand:QF 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QFmode)" - "subf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; PARALLEL INTEGER INSTRUCTIONS -; -; These patterns are under development - -; -; ABSI/STI -; - -(define_insn "*absqi2_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (abs:QI (match_operand:QI 1 "par_ind_operand" "S<>"))) - (set (match_operand:QI 2 "par_ind_operand" "=S<>") - (match_operand:QI 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC_NOOV 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)" - "absi\\t%1,%0\\n||\\tsti\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; ADDI/STI -; - -(define_insn "*addqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (plus:QI (match_operand:QI 1 "parallel_operand" "%q") - (match_operand:QI 2 "parallel_operand" "S<>"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; AND/STI -; - -(define_insn "*andqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (and:QI (match_operand:QI 1 "parallel_operand" "%q") - (match_operand:QI 2 "parallel_operand" "S<>"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; ASH(left)/STI -; - -(define_insn "*ashlqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (ashift:QI (match_operand:QI 1 "par_ind_operand" "S<>") - (match_operand:QI 2 "ext_low_reg_operand" "q"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; ASH(right)/STI -; - -(define_insn "*ashrqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (ashiftrt:QI (match_operand:QI 1 "par_ind_operand" "S<>") - (neg:QI (match_operand:QI 2 "ext_low_reg_operand" "q")))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; FIX/STI -; - -(define_insn "*fixqfqi2_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (fix:QI (match_operand:QF 1 "par_ind_operand" "S<>"))) - (set (match_operand:QI 2 "par_ind_operand" "=S<>") - (match_operand:QI 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)" - "fix\\t%1,%0\\n||\\tsti\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; LSH(right)/STI -; - -(define_insn "*lshrqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (lshiftrt:QI (match_operand:QI 1 "par_ind_operand" "S<>") - (neg:QI (match_operand:QI 2 "ext_low_reg_operand" "q")))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "lsh3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; MPYI/ADDI -; - -(define_insn "*mulqi3_addqi3_clobber" - [(set (match_operand:QI 0 "r0r1_reg_operand" "=t") - (mult:QI (match_operand:QI 1 "parallel_operand" "S<>q") - (match_operand:QI 2 "parallel_operand" "S<>q"))) - (set (match_operand:QI 3 "r2r3_reg_operand" "=u") - (plus:QI (match_operand:QI 4 "parallel_operand" "S<>q") - (match_operand:QI 5 "parallel_operand" "S<>q"))) - (clobber (reg:CC 21))] - "TARGET_PARALLEL_MPY && TARGET_MPYI - && valid_parallel_operands_6 (operands, QImode)" - "mpyi3\\t%2,%1,%0\\n||\\taddi3\\t%5,%4,%3" - [(set_attr "type" "binarycc")]) - -; -; MPYI/STI -; - -(define_insn "*mulqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (mult:QI (match_operand:QI 1 "parallel_operand" "%q") - (match_operand:QI 2 "parallel_operand" "S<>"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && TARGET_MPYI - && valid_parallel_operands_5 (operands, QImode)" - "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; MPYI/SUBI -; - -(define_insn "*mulqi3_subqi3_clobber" - [(set (match_operand:QI 0 "r0r1_reg_operand" "=t") - (mult:QI (match_operand:QI 1 "parallel_operand" "S<>q") - (match_operand:QI 2 "parallel_operand" "S<>q"))) - (set (match_operand:QI 3 "r2r3_reg_operand" "=u") - (minus:QI (match_operand:QI 4 "parallel_operand" "S<>q") - (match_operand:QI 5 "parallel_operand" "S<>q"))) - (clobber (reg:CC 21))] - "TARGET_PARALLEL_MPY && TARGET_MPYI - && valid_parallel_operands_6 (operands, QImode)" - "mpyi3\\t%2,%1,%0\\n||\\tsubi3\\t%5,%4,%3" - [(set_attr "type" "binarycc")]) - -; -; NEGI/STI -; - -(define_insn "*negqi2_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (neg:QI (match_operand:QI 1 "par_ind_operand" "S<>"))) - (set (match_operand:QI 2 "par_ind_operand" "=S<>") - (match_operand:QI 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)" - "negi\\t%1,%0\\n||\\tsti\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; NOT/STI -; - -(define_insn "*notqi2_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (not:QI (match_operand:QI 1 "par_ind_operand" "S<>"))) - (set (match_operand:QI 2 "par_ind_operand" "=S<>") - (match_operand:QI 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)" - "not\\t%1,%0\\n||\\tsti\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; OR/STI -; - -(define_insn "*iorqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (ior:QI (match_operand:QI 1 "parallel_operand" "%q") - (match_operand:QI 2 "parallel_operand" "S<>"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; SUBI/STI -; - -(define_insn "*subqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (minus:QI (match_operand:QI 1 "ext_low_reg_operand" "q") - (match_operand:QI 2 "par_ind_operand" "S<>"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "subi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; XOR/STI -; - -(define_insn "*xorqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (xor:QI (match_operand:QI 1 "parallel_operand" "%q") - (match_operand:QI 2 "parallel_operand" "S<>"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; BRANCH/CALL INSTRUCTIONS -; - -; -; Branch instructions -; -(define_insn "*b" - [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "* - return c4x_output_cbranch (\"b%0\", insn);" - [(set_attr "type" "jmpc")]) - -(define_insn "*b_rev" - [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "* - return c4x_output_cbranch (\"b%I0\", insn);" - [(set_attr "type" "jmpc")]) - -(define_insn "*b_noov" - [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "GET_CODE (operands[0]) != LE - && GET_CODE (operands[0]) != GE - && GET_CODE (operands[0]) != LT - && GET_CODE (operands[0]) != GT" - "* - return c4x_output_cbranch (\"b%0\", insn);" - [(set_attr "type" "jmpc")]) - -(define_insn "*b_noov_rev" - [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "GET_CODE (operands[0]) != LE - && GET_CODE (operands[0]) != GE - && GET_CODE (operands[0]) != LT - && GET_CODE (operands[0]) != GT" - "* - return c4x_output_cbranch (\"b%I0\", insn);" - [(set_attr "type" "jmpc")]) - -(define_expand "beq" - [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (EQ, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "bne" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (NE, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "blt" - [(set (pc) (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (LT, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "bltu" - [(set (pc) (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (LTU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "bgt" - [(set (pc) (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (GT, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "bgtu" - [(set (pc) (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (GTU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "ble" - [(set (pc) (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (LE, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "bleu" - [(set (pc) (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (LEU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "bge" - [(set (pc) (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (GE, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "bgeu" - [(set (pc) (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (GEU, c4x_compare_op0, c4x_compare_op1);") - -(define_insn "*b_reg" - [(set (pc) (match_operand:QI 0 "reg_operand" "r"))] - "" - "bu%#\\t%0" - [(set_attr "type" "jump")]) - -(define_expand "indirect_jump" - [(set (pc) (match_operand:QI 0 "reg_operand" ""))] - "" - "") - -(define_insn "tablejump" - [(set (pc) (match_operand:QI 0 "src_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "" - "bu%#\\t%0" - [(set_attr "type" "jump")]) - -; -; CALL -; -(define_insn "*call_c3x" - [(call (match_operand:QI 0 "call_operand" "T,!o") - (match_operand:QI 1 "general_operand" "")) - (clobber (reg:QI 31))] - ;; Operand 1 not really used on the C4x. The C30 doesn't have reg 31. - - "TARGET_C3X" - "@ - call\\t%C0 - callu\\t%R0" - [(set_attr "type" "call,call")]) - -; LAJ requires R11 (31) for the return address -(define_insn "*laj" - [(call (match_operand:QI 0 "call_operand" "T,!o") - (match_operand:QI 1 "general_operand" "")) - (clobber (reg:QI 31))] - ;; Operand 1 not really used on the C4x. - - "! TARGET_C3X" - "* - if (which_alternative == 0) - { - if (final_sequence) - return \"laj\\t%C0\"; - else - return \"call\\t%C0\"; - } - else - { - if (final_sequence) - return \"laju\\t%R0\"; - else - return \"callu\\t%R0\"; - }" - [(set_attr "type" "laj,laj")]) - -(define_expand "call" - [(parallel [(call (match_operand:QI 0 "call_operand" "") - (match_operand:QI 1 "general_operand" "")) - (clobber (reg:QI 31))])] - "" - "") - -(define_insn "*callv_c3x" - [(set (match_operand 0 "" "=r,r") - (call (match_operand:QI 1 "call_operand" "T,!o") - (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:QI 31))] - ;; Operand 0 and 2 not really used for the C4x. - ;; The C30 doesn't have reg 31. - - "TARGET_C3X" - "@ - call\\t%C1 - callu\\t%R1" - [(set_attr "type" "call,call")]) - -; LAJ requires R11 (31) for the return address -(define_insn "*lajv" - [(set (match_operand 0 "" "=r,r") - (call (match_operand:QI 1 "call_operand" "T,!o") - (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:QI 31))] - ;; Operand 0 and 2 not really used in the C30 instruction. - - "! TARGET_C3X" - "* - if (which_alternative == 0) - { - if (final_sequence) - return \"laj\\t%C1\"; - else - return \"call\\t%C1\"; - } - else - { - if (final_sequence) - return \"laju\\t%R1\"; - else - return \"callu\\t%R1\"; - }" - [(set_attr "type" "laj,laj")]) - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "call_operand" "") - (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:QI 31))])] - "" - "") - -(define_insn "return" - [(return)] - "c4x_null_epilogue_p ()" - "rets" - [(set_attr "type" "rets")]) - -(define_insn "*return_cc" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (return) - (pc)))] - "c4x_null_epilogue_p ()" - "rets%0" - [(set_attr "type" "rets")]) - -(define_insn "*return_cc_noov" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (return) - (pc)))] - "GET_CODE (operands[0]) != LE - && GET_CODE (operands[0]) != GE - && GET_CODE (operands[0]) != LT - && GET_CODE (operands[0]) != GT - && c4x_null_epilogue_p ()" - "rets%0" - [(set_attr "type" "rets")]) - -(define_insn "*return_cc_inverse" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (pc) - (return)))] - "c4x_null_epilogue_p ()" - "rets%I0" - [(set_attr "type" "rets")]) - -(define_insn "*return_cc_noov_inverse" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (pc) - (return)))] - "GET_CODE (operands[0]) != LE - && GET_CODE (operands[0]) != GE - && GET_CODE (operands[0]) != LT - && GET_CODE (operands[0]) != GT - && c4x_null_epilogue_p ()" - "rets%I0" - [(set_attr "type" "rets")]) - -(define_insn "jump" - [(set (pc) (label_ref (match_operand 0 "" "")))] - "" - "br%#\\t%l0" - [(set_attr "type" "jump")]) - -; -; DBcond -; -; Note we have to emit a dbu instruction if there are no delay slots -; to fill. -; Also note that GCC will try to reverse a loop to see if it can -; utilise this instruction. However, if there are more than one -; memory reference in the loop, it cannot guarantee that reversing -; the loop will work :( (see check_dbra_loop() in loop.c) -; Note that the C3x only decrements the 24 LSBs of the address register -; and the 8 MSBs are untouched. The C4x uses all 32-bits. We thus -; have an option to disable this instruction. -(define_insn "*db" - [(set (pc) - (if_then_else (ne (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (clobber (reg:CC_NOOV 21))] - "TARGET_DB && TARGET_LOOP_UNSIGNED" - "* - if (which_alternative == 0) - return \"dbu%#\\t%0,%l1\"; - else if (which_alternative == 1) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tbge\", insn); - else if (which_alternative == 2) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tcmpi\\t0,%0\\n\\tbge\", insn); - else - return c4x_output_cbranch (\"push\\tr0\\n\\tldi\\t%0,r0\\n\\tsubi\\t1,r0\\n\\tsti\\tr0,%0\\n\\tpop\\tr0\\n\\tbhs\", insn); - " - [(set_attr "type" "db,jmpc,jmpc,jmpc")]) - - -; This insn is used for some loop tests, typically loops reversed when -; strength reduction is used. It is actually created when the instruction -; combination phase combines the special loop test. Since this insn -; is both a jump insn and has an output, it must deal with its own -; reloads, hence the `m' constraints. - -; The C4x does the decrement and then compares the result against zero. -; It branches if the result was greater than or equal to zero. -; In the RTL the comparison and decrement are assumed to happen -; at the same time so we bias the iteration counter with by -1 -; when we make the test. -(define_insn "decrement_and_branch_until_zero" - [(set (pc) - (if_then_else (ge (plus:QI (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (clobber (reg:CC_NOOV 21))] - "TARGET_DB && find_reg_note (insn, REG_NONNEG, 0)" - "* - if (which_alternative == 0) - return \"dbu%#\\t%0,%l1\"; - else if (which_alternative == 1) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tbge\", insn); - else if (which_alternative == 2) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tcmpi\\t0,%0\\n\\tbge\", insn); - else - return c4x_output_cbranch (\"push\\tr0\\n\\tldi\\t%0,r0\\n\\tsubi\\t1,r0\\n\\tsti\\tr0,%0\\n\\tpop\\tr0\\n\\tbhs\", insn); - " - [(set_attr "type" "db,jmpc,jmpc,jmpc")]) - -; -; MISC INSTRUCTIONS -; - -; -; NOP -; -(define_insn "nop" - [(const_int 0)] - "" - "nop") -; Default to misc type attr. - - -; -; RPTB -; -(define_insn "rptb_top" - [(use (label_ref (match_operand 0 "" ""))) - (use (label_ref (match_operand 1 "" "")))] - "" - "* - return ! final_sequence && c4x_rptb_rpts_p (insn, operands[0]) - ? \"rpts\\trc\" : \"rptb%#\\t%l1-1\"; - " - [(set_attr "type" "repeat_top")]) - -; This pattern needs to be emitted at the start of the loop to -; say that RS and RE are loaded. -(define_insn "init_branch_on_count" - [(unspec[(match_operand:QI 0 "rc_reg_operand" "v")] 22) - (clobber (reg:QI 25)) - (clobber (reg:QI 26))] - "" - "" - [(set_attr "type" "repeat")]) - -; The RS (25) and RE (26) registers must be unviolate from the top of the loop -; to here. -(define_insn "rptb_end" - [(set (pc) - (if_then_else (ge (match_operand:QI 2 "rc_reg_operand" "0,0,0,0,0") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_operand:QI 0 "rc_reg_operand" "+v,*a,*d,*x*k,*m") - (plus:QI (match_dup 0) - (const_int -1))) - (use (reg:QI 25)) - (use (reg:QI 26)) - (clobber (reg:CC_NOOV 21))] - "" - "* - if (which_alternative == 0) - return c4x_rptb_nop_p (insn) ? \"nop\" : \"\"; - else if (which_alternative == 1) - return \"dbu%#\\t%0,%l1\"; - else if (which_alternative == 2) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tbge\", insn); - else if (which_alternative == 3) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tcmpi\\t0,%0\\n\\tbge\", insn); - else - return c4x_output_cbranch (\"push\\tr0\\n\\tldi\\t%0,r0\\n\\tsubi\\t1,r0\\n\\tsti\\tr0,%0\\n\\tpop\\tr0\\n\\tbhs\", insn); - " - [(set_attr "type" "repeat,db,jmpc,jmpc,jmpc")]) - - -(define_expand "decrement_and_branch_on_count" - [(parallel [(set (pc) - (if_then_else (ge (match_operand:QI 0 "rc_reg_operand" "") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (use (reg:QI 25)) - (use (reg:QI 26)) - (clobber (reg:CC_NOOV 21))])] - "" - "") - - -(define_expand "movstrqi_small2" - [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" "")) - (mem:BLK (match_operand:BLK 1 "src_operand" ""))) - (use (match_operand:QI 2 "immediate_operand" "")) - (use (match_operand:QI 3 "immediate_operand" "")) - (clobber (match_operand:QI 4 "ext_low_reg_operand" ""))])] - "" - " - { - rtx src, dst, tmp; - rtx src_mem, dst_mem; - int len; - int i; - - dst = operands[0]; - src = operands[1]; - len = INTVAL (operands[2]); - tmp = operands[4]; - - src_mem = gen_rtx_MEM (QImode, src); - dst_mem = gen_rtx_MEM (QImode, dst); - - emit_insn (gen_movqi (tmp, src_mem)); - emit_insn (gen_addqi3_noclobber (src, src, const1_rtx)); - for (i = 1; i < len; i++) - { - emit_insn (gen_movqi_parallel (tmp, src_mem, dst_mem, tmp)); - emit_insn (gen_addqi3_noclobber (src, src, const1_rtx)); - emit_insn (gen_addqi3_noclobber (dst, dst, const1_rtx)); - } - emit_insn (gen_movqi (dst_mem, tmp)); - emit_insn (gen_addqi3_noclobber (dst, dst, const1_rtx)); - DONE; - } - ") - - -; -; BLOCK MOVE -; We should probably get RC loaded when using RPTB automagically... -; There's probably no need to call _memcpy() if we don't get -; a immediate operand for the size. We could do a better job here -; than most memcpy() implementations. -; operand 2 is the number of bytes -; operand 3 is the shared alignment -; operand 4 is a scratch register - -(define_insn "movstrqi_small" - [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "a")) - (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a"))) - (use (match_operand:QI 2 "immediate_operand" "i")) - (use (match_operand:QI 3 "immediate_operand" "")) - (clobber (match_operand:QI 4 "ext_low_reg_operand" "=&q")) - (clobber (match_dup 0)) - (clobber (match_dup 1))] - "" - "* - { - int i; - int len = INTVAL (operands[2]); - int first = 1; - - for (i = 0; i < len; i++) - { - if (first) - output_asm_insn (\"ldiu\\t*%1++,%4\", operands); - else - output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); - output_asm_insn (\"sti\\t%4,*%0++\", operands); - first = 0; - } - return \"\"; - } - " - [(set_attr "type" "multi")]) - -(define_insn "movstrqi_large" - [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "a")) - (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a"))) - (use (match_operand:QI 2 "immediate_operand" "i")) - (use (match_operand:QI 3 "immediate_operand" "")) - (clobber (match_operand:QI 4 "ext_low_reg_operand" "=&q")) - (clobber (match_dup 0)) - (clobber (match_dup 1)) - (clobber (reg:QI 25)) - (clobber (reg:QI 26)) - (clobber (reg:QI 27))] - "" - "* - { - int len = INTVAL (operands[2]); - - output_asm_insn (\"ldiu\\t*%1++,%4\", operands); - if (TARGET_RPTS_CYCLES (len)) - { - output_asm_insn (\"rpts\\t%2-2\", operands); - output_asm_insn (\"sti\\t%4,*%0++\", operands); - output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); - return \"sti\\t%4,*%0++\"; - } - else - { - output_asm_insn (\"ldiu\\t%2-2,rc\", operands); - output_asm_insn (\"rptb\\t$+1\", operands); - output_asm_insn (\"sti\\t%4,*%0++\", operands); - output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); - - return \"sti\\t%4,*%0++\"; - } - } - " - [(set_attr "type" "multi")]) - -; Operand 2 is the count, operand 3 is the alignment. -(define_expand "movstrqi" - [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" "")) - (mem:BLK (match_operand:BLK 1 "src_operand" ""))) - (use (match_operand:QI 2 "immediate_operand" "")) - (use (match_operand:QI 3 "immediate_operand" ""))])] - "" - " - { - rtx tmp; - if (GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) > 32767 - || INTVAL (operands[2]) <= 0) - { - FAIL; /* Try to call _memcpy */ - } - - operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - tmp = gen_reg_rtx (QImode); - if (INTVAL (operands[2]) < 8) - emit_insn (gen_movstrqi_small (operands[0], operands[1], operands[2], - operands[3], tmp)); - else - { - emit_insn (gen_movstrqi_large (operands[0], operands[1], operands[2], - operands[3], tmp)); - } - DONE; - }") - - -(define_insn "*cmpstrqi" - [(set (match_operand:QI 0 "reg_operand" "=d") - (compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a")) - (mem:BLK (match_operand:QI 2 "addr_reg_operand" "a")))) - (use (match_operand:QI 3 "immediate_operand" "i")) - (use (match_operand:QI 4 "immediate_operand" "")) - (clobber (match_operand:QI 5 "std_reg_operand" "=&c")) - (clobber (reg:QI 21))] - "" - "* - { - output_asm_insn (\"ldi\\t%3-1,%5\", operands); - output_asm_insn (\"$1:\tsubi3\\t*%1++,*%2++,%0\", operands); - output_asm_insn (\"dbeq\\t%5,$1\", operands); - return \"\"; - }") - -(define_expand "cmpstrqi" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (compare:QI (match_operand:BLK 1 "general_operand" "") - (match_operand:BLK 2 "general_operand" ""))) - (use (match_operand:QI 3 "immediate_operand" "")) - (use (match_operand:QI 4 "immediate_operand" "")) - (clobber (match_dup 5)) - (clobber (reg:QI 21))])] - "" - " -{ - if (GET_CODE (operands[3]) != CONST_INT - || INTVAL (operands[3]) > 32767 - || INTVAL (operands[3]) <= 0) - { - FAIL; - } - operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - operands[2] = copy_to_mode_reg (Pmode, XEXP (operands[2], 0)); - operands[5] = gen_reg_rtx (QImode); -}") - -; -; TWO OPERAND LONG DOUBLE INSTRUCTIONS -; - -(define_expand "movhf" - [(set (match_operand:HF 0 "src_operand" "") - (match_operand:HF 1 "src_operand" ""))] - "" - "if (CONSTANT_P (operands[1])) - { - operands[1] = force_const_mem (HFmode, operands[1]); - if (! memory_address_p (HFmode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], HFmode, - XEXP (operands[1], 0)); - } - - /* Memory to memory copies must go through a register. */ - if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[0]) == MEM - && ! reload_in_progress) - operands[1] = force_reg (HFmode, operands[1]); -") - -(define_insn "*movhf_noclobber_reg" - [(set (match_operand:HF 0 "reg_operand" "=h") - (match_operand:HF 1 "reg_operand" "h"))] - "" - "ldfu\\t%1,%0" - [(set_attr "type" "unary")]) - -; The predicates could be tightened to disallow constants -(define_insn "*movhf_noclobber" - [(set (match_operand:HF 0 "src_operand" "=h,m") - (match_operand:HF 1 "src_operand" "m,h"))] - "reg_operand (operands[0], HFmode) ^ reg_operand (operands[1], HFmode)" - "#" - [(set_attr "type" "multi,multi")]) - -(define_insn "*movhf_test" - [(set (reg:CC 21) - (compare:CC (match_operand:HF 1 "reg_operand" "h") - (const_int 0))) - (clobber (match_scratch:HF 0 "=h"))] - "" - "ldf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*movhf_set" - [(set (reg:CC 21) - (compare:CC (match_operand:HF 1 "reg_operand" "h") - (match_operand:HF 2 "fp_zero_operand" "G"))) - (set (match_operand:HF 0 "reg_operand" "=h") - (match_dup 1))] - "" - "ldf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_split - [(set (match_operand:HF 0 "reg_operand" "") - (match_operand:HF 1 "memory_operand" ""))] - "reload_completed" - [(set (match_dup 0) (float_extend:HF (match_dup 2))) - (set (match_dup 0) (unspec[(subreg:QI (match_dup 0) 0) (match_dup 3)] 8))] - "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode); - operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode); - PUT_MODE (operands[2], QFmode); - PUT_MODE (operands[3], QImode);") - -(define_split - [(set (match_operand:HF 0 "reg_operand" "") - (match_operand:HF 1 "const_operand" ""))] - "reload_completed && 0" - [(set (match_dup 0) (float_extend:HF (match_dup 2))) - (set (match_dup 0) (unspec[(subreg:QI (match_dup 0) 0) (match_dup 3)] 8))] - "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode); - operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode); - PUT_MODE (operands[2], QFmode); - PUT_MODE (operands[3], QImode);") - -(define_split - [(set (match_operand:HF 0 "memory_operand" "") - (match_operand:HF 1 "reg_operand" ""))] - "reload_completed" - [(set (match_dup 2) (float_truncate:QF (match_dup 1))) - (set (match_dup 3) (unspec [(match_dup 1)] 9))] - "operands[2] = c4x_operand_subword (operands[0], 0, 1, HFmode); - operands[3] = c4x_operand_subword (operands[0], 1, 1, HFmode); - PUT_MODE (operands[2], QFmode); - PUT_MODE (operands[3], QImode);") - -(define_insn "*loadhf_float" - [(set (match_operand:HF 0 "reg_operand" "=h") - (float_extend:HF (match_operand:QF 1 "src_operand" "fmH")))] - "" - "@ - ldfu\\t%1,%0" - [(set_attr "type" "unary")]) - -(define_insn "*loadhf_int" - [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec[(subreg:QI (match_dup 0) 0) - (match_operand:QI 1 "src_operand" "g")] 8))] - "" - "@ - ldiu\\t%1,%0" - [(set_attr "type" "unary")]) - -(define_insn "*storehf_float" - [(set (match_operand:QF 0 "memory_operand" "=m") - (float_truncate:QF (match_operand:HF 1 "reg_operand" "h")))] - "" - "stf\\t%1,%0" - [(set_attr "type" "store")]) - -(define_insn "*storehf_int" - [(set (match_operand:QI 0 "memory_operand" "=m") - (unspec [(match_operand:HF 1 "reg_operand" "h")] 9))] - "" - "@ - sti\\t%1,%0" - [(set_attr "type" "store")]) - -(define_insn "extendqfhf2" - [(set (match_operand:HF 0 "reg_operand" "=h") - (float_extend:HF (match_operand:QF 1 "reg_operand" "h")))] - "" - "ldfu\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "trunchfqf2" - [(set (match_operand:QF 0 "reg_operand" "=h") - (float_truncate:QF (match_operand:HF 1 "reg_operand" "0"))) - (clobber (reg:CC 21))] - "" - "andn\\t0ffh,%0" - [(set_attr "type" "unarycc")]) - -; -; PUSH/POP -; -(define_insn "*pushhf" - [(set (mem:HF (pre_inc:QI (reg:QI 20))) - (match_operand:HF 0 "reg_operand" "h"))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (mem:HF (pre_inc:QI (reg:QI 20))) - (match_operand:HF 0 "reg_operand" ""))] - "reload_completed" - [(set (mem:QF (pre_inc:QI (reg:QI 20))) - (float_truncate:QF (match_dup 0))) - (set (mem:QI (pre_inc:QI (reg:QI 20))) - (unspec [(match_dup 0)] 9))] - "") - -(define_insn "pushhf_trunc" - [(set (mem:QF (pre_inc:QI (reg:QI 20))) - (float_truncate:QF (match_operand:HF 0 "reg_operand" "h")))] - "" - "pushf\\t%0" - [(set_attr "type" "push")]) - -(define_insn "pushhf_int" - [(set (mem:QI (pre_inc:QI (reg:QI 20))) - (unspec [(match_operand:HF 0 "reg_operand" "h")] 9))] - "" - "push\\t%0" - [(set_attr "type" "push")]) - -; we can not use this because the popf will destroy the low 8 bits -;(define_insn "*pophf" -; [(set (match_operand:HF 0 "reg_operand" "=h") -; (mem:HF (post_dec:QI (reg:QI 20)))) -; (clobber (reg:CC 21))] -; "" -; "#" -; [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HF 0 "reg_operand" "") - (mem:HF (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_operand:HF 0 "reg_operand" "=h") - (float_extend:HF (mem:QF (post_dec:QI (reg:QI 20))))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 0) - (unspec[(subreg:QI (match_dup 0) 0) - (mem:QI (post_dec:QI (reg:QI 20)))] 8)) - (clobber (reg:CC 21))])] - "") - -(define_insn "*pophf_int" - [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec[(subreg:QI (match_dup 0) 0) - (mem:QI (post_dec:QI (reg:QI 20)))] 8)) - (clobber (reg:CC 21))] - "" - "@ - pop\\t%0" - [(set_attr "type" "pop")]) - -(define_insn "*pophf_float" - [(set (match_operand:HF 0 "reg_operand" "=h") - (float_extend:HF (mem:QF (post_dec:QI (reg:QI 20))))) - (clobber (reg:CC 21))] - "" - "@ - popf\\t%0" - [(set_attr "type" "unary")]) - -; -; FIX -; -(define_insn "fixhfqi_clobber" - [(set (match_operand:QI 0 "reg_operand" "=dc") - (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH"))) - (clobber (reg:CC 21))] - "" - "fix\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; ABSF -; -(define_expand "abshf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (abs:HF (match_operand:HF 1 "reg_or_const_operand" ""))) - (clobber (reg:CC_NOOV 21))])] -"" -"") - -(define_insn "*abshf2_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (abs:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))) - (clobber (reg:CC_NOOV 21))] - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*abshf2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:HF (match_operand:HF 1 "reg_operand" "h")) - (match_operand:HF 2 "fp_zero_operand" "G"))) - (clobber (match_scratch:HF 0 "=h"))] - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*abshf2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) - (match_operand:HF 2 "fp_zero_operand" "G"))) - (set (match_operand:HF 0 "reg_operand" "=h") - (abs:HF (match_dup 1)))] - - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; NEGF -; -(define_expand "neghf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (neg:HF (match_operand:HF 1 "reg_or_const_operand" ""))) - (clobber (reg:CC 21))])] -"" -"") - -(define_insn "*neghf2_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))) - (clobber (reg:CC 21))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*neghf2_test" - [(set (reg:CC 21) - (compare:CC (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) - (match_operand:HF 2 "fp_zero_operand" "G"))) - (clobber (match_scratch:HF 0 "=h"))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*neghf2_set" - [(set (reg:CC 21) - (compare:CC (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) - (match_operand:HF 2 "fp_zero_operand" "G"))) - (set (match_operand:HF 0 "reg_operand" "=h") - (neg:HF (match_dup 1)))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RCPF -; -(define_insn "*rcpfhf_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec [(match_operand:HF 1 "reg_or_const_operand" "hH")] 5)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rcpf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RSQRF -; -(define_insn "*rsqrfhf_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec [(match_operand:HF 1 "reg_or_const_operand" "hH")] 10)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rsqrf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RNDF -; -(define_insn "*rndhf_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec [(match_operand:HF 1 "reg_or_const_operand" "hH")] 6)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rnd\\t%1,%0" - [(set_attr "type" "unarycc")]) - - -; Inlined float square root for C4x -(define_expand "sqrthf2_inline" - [(parallel [(set (match_dup 2) - (unspec [(match_operand:HF 1 "reg_operand" "")] 10)) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:HF (match_dup 5) (match_dup 1))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:HF (match_dup 6) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 2) (mult:HF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:HF (match_dup 6) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 2) (mult:HF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:HF 0 "reg_operand" "") - (mult:HF (match_dup 2) (match_dup 1))) - (clobber (reg:CC_NOOV 21))])] - "! TARGET_C3X" - " - operands[2] = gen_reg_rtx (HFmode); - operands[3] = gen_reg_rtx (HFmode); - operands[4] = gen_reg_rtx (HFmode); - operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", HFmode), HFmode); - operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", HFmode), HFmode); - ") - - -(define_expand "sqrthf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (sqrt:HF (match_operand:HF 1 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (TARGET_C3X || ! TARGET_INLINE) - FAIL; - else - { - emit_insn (gen_sqrthf2_inline (operands[0], operands[1])); - DONE; - } - ") - -(define_expand "fix_trunchfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (fix:HI (match_operand:HF 1 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FIX_TRUNCHFHI2_LIBCALL, FIX, HImode, HFmode, 2, operands); - DONE;") - -(define_expand "fixuns_trunchfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (unsigned_fix:HI (match_operand:HF 1 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FIXUNS_TRUNCHFHI2_LIBCALL, UNSIGNED_FIX, - HImode, HFmode, 2, operands); - DONE;") - -; -; THREE OPERAND LONG DOUBLE INSTRUCTIONS -; - -; -; ADDF -; -(define_insn "addhf3" - [(set (match_operand:HF 0 "reg_operand" "=?h,h") - (plus:HF (match_operand:HF 1 "reg_operand" "%h,0") - (match_operand:HF 2 "reg_or_const_operand" "h,H"))) - (clobber (reg:CC_NOOV 21))] - "" - "@ - addf3\\t%2,%1,%0 - addf\\t%2,%0" - [(set_attr "type" "binarycc,binarycc")]) - -; -; SUBF -; -(define_insn "subhf3" - [(set (match_operand:HF 0 "reg_operand" "=?h,h,h") - (minus:HF (match_operand:HF 1 "reg_or_const_operand" "h,0,H") - (match_operand:HF 2 "reg_or_const_operand" "h,H,0"))) - (clobber (reg:CC_NOOV 21))] - "" - "@ - subf3\\t%2,%1,%0 - subf\\t%2,%0 - subrf\\t%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -; -; MULF -; -; The C3x MPYF only uses 24 bit precision while the C4x uses 32 bit precison. -; -(define_expand "mulhf3" - [(parallel [(set (match_operand:HF 0 "reg_operand" "=h") - (mult:HF (match_operand:HF 1 "reg_operand" "h") - (match_operand:HF 2 "reg_operand" "h"))) - (clobber (reg:CC_NOOV 21))])] - "" - "if (TARGET_C3X) - { - c4x_emit_libcall3 (MULHF3_LIBCALL, MULT, HFmode, operands); - DONE; - } - ") - -(define_insn "*mulhf3_c40" - [(set (match_operand:HF 0 "reg_operand" "=?h,h") - (mult:HF (match_operand:HF 1 "reg_operand" "%h,0") - (match_operand:HF 2 "reg_or_const_operand" "h,hH"))) - (clobber (reg:CC_NOOV 21))] - "" - "@ - mpyf3\\t%2,%1,%0 - mpyf\\t%2,%0" - [(set_attr "type" "binarycc,binarycc")]) - -; -; CMPF -; -(define_expand "cmphf" - [(set (reg:CC 21) - (compare:CC (match_operand:HF 0 "reg_operand" "") - (match_operand:HF 1 "reg_or_const_operand" "")))] - "" - "c4x_compare_op0 = operands[0]; - c4x_compare_op1 = operands[1]; - DONE;") - -(define_insn "*cmphf" - [(set (reg:CC 21) - (compare:CC (match_operand:HF 0 "reg_operand" "h") - (match_operand:HF 1 "reg_or_const_operand" "hH")))] - "" - "cmpf\\t%1,%0" - [(set_attr "type" "compare")]) - -(define_insn "*cmphf_noov" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:HF 0 "reg_operand" "h") - (match_operand:HF 1 "reg_or_const_operand" "hH")))] - "" - "cmpf\\t%1,%0" - [(set_attr "type" "compare")]) - -; Inlined float divide for C4x -(define_expand "divhf3_inline" - [(parallel [(set (match_dup 3) - (unspec [(match_operand:HF 2 "reg_operand" "")] 5)) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:HF (match_dup 5) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:HF (match_dup 3) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:HF (match_dup 5) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:HF (match_dup 3) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:HF 0 "reg_operand" "") - (mult:HF (match_operand:HF 1 "reg_operand" "") - (match_dup 3))) - (clobber (reg:CC_NOOV 21))])] - "! TARGET_C3X" - " - operands[3] = gen_reg_rtx (HFmode); - operands[4] = gen_reg_rtx (HFmode); - operands[5] = CONST2_RTX (HFmode); - ") - -(define_expand "divhf3" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (div:HF (match_operand:HF 1 "reg_operand" "") - (match_operand:HF 2 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (TARGET_C3X || ! TARGET_INLINE) - { - c4x_emit_libcall3 (DIVHF3_LIBCALL, DIV, HFmode, operands); - DONE; - } - else - { - emit_insn (gen_divhf3_inline (operands[0], operands[1], operands[2])); - DONE; - } - ") - - -; -; TWO OPERAND LONG LONG INSTRUCTIONS -; - -; We could load some constants using define_splits for the C30 -; in the large memory model---these would emit shift and or insns. -(define_expand "movhi" - [(set (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" ""))] - "" - "if (CONSTANT_P (operands[1])) - { - /* We don't need to force all constants into memory. - This could be improved.... */ - operands[1] = force_const_mem (HImode, operands[1]); - if (! memory_address_p (HImode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], HImode, - XEXP (operands[1], 0)); - } - - /* Memory to memory copies must go through a register. */ - if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[0]) == MEM - && ! reload_in_progress) - operands[1] = force_reg (HImode, operands[1]); -") - -; The constraints for movhi must include 'r' if we don't -; restrict HImode regnos to start on an even number, since -; we can get RC, R8 allocated as a pair. We want more -; votes for FP_REGS so we use dr as the constraints. -(define_insn "*movhi_noclobber" - [(set (match_operand:HI 0 "src_operand" "=dr,m") - (match_operand:HI 1 "src_operand" "drm,r"))] - "reg_operand (operands[0], HImode) - || reg_operand (operands[1], HImode)" - "#" - [(set_attr "type" "multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" ""))] - "reload_completed - && (reg_operand (operands[0], HImode) || reg_operand (operands[1], HImode))" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - "operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[3] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode);") - - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "reg_operand" "=dc") - (sign_extend:HI (match_operand:QI 1 "src_operand" "g"))) - (clobber (reg:CC 21))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "=?dc") - (sign_extend:HI (match_operand:QI 1 "src_operand" "g"))) - (clobber (reg:CC 21))] - "reload_completed && TARGET_C3X" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (match_dup 2)) - (parallel [(set (match_dup 3) (ashiftrt:QI (match_dup 3) (const_int 31))) - (clobber (reg:CC 21))])] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -(define_split - [(set (match_operand:HI 0 "reg_operand" "=?dc") - (sign_extend:HI (match_operand:QI 1 "src_operand" "g"))) - (clobber (reg:CC 21))] - "reload_completed && ! TARGET_C3X" - [(set (match_dup 2) (match_dup 1)) - (parallel [(set (match_dup 3) (ashiftrt:QI (match_dup 2) (const_int 31))) - (clobber (reg:CC 21))])] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "reg_operand" "=?dc") - (zero_extend:HI (match_operand:QI 1 "src_operand" "g"))) - (clobber (reg:CC 21))] - "" - "#" - [(set_attr "type" "multi")]) - -; If operand0 and operand1 are the same register we don't need -; the first set. -(define_split - [(set (match_operand:HI 0 "reg_operand" "=?dc") - (zero_extend:HI (match_operand:QI 1 "src_operand" "g"))) - (clobber (reg:CC 21))] - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (const_int 0))] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -; -; PUSH/POP -; -(define_insn "*pushhi" - [(set (mem:HI (pre_inc:QI (reg:QI 20))) - (match_operand:HI 0 "reg_operand" "r"))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (mem:HI (pre_inc:QI (reg:QI 20))) - (match_operand:HI 0 "reg_operand" ""))] - "reload_completed" - [(set (mem:QI (pre_inc:QI (reg:QI 20))) (match_dup 2)) - (set (mem:QI (pre_inc:QI (reg:QI 20))) (match_dup 3))] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -(define_insn "*pophi" - [(set (match_operand:HI 0 "reg_operand" "=r") - (mem:HI (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (mem:HI (pre_inc:QI (reg:QI 20))))] - "reload_completed" - [(set (match_dup 2) (mem:QI (pre_inc:QI (reg:QI 20)))) - (set (match_dup 3) (mem:QI (pre_inc:QI (reg:QI 20))))] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -; -; NEG -; -(define_insn "neghi2" - [(set (match_operand:HI 0 "ext_reg_operand" "=d") - (neg:HI (match_operand:HI 1 "src_operand" "rm"))) - (clobber (reg:CC_NOOV 21))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HI 0 "ext_reg_operand" "") - (neg:HI (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_dup 3)) - (const_int 0))) - (set (match_dup 2) (neg:QI (match_dup 3)))]) - (parallel [(set (match_dup 4) (neg:QI (match_dup 5))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))])] - "operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[3] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode);") - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "reg_operand" "=r") - (not:HI (match_operand:HI 1 "src_operand" "rm"))) - (clobber (reg:CC 21))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (not:HI (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_dup 2) (not:QI (match_dup 3))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 4) (not:QI (match_dup 5))) - (clobber (reg:CC 21))])] - "operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[3] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode);") - -(define_expand "floathiqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (float:QF (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FLOATHIQF2_LIBCALL, FLOAT, QFmode, HImode, 2, operands); - DONE;") - -(define_expand "floatunshiqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (unsigned_float:QF (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FLOATUNSHIQF2_LIBCALL, UNSIGNED_FLOAT, - QFmode, HImode, 2, operands); - DONE;") - -(define_expand "floathihf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (float:HF (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FLOATHIHF2_LIBCALL, FLOAT, HFmode, HImode, 2, operands); - DONE;") - -(define_expand "floatunshihf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (unsigned_float:HF (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (FLOATUNSHIHF2_LIBCALL, UNSIGNED_FLOAT, - HFmode, HImode, 2, operands); - DONE;") - - -; -; THREE OPERAND LONG LONG INSTRUCTIONS -; - -(define_expand "addhi3" - [(parallel [(set (match_operand:HI 0 "ext_reg_operand" "") - (plus:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (PLUS, operands, HImode);") - -(define_insn "*addhi3_clobber" - [(set (match_operand:HI 0 "ext_reg_operand" "=d,?d,d") - (plus:HI (match_operand:HI 1 "src_operand" "%rR,rS<>,0") - (match_operand:HI 2 "src_operand" "R,rS<>,rm"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (PLUS, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "ext_reg_operand" "") - (plus:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QI (match_dup 4) (match_dup 5)) - (const_int 0))) - (set (match_dup 3) (plus:QI (match_dup 4) (match_dup 5)))]) - (parallel [(set (match_dup 6) (plus:QI (match_dup 7) (match_dup 8))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -(define_expand "subhi3" - [(parallel [(set (match_operand:HI 0 "ext_reg_operand" "") - (minus:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MINUS, operands, HImode);") - - -(define_insn "*subhi3_clobber" - [(set (match_operand:HI 0 "ext_reg_operand" "=d,?d,d") - (minus:HI (match_operand:HI 1 "src_operand" "rR,rS<>,0") - (match_operand:HI 2 "src_operand" "R,rS<>,rm"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "ext_reg_operand" "") - (minus:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_dup 4) (match_dup 5)) - (const_int 0))) - (set (match_dup 3) (minus:QI (match_dup 4) (match_dup 5)))]) - (parallel [(set (match_dup 6) (minus:QI (match_dup 7) (match_dup 8))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -(define_expand "iorhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (ior:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (IOR, operands, HImode);") - -(define_insn "*iorhi3_clobber" - [(set (match_operand:HI 0 "reg_operand" "=d,?d,d") - (ior:HI (match_operand:HI 1 "src_operand" "%rR,rS<>,0") - (match_operand:HI 2 "src_operand" "R,rS<>,rm"))) - (clobber (reg:CC 21))] - "valid_operands (IOR, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (ior:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_dup 3) (ior:QI (match_dup 4) (match_dup 5))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 6) (ior:QI (match_dup 7) (match_dup 8))) - (clobber (reg:CC 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -(define_expand "andhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (and:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (AND, operands, HImode);") - -(define_insn "*andhi3_clobber" - [(set (match_operand:HI 0 "reg_operand" "=d,?d,d") - (and:HI (match_operand:HI 1 "src_operand" "%rR,rS<>,0") - (match_operand:HI 2 "src_operand" "R,rS<>,rm"))) - (clobber (reg:CC 21))] - "valid_operands (AND, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (and:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_dup 3) (and:QI (match_dup 4) (match_dup 5))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 6) (and:QI (match_dup 7) (match_dup 8))) - (clobber (reg:CC 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -(define_expand "xorhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (xor:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (AND, operands, HImode);") - - -(define_insn "*xorhi3_clobber" - [(set (match_operand:HI 0 "reg_operand" "=d,?d,d") - (xor:HI (match_operand:HI 1 "src_operand" "%rR,rS<>,0") - (match_operand:HI 2 "src_operand" "R,rS<>,rm"))) - (clobber (reg:CC 21))] - "valid_operands (XOR, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (xor:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_dup 3) (xor:QI (match_dup 4) (match_dup 5))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 6) (xor:QI (match_dup 7) (match_dup 8))) - (clobber (reg:CC 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -; This should do all the dirty work with define_split -(define_expand "ashlhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (ashift:HI (match_operand:HI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32) - { - rtx op0hi = operand_subword (operands[0], 1, 0, HImode); - rtx op0lo = operand_subword (operands[0], 0, 0, HImode); - rtx op1lo = operand_subword (operands[1], 0, 0, HImode); - rtx count = GEN_INT ((INTVAL (operands[2]) - 32)); - - if (INTVAL (count)) - emit_insn (gen_ashlqi3 (op0hi, op1lo, count)); - else - emit_insn (gen_movqi (op0hi, op1lo)); - emit_insn (gen_movqi (op0lo, const0_rtx)); - DONE; - } - emit_insn (gen_ashlhi3_reg (operands[0], operands[1], operands[2])); - DONE;") - -; %0.lo = %1.lo << %2 -; %0.hi = (%1.hi << %2 ) | (%1.lo >> (32 - %2)) -; This algorithm should work for shift counts greater than 32 -(define_expand "ashlhi3_reg" - [(use (match_operand:HI 1 "src_operand" "")) - (use (match_operand:HI 0 "reg_operand" "")) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 7) - (ashift:QI (match_dup 3) - (match_operand:QI 2 "reg_operand" ""))) - (clobber (reg:CC 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 8) - (ashift:QI (match_dup 4) (match_dup 2))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 10) - (plus:QI (match_dup 2) (const_int -32))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will do a left shift. */ - (parallel [(set (match_dup 9) - (lshiftrt:QI (match_dup 3) (neg:QI (match_dup 10)))) - (clobber (reg:CC 21))]) - (set (match_dup 5) (match_dup 7)) - (parallel [(set (match_dup 6) - (ior:QI (match_dup 8) (match_dup 9))) - (clobber (reg:CC 21))])] - "" - " - operands[3] = operand_subword (operands[1], 0, 1, HImode); /* lo */ - operands[4] = operand_subword (operands[1], 1, 1, HImode); /* hi */ - operands[5] = operand_subword (operands[0], 0, 1, HImode); /* lo */ - operands[6] = operand_subword (operands[0], 1, 1, HImode); /* hi */ - operands[7] = gen_reg_rtx (QImode); /* lo << count */ - operands[8] = gen_reg_rtx (QImode); /* hi << count */ - operands[9] = gen_reg_rtx (QImode); /* lo >> (32 - count) */ - operands[10] = gen_reg_rtx (QImode); /* 32 - count */ - ") - -; This should do all the dirty work with define_split -(define_expand "lshrhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (lshiftrt:HI (match_operand:HI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32) - { - rtx op0hi = operand_subword (operands[0], 1, 0, HImode); - rtx op0lo = operand_subword (operands[0], 0, 0, HImode); - rtx op1hi = operand_subword (operands[1], 1, 0, HImode); - rtx count = GEN_INT ((INTVAL (operands[2]) - 32)); - - if (INTVAL (count)) - emit_insn (gen_lshrqi3 (op0lo, op1hi, count)); - else - emit_insn (gen_movqi (op0lo, op1hi)); - emit_insn (gen_movqi (op0hi, const0_rtx)); - DONE; - } - emit_insn (gen_lshrhi3_reg (operands[0], operands[1], operands[2])); - DONE;") - -; %0.hi = %1.hi >> %2 -; %0.lo = (%1.lo >> %2 ) | (%1.hi << (32 - %2)) -; This algorithm should work for shift counts greater than 32 -(define_expand "lshrhi3_reg" - [(use (match_operand:HI 1 "src_operand" "")) - (use (match_operand:HI 0 "reg_operand" "")) - (parallel [(set (match_dup 11) - (neg:QI (match_operand:QI 2 "reg_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 7) - (lshiftrt:QI (match_dup 3) - (neg:QI (match_dup 11)))) - (clobber (reg:CC 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 8) - (lshiftrt:QI (match_dup 4) - (neg:QI (match_dup 11)))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 10) - (plus:QI (match_dup 11) (const_int 32))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will do an arithmetic - right shift. However, we need a logical right shift. */ - (parallel [(set (match_dup 9) - (ashift:QI (match_dup 4) (unspec [(match_dup 10)] 3))) - (clobber (reg:CC 21))]) - (set (match_dup 6) (match_dup 8)) - (parallel [(set (match_dup 5) - (ior:QI (match_dup 7) (match_dup 9))) - (clobber (reg:CC 21))])] - "" - " - operands[3] = operand_subword (operands[1], 0, 1, HImode); /* lo */ - operands[4] = operand_subword (operands[1], 1, 1, HImode); /* hi */ - operands[5] = operand_subword (operands[0], 0, 1, HImode); /* lo */ - operands[6] = operand_subword (operands[0], 1, 1, HImode); /* hi */ - operands[7] = gen_reg_rtx (QImode); /* lo >> count */ - operands[8] = gen_reg_rtx (QImode); /* hi >> count */ - operands[9] = gen_reg_rtx (QImode); /* hi << (32 - count) */ - operands[10] = gen_reg_rtx (QImode); /* 32 - count */ - operands[11] = gen_reg_rtx (QImode); /* -count */ - ") - -; This should do all the dirty work with define_split -(define_expand "ashrhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (ashiftrt:HI (match_operand:HI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32) - { - rtx op0hi = operand_subword (operands[0], 1, 0, HImode); - rtx op0lo = operand_subword (operands[0], 0, 0, HImode); - rtx op1hi = operand_subword (operands[1], 1, 0, HImode); - rtx count = GEN_INT ((INTVAL (operands[2]) - 32)); - - if (INTVAL (count)) - emit_insn (gen_ashrqi3 (op0lo, op1hi, count)); - else - emit_insn (gen_movqi (op0lo, op1hi)); - emit_insn (gen_ashrqi3 (op0hi, op1hi, GEN_INT (31))); - DONE; - } - emit_insn (gen_ashrhi3_reg (operands[0], operands[1], operands[2])); - DONE;") - -; %0.hi = %1.hi >> %2 -; %0.lo = (%1.lo >> %2 ) | (%1.hi << (32 - %2)) -; This algorithm should work for shift counts greater than 32 -(define_expand "ashrhi3_reg" - [(use (match_operand:HI 1 "src_operand" "")) - (use (match_operand:HI 0 "reg_operand" "")) - (parallel [(set (match_dup 11) - (neg:QI (match_operand:QI 2 "reg_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 7) - (lshiftrt:QI (match_dup 3) - (neg:QI (match_dup 11)))) - (clobber (reg:CC 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 8) - (ashiftrt:QI (match_dup 4) - (neg:QI (match_dup 11)))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 10) - (plus:QI (match_dup 11) (const_int 32))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will do an arithmetic - right shift. */ - (parallel [(set (match_dup 9) - (ashift:QI (match_dup 4) (match_dup 10))) - (clobber (reg:CC 21))]) - (set (match_dup 6) (match_dup 8)) - (parallel [(set (match_dup 5) - (ior:QI (match_dup 7) (match_dup 9))) - (clobber (reg:CC 21))])] - "" - " - operands[3] = operand_subword (operands[1], 0, 1, HImode); /* lo */ - operands[4] = operand_subword (operands[1], 1, 1, HImode); /* hi */ - operands[5] = operand_subword (operands[0], 0, 1, HImode); /* lo */ - operands[6] = operand_subword (operands[0], 1, 1, HImode); /* hi */ - operands[7] = gen_reg_rtx (QImode); /* lo >> count */ - operands[8] = gen_reg_rtx (QImode); /* hi >> count */ - operands[9] = gen_reg_rtx (QImode); /* hi << (32 - count) */ - operands[10] = gen_reg_rtx (QImode); /* 32 - count */ - operands[11] = gen_reg_rtx (QImode); /* -count */ - ") - -(define_expand "cmphi" - [(set (reg:CC 21) - (compare:CC (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" "")))] - "" - "legitimize_operands (COMPARE, operands, HImode); - c4x_compare_op0 = operands[0]; - c4x_compare_op1 = operands[1]; - DONE;") - -; This works only before reload because we need 2 extra registers. -; Use unspec to avoid recursive split. -(define_split - [(set (reg:CC 21) - (compare:CC (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" "")))] - "! reload_completed" - [(parallel [(set (reg:CC 21) - (unspec [(compare:CC (match_dup 0) - (match_dup 1))] 4)) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 ""))])] - "") - -(define_split - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" "")))] - "! reload_completed" - [(parallel [(set (reg:CC_NOOV 21) - (unspec [(compare:CC_NOOV (match_dup 0) - (match_dup 1))] 4)) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 ""))])] - "") - -; This is normally not used. The define splits above are used first. -(define_insn "*cmphi" - [(set (reg:CC 21) - (compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>")))] - "valid_operands (COMPARE, operands, HImode)" - "* - { - int use_ir1 = (reg_operand (operands[0], HImode) - && REG_P (operands[0]) - && REGNO (operands[0]) == IR1_REGNO) - || (reg_operand (operands[1], HImode) - && REG_P (operands[1]) - && REGNO (operands[1]) == IR1_REGNO); - - if (use_ir1) - output_asm_insn (\"push\\tir1\", operands); - else - output_asm_insn (\"push\\tbk\", operands); - output_asm_insn (\"push\\tr0\", operands); - output_asm_insn (\"subi3\\t%1,%0,r0\", operands); - if (use_ir1) - { - output_asm_insn (\"ldiu\\tst,ir1\", operands); - output_asm_insn (\"or\\t07bh,ir1\", operands); - } - else - { - output_asm_insn (\"ldiu\\tst,bk\", operands); - output_asm_insn (\"or\\t07bh,bk\", operands); - } - output_asm_insn (\"subb3\\t%O1,%O0,r0\", operands); - if (use_ir1) - output_asm_insn (\"and3\\tir1,st,ir1\", operands); - else - output_asm_insn (\"and3\\tbk,st,bk\", operands); - output_asm_insn (\"pop\\tr0\", operands); - if (use_ir1) - { - output_asm_insn (\"ldiu\\tir1,st\", operands); - output_asm_insn (\"pop\\tir1\", operands); - } - else - { - output_asm_insn (\"ldiu\\tbk,st\", operands); - output_asm_insn (\"pop\\tbk\", operands); - } - return \"\"; - }" - [(set_attr "type" "multi")]) - -(define_insn "*cmphi_noov" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>")))] - "valid_operands (COMPARE, operands, HImode)" - "* - { - int use_ir1 = (reg_operand (operands[0], HImode) - && REG_P (operands[0]) - && REGNO (operands[0]) == IR1_REGNO) - || (reg_operand (operands[1], HImode) - && REG_P (operands[1]) - && REGNO (operands[1]) == IR1_REGNO); - - if (use_ir1) - output_asm_insn (\"push\\tir1\", operands); - else - output_asm_insn (\"push\\tbk\", operands); - output_asm_insn (\"push\\tr0\", operands); - output_asm_insn (\"subi3\\t%1,%0,r0\", operands); - if (use_ir1) - { - output_asm_insn (\"ldiu\\tst,ir1\", operands); - output_asm_insn (\"or\\t07bh,ir1\", operands); - } - else - { - output_asm_insn (\"ldiu\\tst,bk\", operands); - output_asm_insn (\"or\\t07bh,bk\", operands); - } - output_asm_insn (\"subb3\\t%O1,%O0,r0\", operands); - if (use_ir1) - output_asm_insn (\"and3\\tir1,st,ir1\", operands); - else - output_asm_insn (\"and3\\tbk,st,bk\", operands); - output_asm_insn (\"pop\\tr0\", operands); - if (use_ir1) - { - output_asm_insn (\"ldiu\\tir1,st\", operands); - output_asm_insn (\"pop\\tir1\", operands); - } - else - { - output_asm_insn (\"ldiu\\tbk,st\", operands); - output_asm_insn (\"pop\\tbk\", operands); - } - return \"\"; - }" - [(set_attr "type" "multi")]) - - -(define_insn "cmphi_cc" - [(set (reg:CC 21) - (unspec [(compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>"))] 4)) - (clobber (match_scratch:QI 2 "=&d,&d")) - (clobber (match_scratch:QI 3 "=&c,&c"))] - "valid_operands (COMPARE, operands, HImode)" - "* - output_asm_insn (\"subi3\\t%1,%0,%2\", operands); - output_asm_insn (\"ldiu\\tst,%3\", operands); - output_asm_insn (\"or\\t07bh,%3\", operands); - output_asm_insn (\"subb3\\t%O1,%O0,%2\", operands); - output_asm_insn (\"and\\t%3,st\", operands); - return \"\";" - [(set_attr "type" "multi")]) - -(define_insn "cmphi_cc_noov" - [(set (reg:CC_NOOV 21) - (unspec [(compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>"))] 4)) - (clobber (match_scratch:QI 2 "=&d,&d")) - (clobber (match_scratch:QI 3 "=&c,&c"))] - "valid_operands (COMPARE, operands, HImode)" - "* - output_asm_insn (\"subi3\\t%1,%0,%2\", operands); - output_asm_insn (\"ldiu\\tst,%3\", operands); - output_asm_insn (\"or\\t07bh,%3\", operands); - output_asm_insn (\"subb3\\t%O1,%O0,%2\", operands); - output_asm_insn (\"and\\t%3,st\", operands); - return \"\";" - [(set_attr "type" "multi")]) - -(define_expand "mulhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (mult:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (MULHI3_LIBCALL, MULT, HImode, operands); - DONE;") - -(define_expand "udivhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (udiv:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (UDIVHI3_LIBCALL, UDIV, HImode, operands); - DONE;") - -(define_expand "divhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (div:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (DIVHI3_LIBCALL, DIV, HImode, operands); - DONE;") - -(define_expand "umodhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (umod:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (UMODHI3_LIBCALL, UMOD, HImode, operands); - DONE;") - -(define_expand "modhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (mod:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (MODHI3_LIBCALL, MOD, HImode, operands); - DONE;") - -; -; PEEPHOLES -; - -; dbCC peepholes -; -; Turns -; loop: -; [ ... ] -; bCC label ; abnormal loop termination -; dbu aN, loop ; normal loop termination -; -; Into -; loop: -; [ ... ] -; dbCC aN, loop -; bCC label -; -; Which moves the bCC condition outside the inner loop for free. -; -(define_peephole - [(set (pc) (if_then_else (match_operator 3 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc))) - (parallel - [(set (pc) - (if_then_else - (ge (plus:QI (match_operand:QI 4 "addr_reg_operand" "0") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_operand:QI 0 "addr_reg_operand" "+a") - (plus:QI (match_dup 0) - (const_int -1))) - (clobber (reg:CC_NOOV 21))])] - "! c4x_label_conflict (insn, operands[2], operands[1])" - "db%I3\\t%0,%l1\\n\\tb%3\\t%l2" - [(set_attr "type" "multi")]) - -(define_peephole - [(set (pc) (if_then_else (match_operator 3 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc))) - (parallel - [(set (pc) - (if_then_else - (ne (match_operand:QI 4 "addr_reg_operand" "0") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_operand:QI 0 "addr_reg_operand" "+a") - (plus:QI (match_dup 0) - (const_int -1))) - (clobber (reg:CC_NOOV 21))])] - "! c4x_label_conflict (insn, operands[2], operands[1])" - "db%I3\\t%0,%l1\\n\\tb%3\\t%l2" - [(set_attr "type" "multi")]) - -; -; Peepholes to convert 'call label; rets' into jump label -; -(define_peephole - [(parallel [(call (match_operand:QI 0 "call_operand" "T,!o") - (match_operand:QI 1 "general_operand" "")) - (clobber (reg:QI 31))]) - (return)] - "c4x_null_epilogue_p ()" - "@ - br%#\\t%C0 - bu%#\\t%R0" - [(set_attr "type" "jump,jump")]) - -(define_peephole - [(parallel [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "call_operand" "T,!o") - (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:QI 31))]) - (return)] - "c4x_null_epilogue_p ()" - "@ - br%#\\t%C1 - bu%#\\t%R1" - [(set_attr "type" "jump,jump")]) - -; -; Peepholes for parallel instructions -; -(define_peephole - [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (match_operand:QI 1 "par_ind_operand" "")) - (set (match_operand:QI 2 "ext_low_reg_operand" "") - (match_operand:QI 3 "par_ind_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[2])) - && ! c4x_address_conflict (operands[1], operands[3], 0, 0)" - "ldi1\\t%1,%0\\n||\\tldi2\\t%3,%2") - -; load occurs before store if 1 and 2 point to same address -(define_peephole - [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (match_operand:QI 1 "par_ind_operand" "")) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3])) - && ! c4x_address_conflict (operands[1], operands[2], 0, 1)" - "ldi\\t%1,%0\\n||\\tsti\\t%3,%2") - -; load occurs before store if 0 and 3 point to same address -(define_peephole - [(set (match_operand:QI 0 "par_ind_operand" "") - (match_operand:QI 1 "ext_low_reg_operand" "")) - (set (match_operand:QI 2 "ext_low_reg_operand" "") - (match_operand:QI 3 "par_ind_operand" ""))] - "(REGNO (operands[1]) != REGNO (operands[2])) - && ! c4x_address_conflict (operands[0], operands[3], 1, 0)" - "ldi\\t%3,%2\\n||\\tsti\\t%1,%0") - -(define_peephole - [(set (match_operand:QI 0 "par_ind_operand" "") - (match_operand:QI 1 "ext_low_reg_operand" "")) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "! c4x_address_conflict (operands[0], operands[2], 1, 1)" - "sti\\t%1,%0\\n||\\tsti\\t%3,%2") - -; This peephole should be unnecessary with my patches to flow.c -; for better autoincrement detection -(define_peephole - [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (mem:QF (match_operand:QI 1 "addr_reg_operand" ""))) - (set (match_operand:QF 2 "ext_low_reg_operand" "") - (mem:QF (plus:QI (match_dup 1) (const_int 1)))) - (parallel [(set (match_dup 1) (plus:QI (match_dup 1) (const_int 2))) - (clobber (reg:CC_NOOV 21))])] - "" - "ldf\\t*%1++,%0\\n\\tldf\\t*%1++,%2") - -(define_peephole - [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (match_operand:QF 1 "par_ind_operand" "")) - (set (match_operand:QF 2 "ext_low_reg_operand" "") - (match_operand:QF 3 "par_ind_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[2])) - && ! c4x_address_conflict (operands[1], operands[3], 0, 1)" - "ldf1\\t%1,%0\\n||\\tldf2\\t%3,%2") - -; This peephole should be unnecessary with my patches to flow.c -; for better autoincrement detection -(define_peephole - [(set (mem:QF (match_operand:QI 0 "addr_reg_operand" "")) - (match_operand:QF 1 "ext_low_reg_operand" "")) - (set (mem:QF (plus:QI (match_dup 0) (const_int 1))) - (match_operand:QF 2 "ext_low_reg_operand" "")) - (parallel [(set (match_dup 0) (plus:QI (match_dup 0) (const_int 2))) - (clobber (reg:CC_NOOV 21))])] - "" - "stf\\t%1,*%0++\\n\\tstf\\t%2,*%0++") - -(define_peephole - [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (match_operand:QF 1 "par_ind_operand" "")) - (set (match_operand:QF 2 "par_ind_operand" "") - (match_operand:QF 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "ldf\\t%1,%0\\n||\\tstf\\t%3,%2") - -(define_peephole - [(set (match_operand:QF 0 "par_ind_operand" "") - (match_operand:QF 1 "ext_low_reg_operand" "")) - (set (match_operand:QF 2 "ext_low_reg_operand" "") - (match_operand:QF 3 "par_ind_operand" ""))] - "! c4x_address_conflict (operands[0], operands[3], 1, 1)" - "ldf\\t%3,%2\\n||\\tstf\\t%1,%0") - -(define_peephole - [(set (match_operand:QF 0 "par_ind_operand" "") - (match_operand:QF 1 "ext_low_reg_operand" "")) - (set (match_operand:QF 2 "par_ind_operand" "") - (match_operand:QF 3 "ext_low_reg_operand" ""))] - "! c4x_address_conflict (operands[0], operands[2], 1, 1)" - "stf1\\t%1,%0\\n||\\tstf2\\t%3,%2") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QF (match_operand:QF 1 "par_ind_operand" "")) - (match_operand:QF 2 "fp_zero_operand" ""))) - (set (match_operand:QF 0 "ext_low_reg_operand" "") - (abs:QF (match_dup 1)))]) - (set (match_operand:QF 3 "par_ind_operand" "") - (match_operand:QF 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "absf\\t%1,%0\\n||\\tstf\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (abs:QF (match_operand:QF 1 "par_ind_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QF 2 "par_ind_operand" "") - (match_operand:QF 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "absf\\t%1,%0\\n||\\tstf\\t%3,%2") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QI (match_operand:QI 1 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (abs:QI (match_dup 1)))]) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "absi\\t%1,%0\\n||\\tsti\\t%3,%2") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (abs:QI (match_operand:QI 1 "par_ind_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "absi\\t%1,%0\\n||\\tsti\\t%3,%2") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (plus:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (plus:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (plus:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (plus:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QF (match_operand:QF 1 "ext_low_reg_operand" "") - (match_operand:QF 2 "par_ind_operand" "")) - (match_operand:QF 3 "fp_zero_operand" ""))) - (set (match_operand:QF 0 "ext_low_reg_operand" "") - (plus:QF (match_dup 1) (match_dup 2)))]) - (set (match_operand:QF 4 "par_ind_operand" "") - (match_operand:QF 5 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[5]))" - "addf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QF (match_operand:QF 1 "par_ind_operand" "") - (match_operand:QF 2 "ext_low_reg_operand" "")) - (match_operand:QF 3 "fp_zero_operand" ""))) - (set (match_operand:QF 0 "ext_low_reg_operand" "") - (plus:QF (match_dup 1) (match_dup 2)))]) - (set (match_operand:QF 4 "par_ind_operand" "") - (match_operand:QF 5 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[5]))" - "addf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4") - -(define_peephole - [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (plus:QF (match_operand:QF 1 "ext_low_reg_operand" "") - (match_operand:QF 2 "par_ind_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QF 3 "par_ind_operand" "") - (match_operand:QF 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "addf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (plus:QF (match_operand:QF 1 "par_ind_operand" "") - (match_operand:QF 2 "ext_low_reg_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QF 3 "par_ind_operand" "") - (match_operand:QF 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "addf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC 21) - (compare:CC (and:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (and:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC 21) - (compare:CC (and:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (and:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (and:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (and:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (ashift:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (ashiftrt:QI (match_operand:QI 1 "par_ind_operand" "") - (neg:QI (match_operand:QI 2 "ext_low_reg_operand" "")))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC 21) - (compare:CC (fix:QI (match_operand:QF 1 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (fix:QI (match_dup 1)))]) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "fix\\t%1,%0\\n||\\tsti\\t%3,%2") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (fix:QI (match_operand:QF 1 "par_ind_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "fix\\t%1,%0\\n||\\tsti\\t%3,%2") - -(define_peephole - [(parallel [(set (reg:CC 21) - (compare:CC (float:QF (match_operand:QI 1 "par_ind_operand" "")) - (match_operand:QF 2 "fp_zero_operand" ""))) - (set (match_operand:QF 0 "ext_low_reg_operand" "") - (float:QF (match_dup 1)))]) - (set (match_operand:QF 3 "par_ind_operand" "") - (match_operand:QF 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "float\\t%1,%0\\n||\\tstf\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (float:QF (match_operand:QI 1 "par_ind_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QF 2 "par_ind_operand" "") - (match_operand:QF 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "float\\t%1,%0\\n||\\tstf\\t%3,%2") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (mult:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (mult:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (mult:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (mult:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QF (match_operand:QF 1 "ext_low_reg_operand" "") - (match_operand:QF 2 "par_ind_operand" "")) - (match_operand:QF 3 "fp_zero_operand" ""))) - (set (match_operand:QF 0 "ext_low_reg_operand" "") - (mult:QF (match_dup 1) (match_dup 2)))]) - (set (match_operand:QF 4 "par_ind_operand" "") - (match_operand:QF 5 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[5]))" - "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QF (match_operand:QF 1 "par_ind_operand" "") - (match_operand:QF 2 "ext_low_reg_operand" "")) - (match_operand:QF 3 "fp_zero_operand" ""))) - (set (match_operand:QF 0 "ext_low_reg_operand" "") - (mult:QF (match_dup 1) (match_dup 2)))]) - (set (match_operand:QF 4 "par_ind_operand" "") - (match_operand:QF 5 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[5]))" - "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4") - -(define_peephole - [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (mult:QF (match_operand:QF 1 "ext_low_reg_operand" "") - (match_operand:QF 2 "par_ind_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QF 3 "par_ind_operand" "") - (match_operand:QF 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (mult:QF (match_operand:QF 1 "par_ind_operand" "") - (match_operand:QF 2 "ext_low_reg_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QF 3 "par_ind_operand" "") - (match_operand:QF 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QF (match_operand:QF 1 "par_ind_operand" "")) - (match_operand:QF 2 "fp_zero_operand" ""))) - (set (match_operand:QF 0 "ext_low_reg_operand" "") - (neg:QF (match_dup 1)))]) - (set (match_operand:QF 3 "par_ind_operand" "") - (match_operand:QF 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "negf\\t%1,%0\\n||\\tstf\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (neg:QF (match_operand:QF 1 "par_ind_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QF 2 "par_ind_operand" "") - (match_operand:QF 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "negf\\t%1,%0\\n||\\tstf\\t%3,%2") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_operand:QI 1 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (neg:QI (match_dup 1)))]) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "negi\\t%1,%0\\n||\\tsti\\t%3,%2") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (neg:QI (match_operand:QI 1 "par_ind_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "negi\\t%1,%0\\n||\\tsti\\t%3,%2") - -(define_peephole - [(parallel [(set (reg:CC 21) - (compare:CC (not:QI (match_operand:QI 1 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (not:QI (match_dup 1)))]) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "not\\t%1,%0\\n||\\tsti\\t%3,%2") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (not:QI (match_operand:QI 1 "par_ind_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 2 "par_ind_operand" "") - (match_operand:QI 3 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[3]))" - "not\\t%1,%0\\n||\\tsti\\t%3,%2") - -(define_peephole - [(parallel [(set (reg:CC 21) - (compare:CC (ior:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (ior:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC 21) - (compare:CC (ior:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (ior:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (ior:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (ior:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (minus:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "subi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (minus:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "subi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QF (match_operand:QF 1 "ext_low_reg_operand" "") - (match_operand:QF 2 "par_ind_operand" "")) - (match_operand:QF 3 "fp_zero_operand" ""))) - (set (match_operand:QF 0 "ext_low_reg_operand" "") - (minus:QF (match_dup 1) (match_dup 2)))]) - (set (match_operand:QF 4 "par_ind_operand" "") - (match_operand:QF 5 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[5]))" - "subf3\\t%2,%1,%0\\n||\\tstf\\t%5,%4") - -(define_peephole - [(parallel [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (minus:QF (match_operand:QF 1 "ext_low_reg_operand" "") - (match_operand:QF 2 "par_ind_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QF 3 "par_ind_operand" "") - (match_operand:QF 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "subf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC 21) - (compare:CC (xor:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (xor:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (reg:CC 21) - (compare:CC (xor:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_low_reg_operand" "") - (xor:QI (match_dup 1) (match_dup 2)))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (xor:QI (match_operand:QI 1 "ext_low_reg_operand" "") - (match_operand:QI 2 "par_ind_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_low_reg_operand" "") - (xor:QI (match_operand:QI 1 "par_ind_operand" "") - (match_operand:QI 2 "ext_low_reg_operand" ""))) - (clobber (reg:CC 21))]) - (set (match_operand:QI 3 "par_ind_operand" "") - (match_operand:QI 4 "ext_low_reg_operand" ""))] - "(REGNO (operands[0]) != REGNO (operands[4]))" - "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3") - - diff --git a/gcc/config/c4x/libgcc.S b/gcc/config/c4x/libgcc.S deleted file mode 100755 index fb79cf8..0000000 --- a/gcc/config/c4x/libgcc.S +++ /dev/null @@ -1,1501 +0,0 @@ -/* libgcc1 routines for the Texas Instruments TMS320C[34]x - Copyright (C) 1997,98 Free Software Foundation, Inc. - - Contributed by Michael Hayes (m.hayes@elec.canterbury.cri.nz) - and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl). - - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -In addition to the permissions in the GNU General Public License, the -Free Software Foundation gives you unlimited permission to link the -compiled version of this file 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, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, 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 routines are called using the standard TI register argument -; passing model. -; The following registers do not have to be saved: -; r0, r1, r2, r3, ar0, ar1, ar2, ir0, ir1, bk, rs, rc, re, (r9, r10, r11) -; -; Perform floating point divqf3 -; -; This routine performs a reciprocal of the divisor using the method -; described in the C30/C40 user manuals. It then multiplies that -; result by the dividend. -; -; Let r be the reciprocal of the divisor v and let the ith estimate -; of r be denoted by r[i]. An iterative approach can be used to -; improve the estimate of r, given an initial estimate r[0], where -; -; r[i + 1] = r[i] * (2.0 - v * r[i]) -; -; The normalised error e[i] at the ith iteration is -; -; e[i] = (r - r[i]) / r = (1 / v - r[i]) * v = (1 - v * r[i]) -; -; Note that -; -; e[i + 1] = (1 - v * r[i + 1]) = 1 - 2 * v * r[i] + v^2 + (r[i])^2 -; = (1 - v * r[i])^2 = (e[i])^2 - -; r2 dividend, r3 divisor, r0 quotient -; clobbers r1, ar1 -#ifdef L_divqf3 - .text - .global ___divqf3 -___divqf3: - -#ifdef _TMS320C4x - .if .REGPARM == 0 - lda sp,ar0 - ldf *-ar0(2), r3 - .endif - - pop ar1 ; Pop return address - -; r0 = estimate of r, r1 = tmp, r2 = dividend, r3 = divisor - rcpf r3, r0 ; Compute initial estimate r[0] - - mpyf3 r0, r3, r1 ; r1 = r[0] * v - subrf 2.0, r1 ; r1 = 2.0 - r[0] * v - mpyf r1, r0 ; r0 = r[0] * (2.0 - r[0] * v) = r[1] -; End of 1st iteration (16 bits accuracy) - - mpyf3 r0, r3, r1 ; r1 = r[1] * v - subrf 2.0, r1 ; r1 = 2.0 - r[1] * v - - bud ar1 ; Delayed branch - mpyf r1, r0 ; r0 = r[1] * (2.0 - r[1] * v) = r[2] -; End of 2nd iteration (32 bits accuracy) - .if .REGPARM == 0 - mpyf *-ar0(1), r0 ; Multiply by the dividend - .else - mpyf r2, r0 ; Multiply by the dividend - .endif - rnd r0 - ; Branch occurs here -#else - .if .REGPARM == 0 - ldiu sp,ar0 - ldf *-ar0(2), r3 - .endif - - pop ar1 ; Pop return address - -; Initial estimate r[0] = 1.0 * 2^(-e - 1) -; where v = m * 2^e - -; r0 = estimate of r, r1 = tmp, r2 = dividend, r3 = divisor - -; Calculate initial estimate r[0] - pushf r3 - pop r0 - not r0 ; r0 = -e - ; complement exponent = -e -1 - ; complement sign (side effect) - ; complement mantissa (almost 3 bit accurate) - push r0 - popf r0 ; r0 = 1.0 * e^(-e - 1) + inverted mantissa - ldf -1.0, r1 ; undo complement sign bit - xor r1, r0 - - mpyf3 r0, r3, r1 ; r1 = r[0] * v - subrf 2.0, r1 ; r1 = 2.0 - r[0] * v - mpyf r1, r0 ; r0 = r[0] * (2.0 - r[0] * v) = r[1] -; End of 1st iteration - - mpyf3 r0, r3, r1 ; r1 = r[1] * v - subrf 2.0, r1 ; r1 = 2.0 - r[1] * v - mpyf r1, r0 ; r0 = r[1] * (2.0 - r[1] * v) = r[2] -; End of 2nd iteration - - mpyf3 r0, r3, r1 ; r1 = r[2] * v - subrf 2.0, r1 ; r1 = 2.0 - r[2] * v - mpyf r1, r0 ; r0 = r[2] * (2.0 - r[2] * v) = r[3] -; End of 3rd iteration - - or 080h, r0 ; add 1 lsb to result. needed when complemeting - ; 1.0 / 2.0 - rnd r0 - -; Use modified last iteration -; r[4] = (r[3] * (1.0 - (v * r[3]))) + r[3] - mpyf3 r0, r3, r1 ; r1 = r[3] * v - subrf 1.0, r1 ; r1 = 1.0 - r[3] * v - mpyf r0, r1 ; r1 = r[3] * (1.0 - r[3] * v) - - bud ar1 ; Delayed branch - addf r1, r0 ; r0 = r[3] * (1.0 - r[3] * v) + r[3] = r[4] - .if .REGPARM == 0 - mpyf *-ar0(1), r0 ; Multiply by the dividend - .else - mpyf r2, r0 ; Multiply by the dividend - .endif - rnd r0 - ; Branch occurs here -#endif - -#endif -; -; Integer signed division -; -; ar2 dividend, r2 divisor, r0 quotient -; clobbers r1, r3, ar0, ar1, ir0, ir1, rc, rs, re -#ifdef L_divqi3 - .text - .global ___divqi3 - .ref udivqi3n -___divqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - - xor3 ar2, r2, r3 ; Get the sign - absi ar2, r0 - bvd divq32 - ldi r0, ar2 - absi r2, r2 - cmpi ar2, r2 ; Divisor > dividend? - - pop ir1 - bhid zero ; If so, return 0 - -; -; Normalize oeprands. Use difference exponents as shift count -; for divisor, and as repeat count for "subc" -; - float ar2, r1 ; Normalize dividend - pushf r1 ; Get as integer - pop ar0 - lsh -24, ar0 ; Get exponent - - float r2, r1 ; Normalize divisor - pushf r1 ; Get as integer - pop ir0 - lsh -24, ir0 ; Get exponent - - subi ir0, ar0 ; Get difference of exponents - lsh ar0, r2 ; Align divisor with dividend - -; -; Do count + 1 subtracts and shifts -; - rpts ar0 - subc r2, ar2 - -; -; Mask off the lower count+1 bits of ar2 -; - subri 31, ar0 ; Shift count is (32 - (ar0 + 1)) - lsh ar0, ar2 ; Shift left - negi ar0, ar0 - lsh3 ar0, ar2, r0 ; Shift right and put result in r0 - -; -; Check sign and negate result if necessary -; - bud ir1 ; Delayed return - negi r0, r1 ; Negate result - ash -31, r3 ; Check sign - ldinz r1, r0 ; If set, use negative result - ; Branch occurs here - -zero: bud ir1 ; Delayed branch - ldi 0, r0 - nop - nop - ; Branch occurs here -; -; special case where ar2 = abs(ar2) = 0x80000000. We handle this by -; calling unsigned divide and negating the result if necessary. -; -divq32: - push r3 ; Save sign - call udivqi3n - pop r3 - pop ir1 - bd ir1 - negi r0, r1 ; Negate result - ash -31, r3 ; Check sign - ldinz r1, r0 ; If set, use negative result - ; Branch occurs here -#endif -; -; -; ar2 dividend, r2 divisor, r0 quotient, -; clobbers r1, r3, ar0, ar1, ir0, ir1, rc, rs, re -#ifdef L_udivqi3 - .text - .global ___udivqi3 - .global udivqi3n -___udivqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - -udivqi3n: - pop ir1 - - cmpi ar2, r2 ; If divisor > dividend - bhi qzero ; return zero - ldi r2, ar1 ; Store divisor in ar1 - - tstb ar2, ar2 ; Check top bit, jump if set to special handler - bld div_32 ; Delayed branch - -; -; Get divisor exponent -; - float ar1, r1 ; Normalize the divisor - pushf r1 ; Get into int register - pop rc - ; branch occurs here - - bzd qzero ; if (float) divisor zero, return zero - - float ar2, r1 ; Normalize the dividend - pushf r1 ; Get into int register - pop ar0 - lsh -24, ar0 ; Get both the exponents - lsh -24, rc - - subi rc, ar0 ; Get the difference between the exponents - lsh ar0, ar1 ; Normalize the divisor with the dividend - -; -; Do count_1 subtracts and shifts -; - rpts ar0 - subc ar1, ar2 - -; -; mask off the lower count+1 bits -; - subri 31, ar0 ; Shift count (31 - (ar0+1)) - bud ir1 ; Delayed return - lsh3 ar0, ar2, r0 - negi ar0, ar0 - lsh ar0, r0 - ; Branch occurs here - -; -; Handle a full 32-bit dividend -; -div_32: tstb ar1, ar1 - bld qone ; if divisor high bit is one, the result is one - lsh -24, rc - subri 31, rc - lsh rc, ar1 ; Line up the divisor - -; -; Now divisor and dividend are aligned. Do first SUBC by hand, save -; of the forst quotient digit. Then, shift divisor right rather -; than shifting dividend left. This leaves a zero in the top bit of -; the divident -; - ldi 1, ar0 ; Initizialize MSB of quotient - lsh rc, ar0 ; create a mask for MSBs - subi 1, ar0 ; mask is (2 << count) - 1 - - subi3 ar1, ar2, r1 - ldihs r1, ar2 - ldihs 1, r1 - ldilo 0, r1 - lsh rc, r1 - - lsh -1, ar1 - subi 1, rc -; -; do the rest of the shifts and subtracts -; - rpts rc - subc ar1, ar2 - - bud ir1 - and ar0, ar2 - or3 r1, ar2, r0 - nop - -qone: - bud ir1 - ldi 1, r0 - nop - nop - -qzero: - bud ir1 - ldi 0, r0 - nop - nop -#endif - -#ifdef L_umodqi3 - .text - .global ___umodqi3 - .global umodqi3n -___umodqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - -umodqi3n: - pop ir1 ; return address - cmpi ar2, r2 ; divisor > dividend ? - bhi uzero ; if so, return dividend - ldi r2, ar1 ; load divisor -; -; If top bit of dividend is set, handle specially. -; - tstb ar2, ar2 ; check top bit - bld umod_32 ; get divisor exponent, then jump. -; -; Get divisor exponent by converting to float. -; - float ar1, r1 ; normalize divisor - pushf r1 ; push as float - pop rc ; pop as int to get exponent - bzd uzero ; if (float)divisor was zero, return -; -; 31 or less bits in dividend. Get dividend exponent. -; - float ar2, r1 ; normalize dividend - pushf r1 ; push as float - pop ar0 ; pop as int to get exponent -; -; Use difference in exponents as shift count to line up MSBs. -; - lsh -24, rc ; divisor exponent - lsh -24, ar0 ; dividend exponent - subi rc, ar0 ; difference - lsh ar0, ar1 ; shift divisor up -; -; Do COUNT+1 subtract & shifts. -; - rpts ar0 - subc ar1, ar2 -; -; Remainder is in upper 31-COUNT bits. -; - bud ir1 ; delayed branch to return - addi 1, ar0 ; shift count is COUNT+1 - negi ar0, ar0 ; negate for right shift - lsh3 ar0, ar2, r0 ; shift to get result - ; Return occurs here - -; -; The following code handles cases of a full 32-bit dividend. Before -; SUBC can be used, the top bit must be cleared (otherwise SUBC can -; possibly shift a significant 1 out the top of the dividend). This -; is accomplished by first doing a normal subtraction, then proceeding -; with SUBCs. -; -umod_32: -; -; If the top bit of the divisor is set too, the remainder is simply -; the difference between the dividend and divisor. Otherwise, shift -; the divisor up to line up the MSBs. -; - tstb ar1, ar1 ; check divisor - bld uone ; if negative, remainder is diff - - lsh -24, rc ; divisor exponent - subri 31, rc ; shift count = 31 - exp - negi rc, ar0 ; used later as shift count - lsh rc, ar1 ; shift up to line up MSBs -; -; Now MSBs are aligned. Do first SUBC by hand using a plain subtraction. -; Then, shift divisor right rather than shifting dividend left. This leaves -; a 0 in the top bit of the dividend. -; - subi3 ar1, ar2, r1 ; subtract - ldihs r1, ar2 ; if positive, replace dividend - subi 1, rc ; first iteration is done - lsh -1, ar1 ; shift divisor down -; -; Do EXP subtract & shifts. -; - rpts rc - subc ar1, ar2 -; -; Quotient is in EXP+1 LSBs; shift remainder (in MSBs) down. -; - bud ir1 - lsh3 ar0, ar2, r0 ; COUNT contains -(EXP+1) - nop - nop -; -; Return (dividend - divisor). -; -uone: bud ir1 - subi3 r2, ar2, r0 - nop - nop -; -; Return dividend. -; -uzero: bud ir1 - ldi ar2, r0 ; set status from result - nop - nop -#endif - -#ifdef L_modqi3 - .text - .global ___modqi3 - .ref umodqi3n -___modqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - -; -; Determine sign of result. Get absolute value of operands. -; - ldi ar2, ar0 ; sign of result same as dividend - absi ar2, r0 ; make dividend positive - bvd mod_32 ; if still negative, escape - absi r2, r1 ; make divisor positive - ldi r1, ar1 ; save in ar1 - cmpi r0, ar1 ; divisor > dividend ? - - pop ir1 ; return address - bhid return ; if so, return dividend -; -; Normalize operands. Use difference in exponents as shift count -; for divisor, and as repeat count for SUBC. -; - float r1, r1 ; normalize divisor - pushf r1 ; push as float - pop rc ; pop as int - bzd return ; if (float)divisor was zero, return - - float r0, r1 ; normalize dividend - pushf r1 ; push as float - pop r1 ; pop as int - - lsh -24, rc ; get divisor exponent - lsh -24, r1 ; get dividend exponent - subi rc, r1 ; get difference in exponents - lsh r1, ar1 ; align divisor with dividend -; -; Do COUNT+1 subtract & shifts. -; - rpts r1 - subc ar1, r0 -; -; Remainder is in upper bits of R0 -; - addi 1, r1 ; shift count is -(r1+1) - negi r1, r1 - lsh r1, r0 ; shift right -; -; Check sign and negate result if necessary. -; -return: - bud ir1 ; delayed branch to return - negi r0, r1 ; negate result - cmpi 0, ar0 ; check sign - ldin r1, r0 ; if set, use negative result - ; Return occurs here -; -; The following code handles cases of a full 32-bit dividend. This occurs -; when R0 = abs(R0) = 080000000h. Handle this by calling the unsigned mod -; function, then negating the result if necessary. -; -mod_32: - push ar0 ; remember sign - call umodqi3n ; do divide - - brd return ; return - pop ar0 ; restore sign - pop ir1 ; return address - nop -#endif - -#ifdef L_unsfltconst - .section .const - .global ___unsfltconst -___unsfltconst: .float 4294967296.0 -#endif - -#ifdef L_unsfltcompare - .section .const - .global ___unsfltcompare -___unsfltcompare: .float 2147483648.0 -#endif - -; Integer 32-bit signed multiplication -; -; The TMS320C3x MPYI instruction takes two 24-bit signed integers -; and produces a 48-bit signed result which is truncated to 32-bits. -; -; A 32-bit by 32-bit multiplication thus requires a number of steps. -; -; Consider the product of two 32-bit signed integers, -; -; z = x * y -; -; where x = (b << 16) + a, y = (d << 16) + c -; -; This can be expressed as -; -; z = ((b << 16) + a) * ((d << 16) + c) -; -; = ((b * d) << 32) + ((b * c + a * d) << 16) + a * c -; -; Let z = (f << 16) + e where f < (1 << 16). -; -; Since we are only interested in a 32-bit result, we can ignore the -; (b * d) << 32 term, and thus -; -; f = b * c + a * d, e = a * c -; -; We can simplify things if we have some a priori knowledge of the -; operands, for example, if -32768 <= y <= 32767, then y = c and d = 0 and thus -; -; f = b * c, e = a * c -; -; ar2 multiplier, r2 multiplicand, r0 product -; clobbers r1, r2, r3 -#ifdef L_mulqi3 - .text - .global ___mulqi3 -___mulqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - - pop ir1 ; return address - ldi ar2, r0 ; - and 0ffffh, r0 ; a - lsh -16, ar2 ; b - ldi r2, r3 ; - and 0ffffh, r3 ; c - mpyi r3, ar2 ; c * b - lsh -16, r2 ; d - mpyi r0, r2 ; a * d - addi ar2, r2 ; c * b + a * d - bd ir1 ; delayed branch to return - lsh 16, r2 ; (c * b + a * d) << 16 - mpyi r3, r0 ; a * c - addi r2, r0 ; a * c + (c * b + a * d) << 16 -; branch occurs here - -#endif - -; -; Integer 64 by 64 multiply -; long1 and long2 on stack -; result in r0,r1 -; -#ifdef L_mulhi3 - .text - .global ___mulhi3 -#ifdef _TMS320C4x -___mulhi3: - pop ar0 - ldi sp,ar2 - ldi *-ar2(1),r2 - ldi *-ar2(3),r3 - mpyi3 r2,r3,r0 - mpyuhi3 r2,r3,r1 - mpyi *-ar2(2),r2 - bd ar0 - mpyi *-ar2(0),r3 - addi r2,r1 - addi r3,r1 -#else -___mulhi3: - ldi sp,ar2 - ldi -16,rs - ldi *-ar2(2),ar0 - ldi *-ar2(4),ar1 - ldi ar0,r2 - and 0ffffh,r2 - ldi ar1,r3 - and 0ffffh,r3 - lsh rs,ar0 - lsh rs,ar1 - - mpyi r2,r3,r0 - mpyi ar0,ar1,r1 - mpyi r2,ar1,rc - lsh rs,rc,re - addi re,r1 - lsh 16,rc - addi rc,r0 - addc 0,r1 - mpyi r3,ar0,rc - lsh rs,rc,re - addi re,r1 - lsh 16,rc - addi rc,r0 - addc 0,r1 - - ldi *-ar2(1),ar0 - ldi ar0,r2 - and 0ffffh,r2 - lsh rs,ar0 - mpyi r2,r3,rc - addi rc,r1 - mpyi r2,ar1,rc - mpyi r3,ar0,re - addi re,rc - lsh 16,rc - addi rc,r1 - - ldi *-ar2(2),ar0 - ldi *-ar2(3),ar1 - ldi ar0,r2 - and 0ffffh,r2 - ldi ar1,r3 - and 0ffffh,r3 - lsh rs,ar0 - lsh rs,ar1 - mpyi r2,r3,rc - addi rc,r1 - mpyi r2,ar1,rc - mpyi r3,ar0,re - pop ar0 - bd ar0 - addi re,rc - lsh 16,rc - addi rc,r1 -#endif -#endif - -; -; Integer 32 by 32 multiply highpart unsigned -; src1 in ar2 -; src2 in r2 -; result in r0 -; -#ifdef L_umulhi3_high - .text - .global ___umulhi3_high -___umulhi3_high: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - - ldi -16,rs - ldi r2,r3 - and 0ffffh,r2 - ldi ar2,ar1 - and 0ffffh,ar2 - lsh rs,r3 - lsh rs,ar1 - - mpyi ar2,r2,r1 - mpyi ar1,r3,r0 - mpyi ar2,r3,rc - lsh rs,rc,re - addi re,r0 - lsh 16,rc - addi rc,r1 - addc 0,r0 - mpyi r2,ar1,rc - lsh rs,rc,re - addi re,r0 - pop ar0 - bd ar0 - lsh 16,rc - addi rc,r1 - addc 0,r0 -#endif - -; -; Integer 32 by 32 multiply highpart signed -; src1 in ar2 -; src2 in r2 -; result in r0 -; -#ifdef L_smulhi3_high - .text - .global ___smulhi3_high -___smulhi3_high: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - - ldi -16,rs - ldi 0,rc - subi3 ar2,rc,r0 - ldi r2,r3 - ldilt r0,rc - subi3 r2,rc,r0 - ldi ar2,ar1 - tstb ar1,ar1 - ldilt r0,rc - and 0ffffh,r2 - and 0ffffh,ar2 - lsh rs,r3 - lsh rs,ar1 - - mpyi ar2,r2,r1 - mpyi ar1,r3,r0 - addi rc,r0 - mpyi ar2,r3,rc - lsh rs,rc,re - addi re,r0 - lsh 16,rc - addi rc,r1 - addc 0,r0 - mpyi r2,ar1,rc - lsh rs,rc,re - addi re,r0 - pop ar0 - bd ar0 - lsh 16,rc - addi rc,r1 - addc 0,r0 -#endif - -; -; Integer 64 by 64 unsigned divide -; long1 and long2 on stack -; divide in r0,r1 -; modulo in r2,r3 -; routine takes a maximum of 64*9+21=597 cycles = 24 us @ 50Mhz -; -#ifdef L_udivhi3 - .text - .global ___udivhi3 - .global ___udivide - .global ___umodulo - .ref udivqi3n - .ref umodqi3n -___udivhi3: - ldi sp,ar2 - ldi *-ar2(4),ar0 - ldi *-ar2(3),ar1 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - -___udivide: - or r1,ar1,r2 - bne udiv0 - ldi ar0,r2 - ldi r0,ar2 - call udivqi3n - ldiu 0,r1 - rets - -___umodulo: - or r1,ar1,r2 - bne udiv0 - ldi ar0,r2 - ldi r0,ar2 - call umodqi3n - ldi r0,r2 - ldiu 0,r3 - rets - -udiv0: - tstb ar1,ar1 - bne udiv1 - tstb ar0,ar0 - bn udiv1 - - ldiu 63,rc -#ifdef _TMS320C4x - rptbd udivend0 - ldiu 0,r2 - addi r0,r0 - rolc r1 -#else - ldiu 0,r2 - addi r0,r0 - rolc r1 - rptb udivend0 -#endif - - rolc r2 - subi3 ar0,r2,r3 - xor 1,st - ldic r3,r2 - rolc r0 -udivend0: - rolc r1 - - ldiu 0,r3 - rets -udiv1: - push r4 - push r5 - ldiu 63,rc - ldiu 0,r2 -#ifdef _TMS320C4x - rptbd udivend1 - ldiu 0,r3 - addi r0,r0 - rolc r1 -#else - ldiu 0,r3 - addi r0,r0 - rolc r1 - rptb udivend1 -#endif - - rolc r2 - rolc r3 - subi3 ar0,r2,r4 - subb3 ar1,r3,r5 - xor 1,st - ldic r4,r2 - ldic r5,r3 - rolc r0 -udivend1: - rolc r1 - - pop r5 - pop r4 - rets -#endif - -; -; Integer 64 by 64 unsigned modulo -; long1 and long2 on stack -; result in r0,r1 -; -#ifdef L_umodhi3 - .text - .global ___umodhi3 - .ref ___modulo -___umodhi3: - ldi sp,ar2 - ldi *-ar2(4),ar0 - ldi *-ar2(3),ar1 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - call ___umodulo - pop ar0 - bd ar0 - ldi r2,r0 - ldi r3,r1 - nop -#endif - -; -; Integer 64 by 64 signed divide -; long1 and long2 on stack -; result in r0,r1 -; -#ifdef L_divhi3 - .text - .global ___divhi3 - .ref ___udivide -___divhi3: - ldi 0,ir0 - ldi sp,ar2 - ldi *-ar2(4),r0 - ldi *-ar2(3),r1 - bge div1 - negi ir0 - negi r0 - negb r1 -div1: - ldi r0,ar0 - ldi r1,ar1 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - bge div2 - negi ir0 - negi r0 - negb r1 -div2: - call ___udivide - tstb ir0,ir0 - bge div3 - negi r0 - negb r1 -div3: - rets -#endif - -; -; Integer 64 by 64 signed modulo -; long1 and long2 on stack -; result in r0,r1 -; -#ifdef L_modhi3 - .text - .global ___modhi3 - .ref ___umodulo -___modhi3: - ldi 0,ir0 - ldi sp,ar2 - ldi *-ar2(4),r0 - ldi *-ar2(3),r1 - bge mod1 - negi ir0 - negi r0 - negb r1 -mod1: - ldi r0,ar0 - ldi r1,ar1 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - bge mod2 - negi ir0 - negi r0 - negb r1 -mod2: - call ___umodulo - ldi r2,r0 - ldi r3,r1 - tstb ir0,ir0 - bge mod3 - negi r0 - negb r1 -mod3: - rets -#endif - -; -; double to signed long long converion -; input in r2 -; result in r0,r1 -; -#ifdef L_fix_truncqfhi2 - .text - .global ___fix_truncqfhi2 - .ref ufix_truncqfhi2n -___fix_truncqfhi2: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(1), r2 - .endif - - cmpf 0.0,r2 - bge ufix_truncqfhi2n - negf r2 - call ufix_truncqfhi2n - negi r0 - negb r1 - rets -#endif - -; -; double to unsigned long long converion -; input in r2 -; result in r0,r1 -; -#ifdef L_ufix_truncqfhi2 - .text - .global ___ufix_truncqfhi2 - .global ufix_truncqfhi2n -___ufix_truncqfhi2: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(1), r2 - .endif - -ufix_truncqfhi2n: - cmpf 0.0,r2 - ble ufix1 - pushf r2 - pop r3 - ash -24,r3 - subi 31,r3 - cmpi 32,r3 - bge ufix1 - cmpi -32,r3 - ble ufix1 - ldi 1,r0 - ash 31,r0 - or3 r0,r2,r0 - ldi r0,r1 - lsh3 r3,r0,r0 - subi 32,r3 - cmpi -32,r3 - ldile 0,r1 - lsh3 r3,r1,r1 - rets -ufix1: - ldi 0,r0 - ldi 0,r1 - rets -#endif - -; -; signed long long to double converion -; input on stack -; result in r0 -; -#ifdef L_floathiqf2 - .text - .global ___floathiqf2 - .ref ufloathiqf2n -___floathiqf2: - ldi sp,ar2 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - bge ufloathiqf2n - negi r0 - negb r1 - call ufloathiqf2n - negf r0 - rets -#endif - -; -; unsigned long long to double converion -; input on stack -; result in r0 -; -#ifdef L_ufloathiqf2 - .text - .global ___ufloathiqf2 - .global ufloathiqf2n - .ref ___unsfltconst -___ufloathiqf2: - ldi sp,ar2 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 -ufloathiqf2n: - .if .BIGMODEL -#ifdef _TMS320C4x - ldpk @___unsfltconst -#else - ldp @___unsfltconst -#endif - .endif - ldf @___unsfltconst,r2 - float r0 - bge uflt1 - addf r2,r0 -uflt1: - float r1 - bge uflt2 - addf r2,r1 -uflt2: -#ifdef _TMS320C4x - pop r3 - bd r3 - mpyf r2,r1 - addf r1,r0 - nop -#else - ldf r1,r3 - and 0ffh,r3 - norm r3,r3 - mpyf r2,r3 - pop ar2 - bd ar2 - addf r3,r0 - mpyf r2,r1 - addf r1,r0 -#endif -#endif - -; -; long double to signed long long converion -; input in r2 -; result in r0,r1 -; -#ifdef L_fix_trunchfhi2 - .text - .global ___fix_trunchfhi2 - .ref ufix_trunchfhi2n -___fix_trunchfhi2: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(2), r2 - ldi *-ar0(1), r2 - .endif - - cmpf 0.0,r2 - bge ufix_trunchfhi2n - negf r2 - call ufix_trunchfhi2n - negi r0 - negb r1 - rets -#endif - -; -; long double to unsigned long long converion -; input in r2 -; result in r0,r1 -; -#ifdef L_ufix_trunchfhi2 - .text - .global ___ufix_trunchfhi2 - .global ufix_trunchfhi2n -___ufix_trunchfhi2: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(2), r2 - ldi *-ar0(1), r2 - .endif - -ufix_trunchfhi2n: - cmpf 0.0,r2 - ble ufixh1 - pushf r2 - pop r3 - ash -24,r3 - subi 31,r3 - cmpi 32,r3 - bge ufixh1 - cmpi -32,r3 - ble ufixh1 - ldi 1,r0 - ash 31,r0 - or3 r0,r2,r0 - ldi r0,r1 - lsh3 r3,r0,r0 - subi 32,r3 - cmpi -32,r3 - ldile 0,r1 - lsh3 r3,r1,r1 - rets -ufixh1: - ldi 0,r0 - ldi 0,r1 - rets -#endif - -; -; signed long long to long double converion -; input on stack -; result in r0 -; -#ifdef L_floathihf2 - .text - .global ___floathihf2 - .ref ufloathihf2n -___floathihf2: - ldi sp,ar2 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - bge ufloathihf2n - negi r0 - negb r1 - call ufloathihf2n - negf r0 - rets -#endif - -; -; unsigned long long to double converion -; input on stack -; result in r0 -; -#ifdef L_ufloathihf2 - .text - .global ___ufloathihf2 - .global ufloathihf2n - .ref ___unsfltconst -___ufloathihf2: - ldi sp,ar2 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 -ufloathihf2n - .if .BIGMODEL -#ifdef _TMS320C4x - ldpk @___unsfltconst -#else - ldp @___unsfltconst -#endif - .endif - ldf @___unsfltconst,r2 - float r0 - bge uflth1 - addf r2,r0 -uflth1: - float r1 - bge uflth2 - addf r2,r1 -uflth2: -#ifdef _TMS320C4x - pop r3 - bd r3 - mpyf r2,r1 - addf r1,r0 - nop -#else - ldf r1,r3 - and 0ffh,r3 - norm r3,r3 - mpyf r2,r3 - pop ar2 - bd ar2 - addf r3,r0 - mpyf r2,r1 - addf r1,r0 -#endif -#endif - -; -; calculate ffs -; input in ar2 -; result in r0 -; -#ifdef L_ffs - .global ___ffs - .ref ___unsfltconst - .text -___ffs: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - .endif - - negi ar2,r0 - and ar2,r0 - float r0,r0 - ldfu 0.0,r1 - .if .BIGMODEL -#ifdef _TMS320C4x - ldpk @___unsfltconst -#else - ldp @___unsfltconst -#endif - .endif - ldflt @___unsfltconst,r1 - addf r1,r0 - pushf r0 - pop r0 - pop ar0 - bd ar0 - ash -24,r0 - ldilt -1,r0 - addi 1,r0 -#endif - -; -; calculate long double * long double -; input in r2, r3 -; output in r0 -; -#ifdef L_mulhf3 - .global ___mulhf3 - .text -___mulhf3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(2), r2 - ldi *-ar0(1), r2 - ldf *-ar0(4), r3 - ldi *-ar0(3), r3 - .endif - - pop ar2 ; return ad - ldf r2,r0 ; copy lsb0 - ldf r3,r1 ; copy lsb1 - and 0ffh,r0 ; mask lsb0 - and 0ffh,r1 ; mask lsb1 - norm r0,r0 ; correct lsb0 - norm r1,r1 ; correct lsb1 - mpyf r2,r1 ; arg0*lsb1 - mpyf r3,r0 ; arg1*lsb0 - bd ar2 ; return (delayed) - addf r0,r1 ; arg0*lsb1 + arg1*lsb0 - mpyf r2,r3,r0 ; msb0*msb1 - addf r1,r0 ; msb0*msb1 + arg0*lsb1 + arg1*lsb0 -#endif - -; -; calculate long double / long double -; r2 dividend, r3 divisor, r0 quotient -; -#ifdef L_divhf3 - .global ___divhf3 - .text -___divhf3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(2), r2 - ldi *-ar0(1), r2 - ldf *-ar0(4), r3 - ldi *-ar0(3), r3 - .endif - -#ifdef _TMS320C4x - pop ar1 - rcpf r3, r0 - mpyf3 r0, r3, r1 - subrf 2.0, r1 - mpyf r1, r0 - mpyf3 r0, r3, r1 - bud ar1 - subrf 2.0, r1 - mpyf r1, r0 - mpyf r2, r0 -#else - pop ar1 - pushf r3 - pop r0 - not r0 - push r0 - popf r0 - ldf -1.0, r1 - xor r1, r0 - - mpyf3 r0, r3, r1 ; r1 = r[0] * v - subrf 2.0, r1 ; r1 = 2.0 - r[0] * v - mpyf r1, r0 ; r0 = r[0] * (2.0 - r[0] * v) = r[1] -; End of 1st iteration - - mpyf3 r0, r3, r1 ; r1 = r[1] * v - subrf 2.0, r1 ; r1 = 2.0 - r[1] * v - mpyf r1, r0 ; r0 = r[1] * (2.0 - r[1] * v) = r[2] -; End of 2nd iteration - - mpyf3 r0, r3, r1 ; r1 = r[2] * v - subrf 2.0, r1 ; r1 = 2.0 - r[2] * v - mpyf r1, r0 ; r0 = r[2] * (2.0 - r[2] * v) = r[3] -; End of 3rd iteration - - or 080h, r0 - rnd r0 - -; mpyf3 r0, r3, r1 ; r1 = r[3] * v - push r4 - pushf r4 - mpyf r0, r3, r1 - - ldf r0, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r3, r4 - addf r4, r1 - - ldf r3, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r0, r4 - addf r4, r1 - - subrf 2.0, r1 ; r1 = 2.0 - r[3] * v - - mpyf r1, r0, r3 ; r3 = r[3] * (2.0 - r[3] * v) = r[5] - - ldf r1, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r0, r4 - addf r4, r3 - - ldf r0, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r1, r4 - addf r4, r3 - - mpyf r2, r3, r0 ; Multiply by the dividend - - ldf r2, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r3, r4 - addf r4, r0 - - ldf r3, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r2, r4 - bd ar1 - addf r4, r0 - - popf r4 - pop r4 -#endif -#endif diff --git a/gcc/config/c4x/t-c4x b/gcc/config/c4x/t-c4x deleted file mode 100755 index 39e316e..0000000 --- a/gcc/config/c4x/t-c4x +++ /dev/null @@ -1,22 +0,0 @@ -CROSS_LIBGCC1 = libgcc1-asm.a -LIB1ASMSRC = c4x/libgcc.S -LIB1ASMFUNCS = _divqf3 _divqi3 _udivqi3 _umodqi3 _modqi3 _mulqi3 \ - _mulhf3 _divhf3 _unsfltconst _unsfltcompare \ - _mulhi3 _umulhi3_high _smulhi3_high _divhi3 _modhi3 _umodhi3 _udivhi3 \ - _fix_truncqfhi2 _ufix_truncqfhi2 _floathiqf2 _ufloathiqf2 \ - _floathihf2 _ufloathihf2 _fix_trunchfhi2 _ufix_trunchfhi2 _ffs - -# We do not have DF or DI types (or SF and SI for that matter), -# so fake out the libgcc2 compilation. -LIBGCC2_CFLAGS = -O2 -Dexit=unused_exit $(GCC_CFLAGS) $(LIBGCC2_INCLUDES) -DDF=HF -DDI=HI -DSF=QF -DSI=QI -Dinhibit_libc - -MULTILIB_OPTIONS = m30 msmall mmemparm -MULTILIB_DIRNAMES = c3x small mem -MULTILIB_MATCHES = m30=mcpu?30 m30=mcpu?31 m30=mcpu?32 m30=m31 m30=m32 -MULTILIB_EXCEPTIONS = -MULTILIB_EXTRA_OPTS = -LIBGCC = stmp-multilib -INSTALL_LIBGCC = install-multilib - -# Don't make libgcc1-test since require crt0.o -LIBGCC1_TEST = diff --git a/gcc/config/c4x/xm-c4x.h b/gcc/config/c4x/xm-c4x.h deleted file mode 100755 index dc329eb..0000000 --- a/gcc/config/c4x/xm-c4x.h +++ /dev/null @@ -1,21 +0,0 @@ -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 32 -#define HOST_BITS_PER_SHORT 32 -#define HOST_BITS_PER_INT 32 -#define HOST_BITS_PER_LONG 32 -#define HOST_BITS_PER_LONGLONG 64 - -#define HOST_WORDS_BIG_ENDIAN - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - diff --git a/gcc/config/clipper/clipper.c b/gcc/config/clipper/clipper.c deleted file mode 100755 index d59d3f1..0000000 --- a/gcc/config/clipper/clipper.c +++ /dev/null @@ -1,508 +0,0 @@ -/* Subroutines for insn-output.c for Clipper - Copyright (C) 1987, 1988, 1991, 1997 Free Software Foundation, Inc. - Contributed by Holger Teutsch (holger@hotbso.rhein-main.de) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "tree.h" -#include "c-tree.h" -#include "expr.h" -#include "flags.h" -#include "machmode.h" - -extern char regs_ever_live[]; - -extern int frame_pointer_needed; - -static int frame_size; - -/* - * compute size of a clipper stack frame where 'lsize' is the required - * space for local variables. - */ - -int -clipper_frame_size (lsize) - int lsize; -{ - int i,size; /* total size of frame */ - int save_size; - save_size = 0; /* compute size for reg saves */ - - for (i = 16; i < 32; i++) - if (regs_ever_live[i] && !call_used_regs[i]) - save_size += 8; - - for (i = 0; i < 16; i++) - if (regs_ever_live[i] && !call_used_regs[i]) - save_size += 4; - - size = lsize + save_size; - - size = (size + 7) & ~7; /* align to 64 Bit */ - return size; -} - -/* - * prologue and epilogue output - * function is entered with pc pushed, i.e. stack is 32 bit aligned - * - * current_function_args_size == 0 means that the current function's args - * are passed totally in registers i.e fp is not used as ap. - * If frame_size is also 0 the current function does not push anything and - * can run with misaligned stack -> subq $4,sp / add $4,sp on entry and exit - * can be omitted. - * - */ -void -output_function_prologue (file, lsize) - FILE *file; - int lsize; /* size for locals */ -{ - int i, offset; - int size; - - frame_size = size = clipper_frame_size (lsize); - - if (frame_pointer_needed) - { - fputs ("\tpushw fp,sp\n", file); - fputs ("\tmovw sp,fp\n", file); - } - else if (size != 0 || current_function_args_size != 0) - { - size += 4; /* keep stack aligned */ - frame_size = size; /* must push data or access args */ - } - - if (size) - { - if (size < 16) - fprintf (file, "\tsubq $%d,sp\n", size); - else - fprintf (file, "\tsubi $%d,sp\n", size); - - /* register save slots are relative to sp, because we have small positive - displacements and this works whether we have a frame pointer or not */ - - offset = 0; - for (i = 16; i < 32; i++) - if (regs_ever_live[i] && !call_used_regs[i]) - { - if (offset == 0) - fprintf (file, "\tstord f%d,(sp)\n", i-16); - else - fprintf (file, "\tstord f%d,%d(sp)\n", i-16, offset); - offset += 8; - } - - for (i = 0; i < 16; i++) - if (regs_ever_live[i] && !call_used_regs[i]) - { - if (offset == 0) - fprintf (file, "\tstorw r%d,(sp)\n", i); - else - fprintf (file, "\tstorw r%d,%d(sp)\n", i, offset); - offset += 4; - } - } -} - -void -output_function_epilogue (file, size) - FILE *file; - int size; /* ignored */ -{ - int i, offset; - - if (frame_pointer_needed) - { - offset = -frame_size; - - for (i = 16; i < 32; i++) - if (regs_ever_live[i] && !call_used_regs[i]) - { - fprintf (file, "\tloadd %d(fp),f%d\n", offset, i-16); - offset += 8; - } - - for (i = 0; i < 16; i++) - if (regs_ever_live[i] && !call_used_regs[i]) - { - fprintf (file, "\tloadw %d(fp),r%d\n", offset, i); - offset += 4; - } - - fputs ("\tmovw fp,sp\n\tpopw sp,fp\n\tret sp\n", - file); - } - - else /* no frame pointer */ - { - offset = 0; - - for (i = 16; i < 32; i++) - if (regs_ever_live[i] && !call_used_regs[i]) - { - if (offset == 0) - fprintf (file, "\tloadd (sp),f%d\n", i-16); - else - fprintf (file, "\tloadd %d(sp),f%d\n", offset, i-16); - offset += 8; - } - - for (i = 0; i < 16; i++) - if (regs_ever_live[i] && !call_used_regs[i]) - { - if (offset == 0) - fprintf (file, "\tloadw (sp),r%d\n", i); - else - fprintf (file, "\tloadw %d(sp),r%d\n", offset, i); - offset += 4; - } - - if (frame_size > 0) - { - if (frame_size < 16) - fprintf (file, "\taddq $%d,sp\n", frame_size); - else - fprintf (file, "\taddi $%d,sp\n", frame_size); - } - - fputs ("\tret sp\n", file); - } -} - -/* - * blockmove - * - * clipper_movstr () - */ -void -clipper_movstr (operands) - rtx *operands; -{ - rtx dst,src,cnt,tmp,top,bottom,xops[3]; - int align; - int fixed; - - extern FILE *asm_out_file; - - dst = operands[0]; - src = operands[1]; - /* don't change this operands[2]; gcc 2.3.3 doesn't honor clobber note */ - align = INTVAL (operands[3]); - tmp = operands[4]; - cnt = operands[5]; - - if (GET_CODE (operands[2]) == CONST_INT) /* fixed size move */ - { - if ((fixed = INTVAL (operands[2])) <= 0) - abort (); - - if (fixed <16) - output_asm_insn ("loadq %2,%5", operands); - else - output_asm_insn ("loadi %2,%5", operands); - } - else - { - fixed = 0; - bottom = (rtx)gen_label_rtx (); /* need a bottom label */ - xops[0] = cnt; xops[1] = bottom; - output_asm_insn ("movw %2,%5", operands); /* count is scratch reg 5 */ - output_asm_insn ("brle %l1", xops); - } - - - top = (rtx)gen_label_rtx (); /* top of loop label */ - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (top)); - - - xops[0] = src; xops[1] = tmp; xops[2] = dst; - - if (fixed && (align & 0x3) == 0) /* word aligned move with known size */ - { - if (fixed >= 4) - { - rtx xops1[2]; - output_asm_insn( - "loadw %a0,%1\n\taddq $4,%0\n\tstorw %1,%a2\n\taddq $4,%2", - xops); - - xops1[0] = cnt; xops1[1] = top; - output_asm_insn ("subq $4,%0\n\tbrgt %l1", xops1); - } - - if (fixed & 0x2) - { - output_asm_insn ("loadh %a0,%1\n\tstorh %1,%a2", xops); - if (fixed & 0x1) - output_asm_insn ("loadb 2%a0,%1\n\tstorb %1,2%a2", xops); - } - else - if (fixed & 0x1) - output_asm_insn ("loadb %a0,%1\n\tstorb %1,%a2", xops); - } - else - { - output_asm_insn( - "loadb %a0,%1\n\taddq $1,%0\n\tstorb %1,%a2\n\taddq $1,%2", - xops); - - xops[0] = cnt; xops[1] = top; - output_asm_insn ("subq $1,%0\n\tbrgt %l1", xops); - } - - if (fixed == 0) - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (bottom)); -} - - -print_operand_address (file, addr) - FILE *file; - register rtx addr; -{ - rtx op0,op1; - - retry: - switch (GET_CODE (addr)) - { - case REG: - fprintf (file, "(%s)", reg_names[REGNO (addr)]); - break; - - case PLUS: - /* can be 'symbol + reg' or 'reg + reg' */ - - op0 = XEXP (addr, 0); - op1 = XEXP (addr, 1); - - if (GET_CODE (op0) == REG && GET_CODE (op1) == REG) - { - fprintf (file, "[%s](%s)", - reg_names[REGNO (op0)], reg_names[REGNO (op1)]); - break; - } - - if (GET_CODE (op0) == REG && CONSTANT_ADDRESS_P (op1)) - { - output_addr_const (file, op1); - fprintf (file, "(%s)", reg_names[REGNO (op0)]); - break; - } - - if (GET_CODE (op1) == REG && CONSTANT_ADDRESS_P (op0)) - { - output_addr_const (file, op0); - fprintf (file, "(%s)", reg_names[REGNO (op1)]); - break; - } - abort (); /* Oh no */ - - default: - output_addr_const (file, addr); - } -} - - -char * -rev_cond_name (op) - rtx op; -{ - switch (GET_CODE (op)) - { - case EQ: - return "ne"; - case NE: - return "eq"; - case LT: - return "ge"; - case LE: - return "gt"; - case GT: - return "le"; - case GE: - return "lt"; - case LTU: - return "geu"; - case LEU: - return "gtu"; - case GTU: - return "leu"; - case GEU: - return "ltu"; - - default: - abort (); - } -} - - -/* Do what is necessary for `va_start'. The argument is ignored; - We fill in an initial va_list. A pointer to this constructor - is returned. */ - - -struct rtx_def * -clipper_builtin_saveregs (arglist) - tree arglist; -{ - extern int current_function_varargs; - rtx block, addr, argsize, scratch, r0_addr,r1_addr,f0_addr,f1_addr; - - /* Allocate the va_list constructor + save area for r0,r1,f0,f1 */ - - block = assign_stack_local (BLKmode, - (6 + 6) * UNITS_PER_WORD, 2 * BITS_PER_WORD); - - RTX_UNCHANGING_P (block) = 1; - RTX_UNCHANGING_P (XEXP (block, 0)) = 1; - - addr = copy_to_reg (XEXP (block, 0)); - - f0_addr = gen_rtx (PLUS, Pmode, addr, GEN_INT (24)); - f1_addr = gen_rtx (PLUS, Pmode, addr, GEN_INT (32)); - r0_addr = gen_rtx (PLUS, Pmode, addr, GEN_INT (40)); - r1_addr = gen_rtx (PLUS, Pmode, addr, GEN_INT (44)); - - - /* Store float regs */ - - emit_move_insn (gen_rtx (MEM, DFmode, f0_addr), gen_rtx (REG, DFmode, 16)); - emit_move_insn (gen_rtx (MEM, DFmode, f1_addr), gen_rtx (REG, DFmode, 17)); - - /* Store int regs */ - - emit_move_insn (gen_rtx (MEM, SImode, r0_addr), gen_rtx (REG, SImode, 0)); - emit_move_insn (gen_rtx (MEM, SImode, r1_addr), gen_rtx (REG, SImode, 1)); - - /* Store the arg pointer in the __va_stk member. */ - - emit_move_insn (gen_rtx (MEM, SImode, addr), - copy_to_reg (virtual_incoming_args_rtx)); - - - /* now move addresses of the saved regs into the pointer array */ - - scratch = gen_reg_rtx (Pmode); - - emit_move_insn (scratch, r0_addr); - emit_move_insn (gen_rtx (MEM, SImode, - gen_rtx (PLUS, Pmode, addr, - GEN_INT (4))), - scratch); - - emit_move_insn (scratch, f0_addr); - emit_move_insn (gen_rtx (MEM, SImode, - gen_rtx (PLUS, Pmode, addr, - GEN_INT (8))), - scratch); - - emit_move_insn (scratch, r1_addr); - emit_move_insn (gen_rtx (MEM, SImode, - gen_rtx (PLUS, Pmode, addr, - GEN_INT (12))), - scratch); - - emit_move_insn (scratch, f1_addr); - emit_move_insn (gen_rtx (MEM, SImode, - gen_rtx (PLUS, Pmode, addr, - GEN_INT (16))), - scratch); - - - if (current_function_check_memory_usage) - { - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - addr, ptr_mode, - GEN_INT (5 * GET_MODE_SIZE (SImode)), - TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - f0_addr, ptr_mode, - GEN_INT (GET_MODE_SIZE (DFmode)), - TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - f1_addr, ptr_mode, - GEN_INT (GET_MODE_SIZE (DFmode)), - TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - r0_addr, ptr_mode, - GEN_INT (GET_MODE_SIZE (SImode)), - TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - r1_addr, ptr_mode, - GEN_INT (GET_MODE_SIZE (SImode)), - TYPE_MODE (sizetype), - GEN_INT (MEMORY_USE_RW), - TYPE_MODE (integer_type_node)); - } - - /* Return the address of the va_list constructor, but don't put it in a - register. This fails when not optimizing and produces worse code when - optimizing. */ - return XEXP (block, 0); -} - - -/* Return truth value of whether OP can be used as an word register - operand. Reject (SUBREG:SI (REG:SF )) */ - -int -int_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) && - (GET_CODE (op) != SUBREG || - GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) == MODE_INT)); -} - -/* Return truth value of whether OP can be used as a float register - operand. Reject (SUBREG:SF (REG:SI )) )) */ - -int -fp_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) && - (GET_CODE (op) != SUBREG || - GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) == MODE_FLOAT)); -} - diff --git a/gcc/config/clipper/clipper.h b/gcc/config/clipper/clipper.h deleted file mode 100755 index 666e96d..0000000 --- a/gcc/config/clipper/clipper.h +++ /dev/null @@ -1,1125 +0,0 @@ -/* Definitions of target machine for GNU compiler. Clipper version. - Copyright (C) 1987, 88, 91, 93-95, 1996 Free Software Foundation, Inc. - Contributed by Holger Teutsch (holger@hotbso.rhein-main.de) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -extern struct rtx_def *clipper_builtin_saveregs (); -extern int clipper_frame_size (); - -/* Print subsidiary information on the compiler version in use. */ - -#define TARGET_VERSION fprintf (stderr, " (clipper)"); - -/* Run-time compilation parameters selecting different hardware subsets. */ - -extern int target_flags; - -/* Macros used in the machine description to test the flags. */ - -/* Macro to define tables used to set the flags. - This is a list in braces of pairs in braces, - each pair being { "NAME", VALUE } - where VALUE is the bits to set or minus the bits to clear. - An empty string NAME is used to identify the default VALUE. */ - -#define TARGET_SWITCHES \ - { { "c400", 1 }, \ - { "c300", -1 }, \ - { "", TARGET_DEFAULT} } - -#define TARGET_C400 1 -#define TARGET_C300 0 - -/* Default target_flags if no switches specified. */ - -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT TARGET_C300 -#endif - -/* Show that we can debug generated code without a frame pointer. */ -#define CAN_DEBUG_WITHOUT_FP - -/* Target machine storage layout */ - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. */ - -#define BITS_BIG_ENDIAN 0 - -/* Define this if most significant byte of a word is the lowest numbered. */ - -#define BYTES_BIG_ENDIAN 0 - -/* Define this if most significant word of a multiword number is the lowest - numbered. */ - -#define WORDS_BIG_ENDIAN 0 - -/* Number of bits in an addressable storage unit */ -#define BITS_PER_UNIT 8 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; - if using 16-bit ints on a 68000, this would still be 32. - But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 32 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 4 - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 32 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Largest alignment for stack parameters (if greater than PARM_BOUNDARY). */ -#define MAX_PARM_BOUNDARY 64 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 128 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 32 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* A bitfield declared as `int' forces `int' alignment for the struct. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 64 - -/* No structure field wants to be aligned rounder than this. */ -#define BIGGEST_FIELD_ALIGNMENT 64 - -/* Make strcpy of constants fast. */ -#define CONSTANT_ALIGNMENT(CODE, TYPEALIGN) \ - ((TYPEALIGN) < 32 ? 32 : (TYPEALIGN)) - -/* Make arrays of chars word-aligned for the same reasons. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -/* Set this nonzero if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 1 - -/* Let's keep the stack somewhat aligned. */ -#define STACK_BOUNDARY 64 - -/* Define this macro if it is advisable to hold scalars in registers - in a wider mode than that declared by the program. In such cases, - the value is constrained to be within the bounds of the declared - type, but kept valid in the wider mode. The signedness of the - extension may differ from that of the type. - - For Clipper, we always store objects in a full register. */ - -#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ - if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ - { \ - (UNSIGNEDP) = 0; \ - (MODE) = SImode; \ - } - - -/* Define this if function arguments should also be promoted using the above - procedure. */ - -/* FIXME: do we loose compatibility to acc if we define this? */ - -/* #define PROMOTE_FUNCTION_ARGS */ - -/* Likewise, if the function return value is promoted. */ - -/* #define PROMOTE_FUNCTION_RETURN */ - - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. */ -#define FIRST_PSEUDO_REGISTER 32 - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - On the clipper, these are the FP and SP . */ -#define FIXED_REGISTERS \ -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,\ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1} /* Default: C300 */ - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. */ -#define CALL_USED_REGISTERS \ -{1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,\ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1} /* default: C300 */ - -/* Zero or more C statements that may conditionally modify two - variables `fixed_regs' and `call_used_regs' (both of type `char - []') after they have been initialized from the two preceding - macros. A C400 has additional floating registers f8 -> f15 */ - -#define CONDITIONAL_REGISTER_USAGE \ - if (target_flags & TARGET_C400) \ - { int i; \ - for (i = 24; i < 32; i++) fixed_regs[i] = call_used_regs[i] = 0; } - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. - On the clipper, fp registers are 64 bits. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((REGNO) >= 16 ? 1 \ - : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - On the clipper 0-15 may hold any mode but DImode and DFmode must be even. - Registers 16-31 hold SFmode and DFmode */ - -#define HARD_REGNO_MODE_OK(REGNO, MODE) \ - ((REGNO) < 16 \ - ? ((MODE) != DImode && (MODE) != DFmode || ((REGNO) & 1) == 0) \ - : ((MODE) == SFmode || (MODE) == DFmode)) - -/* Value is 1 if it is a good idea to tie two pseudo registers - when one has mode MODE1 and one has mode MODE2. - If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, - for any hard reg, then this must be 0 for correct output. */ -#define MODES_TIEABLE_P(MODE1, MODE2) ((MODE1) == (MODE2)) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* clipper has extra PC */ -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM 15 - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 14 - -/* 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 \ - (! leaf_function_p ()) - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM - -/* Register in which static-chain is passed to a function. */ -#define STATIC_CHAIN_REGNUM 2 - -/* Register in which address to store a structure value - is passed to a function. */ -#define STRUCT_VALUE_REGNUM 0 - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -/* The clipper has general and FP regs. */ - -enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, LIM_REG_CLASSES}; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ - {"NO_REGS", "GENERAL_REGS", "FLOAT_REGS", "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS {0, 0x0000ffff, 0xffff0000, 0xffffffff} - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) ((REGNO) >= 16 ? FLOAT_REGS : GENERAL_REGS) - -/* The class value for index registers, and the one for base regs. */ - -#define INDEX_REG_CLASS GENERAL_REGS -#define BASE_REG_CLASS GENERAL_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) \ - ((C) == 'r' ? GENERAL_REGS : ((C) == 'f' ? FLOAT_REGS: NO_REGS)) - -/* The letters I, J, K, L and M in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) 0 - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 - -/* Optional extra constraints for this machine. */ - -/* #define EXTRA_CONSTRAINT(OP, 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 on some machines - in some cases it is preferable to use a more restrictive class. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ - -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((CLASS) == FLOAT_REGS \ - ? 1 \ - : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -#define STACK_GROWS_DOWNWARD - -/* Define this if longjmp restores from saved registers - rather than from what setjmp saved. */ -/* #define LONGJMP_RESTORE_FROM_STACK */ - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ -#define STARTING_FRAME_OFFSET 0 - -/* 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. */ -#define DYNAMIC_CHAIN_ADDRESS(frame) (frame) - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. */ - -/* #define PUSH_ROUNDING(BYTES) (BYTES) */ - -/* Keep the stack pointer constant throughout the function. */ -/* we can't set this for clipper as library calls may have 3 args and we pass - only 2 args in regs. */ - -/* #define ACCUMULATE_OUTGOING_ARGS */ - - -/* Offset of first parameter from the argument pointer register value. - size of PC + FP */ - -#define FIRST_PARM_OFFSET(FNDECL) 8 - -/* Value is the number of bytes of arguments automatically - popped when returning from a subroutine call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - SIZE is the number of bytes of arguments passed on the stack. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), ((TYPE_MODE (VALTYPE) == SFmode ||\ - TYPE_MODE (VALTYPE) == DFmode) ? \ - 16 : 0)) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ - -#define LIBCALL_VALUE(MODE) \ - gen_rtx (REG, (MODE), ((MODE) == SFmode || (MODE) == DFmode ? 16 : 0)) - - -/* 1 if N is a possible register number for a function value - as seen by the caller. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N) == 16) - -/* 1 if N is a possible register number for function argument passing. */ - -#define FUNCTION_ARG_REGNO_P(N) \ - ((N) == 0 || (N) == 1 || (N) == 16 || (N) == 17) - -/* Define this if PCC uses the nonreentrant convention for returning - structure and union values. Old Green Hills C-Clipper returns static - structs but the newer Apogee compiler passes structs as hidden arg 0. - Structs etc are always passed in memory */ - -/* #define PCC_STATIC_STRUCT_RETURN */ - - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. - - Clipper uses 2 register 'slots' that pass arguments in r0/r1 or f0/f1. - An argument that must be passed in memory (struct... ) leaves that slot - free. - We pass 'long long' only in registers when both slots are free. - Returned structs must be allocated by the caller, the address is passed - in r0. - - struct ss {..} - - fun (i,j,k) i in r0, j in r1, k on stack - fun (s,j,k) s on stack, j in r1, k on stack - fun (i,s,k) i in r0, s on stack, k on stack - s1 = fun (i,s,k) &s1 in r0, i in r1, s on stack, k on stack - - We must keep enough information for varargs/stdargs. - - _clipper_cum_args is a struct of 2 integers, with - num = slots used - size = size of all stack args = offset to next arg without alignment - - If we use stdarg.h, size points to the first unnamed arg, - see va-clipper.h */ - -struct _clipper_cum_args { int num; int size; }; - -#define CUMULATIVE_ARGS struct _clipper_cum_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. - - clipper passes the address of a struct in r0, set num = 1 in this case */ - -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ - ((CUM).num = ((FNTYPE) != 0 && aggregate_value_p (TREE_TYPE (FNTYPE))), \ - (CUM).size = 0) - -/* internal helper : size of an argument */ - -#define CLIPPER_ARG_SIZE(MODE, TYPE) \ -(((MODE) != BLKmode \ - ? (GET_MODE_SIZE (MODE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD \ - : (int_size_in_bytes (TYPE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD) \ - * UNITS_PER_WORD) - -/* 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) \ -do \ -{ \ - int reg = 0; \ - \ - if ((CUM).num < 2 \ - && (GET_MODE_CLASS(MODE)==MODE_INT || GET_MODE_CLASS(MODE)==MODE_FLOAT) \ - && (GET_MODE_SIZE (MODE) <= 8) \ - && ((TYPE) == NULL || !AGGREGATE_TYPE_P(TYPE)) \ - && ((MODE) != DImode || (CUM).num == 0)) \ - { \ - reg = 1; \ - if ((MODE) == DImode) \ - (CUM).num = 1; \ - } \ - \ - (CUM).num++; \ - \ - if (! reg) \ - { \ - int align = FUNCTION_ARG_BOUNDARY (MODE, TYPE) / BITS_PER_UNIT; \ - (CUM).size += align - 1; \ - (CUM).size &= ~(align - 1); \ - (CUM).size += CLIPPER_ARG_SIZE (MODE, TYPE); \ - } \ -} while (0) - -/* Define where to put the arguments to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). - - 2 args may go into regs. These must be MODE_INT or MODE_FLOAT but only - if they really fit into ONE register. The exception is a DImode arg - that occupies both register slots. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - (((CUM).num < 2 \ - && (GET_MODE_CLASS(MODE)==MODE_INT || GET_MODE_CLASS(MODE)==MODE_FLOAT) \ - && (GET_MODE_SIZE (MODE) <= 8) \ - && ((TYPE) == NULL || !AGGREGATE_TYPE_P(TYPE)) \ - && ((MODE) != DImode || (CUM).num == 0)) \ - ? gen_rtx (REG, (MODE), \ - GET_MODE_CLASS(MODE) == MODE_FLOAT ? (CUM).num+16 : (CUM).num) \ - : 0) - -/* 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) \ - (((TYPE) ? TYPE_ALIGN (TYPE) : GET_MODE_SIZE (MODE)) <= PARM_BOUNDARY \ - ? PARM_BOUNDARY : 2 * PARM_BOUNDARY) - -/* 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. - Clipper never passed args partially in regs/mem. */ - -/* #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0 */ - -/* Generate necessary RTL for __builtin_saveregs(). - ARGLIST is the argument list; see expr.c. */ - -#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) clipper_builtin_saveregs (ARGLIST) - -/* This macro generates the assembly code for function entry. - FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - 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. */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) output_function_prologue (FILE,SIZE) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) /* FIXME */ - -/* Output assembler code to FILE to initialize this source file's - basic block profiling info, if that has not already been done. */ - -#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) /* FIXME */ - -/* Output assembler code to FILE to increment the entry-count for - the BLOCKNO'th basic block in this source file. */ - -#define BLOCK_PROFILER(FILE, BLOCKNO) /* FIXME */ - -/* 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 - -/* This macro generates the assembly code for function exit, - on machines that need it. If FUNCTION_EPILOGUE is not defined - then individual return instructions are generated for each - return statement. Args are same as for FUNCTION_PROLOGUE. */ - -#define FUNCTION_EPILOGUE(FILE, SIZE) output_function_epilogue(FILE,SIZE) - -/* Store in the variable DEPTH the initial difference between the - frame pointer reg contents and the stack pointer reg contents, - as of the start of the function body. This depends on the layout - of the fixed parts of the stack frame and on how registers are saved. */ - -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ - DEPTH = clipper_frame_size (get_frame_size ()) - - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. */ - -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - fputs ("\t.word 0x459F,0x0004\t# call sp,.+4\n", FILE); \ - fputs ("\tmovw (sp),r3\n", FILE); \ - fputs ("\taddq $4,sp\n", FILE); \ - fputs ("\tloadw 20(r3),r2\n", FILE); \ - fputs ("\tloadw 24(r3),r3\n", FILE); \ - fputs ("\tb (r3)\n", FILE); \ - fputs ("\t.long 0,0\n", FILE); \ -} - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 32 - -/* Alignment required for a trampoline. 128 is used to find the - beginning of a line in the instruction cache and to allow for - instruction cache lines of up to 128 bytes. */ - -#define TRAMPOLINE_ALIGNMENT 128 - -/* Section in which to place the trampoline. */ - -#define TRAMPOLINE_SECTION text_section - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 24)), CXT); \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 28)), FNADDR); \ -} - -/* Addressing modes, and classification of registers for them. */ - -/* #define HAVE_POST_DECREMENT 0 */ - -/* #define HAVE_PRE_INCREMENT 0 */ - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_INDEX_P(regno) \ -((regno) < 16 || (unsigned)reg_renumber[regno] < 16) -#define REGNO_OK_FOR_BASE_P(regno) \ -((regno) < 16 || (unsigned)reg_renumber[regno] < 16) - -/* Maximum number of registers that can appear in a valid memory address. */ - -#define MAX_REGS_PER_ADDRESS 2 - -/* 1 if X is an rtx for a constant that is a valid address. */ - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ - || GET_CODE (X) == HIGH) - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ - -#define LEGITIMATE_CONSTANT_P(X) 1 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - - /* clipper doesn't have true indexing */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ - -#define REG_OK_FOR_INDEX_P(X) \ - (REGNO (X) < 16 || REGNO(X) >= FIRST_PSEUDO_REGISTER) - -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ - -#define REG_OK_FOR_BASE_P(X) \ - (REGNO (X) < 16 || REGNO(X) >= FIRST_PSEUDO_REGISTER) - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) (REGNO(X) < 16) - -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) (REGNO(X) < 16) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS, - except for CONSTANT_ADDRESS_P which is actually machine-independent. */ - -/* Non-zero if X is an address which can be indirected. */ - -#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) 0 - -#define INDIRECTABLE_ADDRESS_P(X) \ - (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) - -/* Go to ADDR if X is a valid address not using indexing. - (This much is the easy part.) */ - -#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \ -{ if (CONSTANT_ADDRESS_P (X)) goto ADDR; \ - if (INDIRECTABLE_ADDRESS_P (X)) goto ADDR; } - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ register rtx xfoo = (X); \ - GO_IF_NONINDEXED_ADDRESS (xfoo, ADDR); \ - if (GET_CODE (xfoo) == PLUS) \ - { register rtx xfoo0, xfoo1; \ - xfoo0 = XEXP (xfoo, 0); \ - xfoo1 = XEXP (xfoo, 1); \ - /* handle reg + reg -> [r1](r0) */ \ - if (INDIRECTABLE_ADDRESS_P (xfoo0) && INDIRECTABLE_ADDRESS_P (xfoo1)) \ - goto ADDR; \ - /* Handle (reg) -> xxx(r0) */ \ - if (INDIRECTABLE_ADDRESS_P (xfoo0) && CONSTANT_ADDRESS_P (xfoo1)) \ - goto ADDR; \ - if (INDIRECTABLE_ADDRESS_P (xfoo1) && CONSTANT_ADDRESS_P (xfoo0)) \ - goto ADDR; }} - - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. - - For the clipper, nothing needs to be done. */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {} - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {} - - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE 1 */ - -/* Define this if the case instruction drops through after the table - when the index is out of range. Don't define it if the case insn - jumps to the default label instead. */ -/* #define CASE_DROPS_THROUGH */ - -/* Define if operations between registers always perform the operation - on the full register even if a narrower mode is specified. */ -#define WORD_REGISTER_OPERATIONS - -/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD - will either zero-extend or sign-extend. The value of this macro should - be the code that says which one of the two operations is implicitly - done, NIL if none. */ -#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND - -/* Specify the tree operation to be used to convert reals to integers. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* This is the kind of divide that is easiest to do in the general case. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* This flag, if defined, says the same insns that convert to a signed fixnum - also convert validly to an unsigned one. */ -#define FIXUNS_TRUNC_LIKE_FIX_TRUNC - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 4 - -/* If a memory-to-memory move would take MOVE_RATIO or more simple - move-instruction pairs, we will do a movstr or libcall instead. - - Make this large on clipper, since the block move is very - inefficient with small blocks, and the hard register needs of the - block move require much reload work. */ - -#define MOVE_RATIO 20 - -/* Define this if zero-extension is slow (more than one real instruction). */ -/* #define SLOW_ZERO_EXTEND */ - -/* Nonzero if access to memory by bytes is slow and undesirable. */ -#define SLOW_BYTE_ACCESS 0 - -/* Define if shifts truncate the shift count - which implies one can omit a sign-extension or zero-extension - of a shift count. */ -/* #define SHIFT_COUNT_TRUNCATED */ - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -#define Pmode SImode - -/* A function address in a call instruction - is a byte address (for indexing purposes) - so give the MEM rtx a byte's mode. */ -#define FUNCTION_MODE QImode - -/* This machine uses IEEE floats. */ - -#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT - -/* Check a `double' value for validity for a particular machine mode. - This is defined to avoid crashes outputting certain constants. - Since we output the number in hex, the assembler won't choke on it. */ -/* #define CHECK_FLOAT_VALUE(MODE,VALUE) */ - - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. */ - -/* On a Clipper, constants from 0..15 are cheap because they can use the - 'quick' mode. */ - -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - if (0 <= INTVAL (RTX) && INTVAL(RTX) <= 15 ) return 0; \ - return 1; \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - return 3; \ - case CONST_DOUBLE: \ - return 5; - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. */ - -#define RTX_COSTS(X,CODE,OUTER_CODE) \ - case MULT: \ - return COSTS_N_INSNS (4); \ - case DIV: \ - case UDIV: \ - case MOD: \ - case UMOD: \ - return COSTS_N_INSNS (40); \ - case ASHIFT: \ - case LSHIFTRT: \ - case ASHIFTRT: \ - return COSTS_N_INSNS (2); \ - case SIGN_EXTEND: \ - return (GET_CODE (XEXP (X,0)) == REG ? COSTS_N_INSNS (3) : 4); - -/* Specify the cost of a branch insn; roughly the number of extra insns that - should be added to avoid a branch */ - -/* #define BRANCH_COST 0 */ - - -/* Tell final.c how to eliminate redundant test instructions. */ - -/* Here we define machine-dependent flags and fields in cc_status - (see `conditions.h'). No extra ones are needed for the clipper. */ - -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. */ - -#define NOTICE_UPDATE_CC(EXP, INSN) \ -{ \ - enum attr_cc cc = get_attr_cc (INSN); \ - rtx dest = SET_DEST (EXP); \ - switch (cc) \ - { \ - case CC_CHANGE0: \ - if (GET_CODE (EXP) == PARALLEL) abort(); \ - if (cc_status.value1 && rtx_equal_p (dest, cc_status.value1) || \ - cc_status.value2 && rtx_equal_p (dest, cc_status.value2)) \ - CC_STATUS_INIT; \ - break; \ - \ - case CC_SET1: \ - if (GET_CODE (EXP) == PARALLEL) abort(); \ - cc_status.flags = 0; \ - cc_status.value1 = dest; \ - cc_status.value2 = 0; \ - break; \ - \ - case CC_SET2: \ - if (GET_CODE (EXP) == PARALLEL) abort(); \ - cc_status.flags = 0; \ - cc_status.value1 = dest; \ - cc_status.value2 = SET_SRC (EXP); \ - break; \ - \ - case CC_UNCHANGED: \ - break; \ - \ - case CC_CLOBBER: \ - CC_STATUS_INIT; \ - break; \ - \ - default: \ - abort (); \ - } \ -} - - -/* Control the assembler format that we output. */ - -/* Output at beginning of assembler file. */ - -#define ASM_FILE_START(FILE) fprintf (FILE, "#NO_APP\n"); - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "#APP\n" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF "#NO_APP\n" - -/* Output before read-only data. */ - -#define TEXT_SECTION_ASM_OP ".text" - -/* Output before writable data. */ - -#define DATA_SECTION_ASM_OP ".data" - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \ - "r9", "r10", "r11", "r12", "r13", "fp", "sp", \ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", \ - "f9", "f10", "f11", "f12", "f13", "f14", "f15" } - -/* How to renumber registers for dbx and gdb. - Clipper needs no change in the numeration. */ - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - - -/* This is how to output the definition of a user-level label named NAME, - such as the label on a static function or variable NAME. */ - -#define ASM_OUTPUT_LABEL(FILE,NAME) \ - do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) - -/* This is how to output a command to make the user-level label named NAME - defined for reference from other files. */ - -#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ - do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) - -/* This is how to output an assembler line defining an `int' constant. */ - -#define ASM_OUTPUT_INT(FILE,VALUE) \ -( fprintf (FILE, "\t.long "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* Likewise for `char' and `short' constants. */ - -#define ASM_OUTPUT_SHORT(FILE,VALUE) \ -( fprintf (FILE, "\t.word "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ -( fprintf (FILE, "\t.byte "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* This is how to output an assembler line for a numeric constant byte. */ - -#define ASM_OUTPUT_BYTE(FILE,VALUE) \ - fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tsubq $8,sp\n\t%s %s,(sp)\n", \ - (REGNO) < 16 ? "storw" : "stord", reg_names[REGNO]) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\t%s (sp),%s\n\t\addq $8,sp\n", \ - (REGNO) < 16 ? "loadw" : "loadd", reg_names[REGNO]) -/* This is how to output an element of a case-vector that is absolute */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.long .L%d\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL) - -/* This is how to output an assembler line - that says to advance the location counter by SIZE bytes. */ - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t.space %u\n", (SIZE)) - -/* This says how to output an assembler line - to define a local common symbol. */ -/* ??? The use of .bss here seems odd. */ - -#define ASM_OUTPUT_ALIGNED_LOCAL(FILE,NAME,SIZE,ALIGN) \ -( data_section (), \ - fputs ("\t.bss\t", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN)/BITS_PER_UNIT)) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) - -/* Define the parentheses used to group arithmetic operations - in assembler code. */ - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* Define results of standard character escape sequences. */ -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - -/* Print an instruction operand X on file FILE. - CODE is the code from the %-spec that requested printing this operand; - if `%z3' was used to print operand 3, then CODE is 'z'. - -Clipper operand formatting codes: - - letter print - C reverse branch condition -*/ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ - ((CODE) == 'C') - -#define PRINT_OPERAND(FILE, X, CODE) \ -{ extern char *rev_cond_name (); \ - if (CODE == 'C') \ - fputs (rev_cond_name (X), FILE); \ - else if (GET_CODE (X) == REG) \ - fprintf (FILE, "%s", reg_names[REGNO (X)]); \ - else if (GET_CODE (X) == MEM) \ - output_address (XEXP (X, 0)); \ - else { putc ('$', FILE); output_addr_const (FILE, X); }} - -/* Print a memory operand whose address is X, on file FILE. - This uses a function in output-clipper.c. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ - print_operand_address (FILE, ADDR) - -/* Define the codes that are matched by predicates in clipper.c */ - -#define PREDICATE_CODES \ - {"int_reg_operand", {SUBREG, REG}}, \ - {"fp_reg_operand", {SUBREG, REG}}, diff --git a/gcc/config/clipper/clipper.md b/gcc/config/clipper/clipper.md deleted file mode 100755 index 87f30fa..0000000 --- a/gcc/config/clipper/clipper.md +++ /dev/null @@ -1,1421 +0,0 @@ -;;- Machine description for GNU compiler, Clipper Version -;; Copyright (C) 1987, 88, 91, 93, 94, 1997 Free Software Foundation, Inc. -;; Contributed by Holger Teutsch (holger@hotbso.rhein-main.de) - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - -;;- Instruction patterns. When multiple patterns apply, -;;- the first one in the file is chosen. -;;- -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. -;;- -;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code -;;- updates for most instructions. - -;; -;; define attributes -;; -;; instruction type -;; -;; unknown is temporary in order to generate 'cc clobber' until attribute -;; assignment is consistent -;; -(define_attr "type" "load,store,arith,fp,branch,unknown" - (const_string "unknown")) - -;; condition code setting -;; -;; clobber destroyed -;; unchanged -;; set1 set cc_status.value1, e.g. sub r0,r1 -;; set2 set value1 and value2, e.g. mov r0,r1 -;; change0 may be side effect, i.e. load mem,r0 -;; -;; note: loadi and loadq are 'arith' instructions that set the condition codes -;; mul,div,mod do NOT set the condition codes -;; -(define_attr "cc" "clobber,unchanged,set1,set2,change0" - (cond [(eq_attr "type" "load") (const_string "change0") - (eq_attr "type" "store,branch") (const_string "unchanged") - (eq_attr "type" "arith") (if_then_else (match_operand:SI 0 "" "") - (const_string "set1") - (const_string "clobber")) - ] - (const_string "clobber"))) - -;; -;; clipper seems to be a traditional risc processor -;; we define a functional unit 'memory' -;; -(define_function_unit "memory" 1 1 (eq_attr "type" "load") 4 0) - - -;; We don't want to allow a constant operand for test insns because -;; (set (cc0) (const_int foo)) has no mode information. Such insns will -;; be folded while optimizing anyway. - -(define_insn "tstsi" - [(set (cc0) - (match_operand:SI 0 "int_reg_operand" "r"))] - "" - "cmpq $0,%0") - -(define_insn "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "nonimmediate_operand" "r,r,n") - (match_operand:SI 1 "nonmemory_operand" "r,n,r")))] - "" - "* -{ - int val; - - if (which_alternative == 0) - return \"cmpw %1,%0\"; - - if (which_alternative == 1) - { - val = INTVAL (operands[1]); - if (0 <= val && val < 16) - return \"cmpq %1,%0\"; - return \"cmpi %1,%0\"; - } - - cc_status.flags |= CC_REVERSED; /* immediate must be first */ - - val = INTVAL (operands[0]); - - if (0 <= val && val < 16) - return \"cmpq %0,%1\"; - - return \"cmpi %0,%1\"; -}") - -(define_insn "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "fp_reg_operand" "f") - (match_operand:DF 1 "fp_reg_operand" "f")))] - "" - "cmpd %1,%0") - -(define_insn "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "fp_reg_operand" "f") - (match_operand:SF 1 "fp_reg_operand" "f")))] - "" - "cmps %1,%0") - - -;; -;; double and single float move -;; -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM) - { - if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = force_reg (DFmode, - force_const_mem (DFmode, operands[1])); - else if (GET_CODE (operands[1]) != REG) - operands[1] = force_reg (DFmode, operands[1]); - } - - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = force_const_mem (DFmode, operands[1]); -}") - -;; -;; provide two patterns with different predicates as we don't want combine -;; to recombine a mem -> mem move -;; -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=*rf") - (match_operand:DF 1 "nonimmediate_operand" "*rfo"))] - "" - "* -{ -#define FP_REG_P(X) (GET_CODE (X) == REG && REGNO (X) >= 16) - - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) /* f -> f */ - return \"movd %1,%0\"; - - if (GET_CODE (operands[1]) == REG) /* r -> f */ - return \"movld %1,%0\"; - - return \"loadd %1,%0\"; /* m -> f */ - } - - if (FP_REG_P (operands[1])) - { - if (GET_CODE (operands[0]) == REG) /* f -> r */ - return \"movdl %1,%0\"; - - abort (); - } - - if (GET_CODE (operands[1]) == MEM) /* m -> r */ - { - rtx xops[4]; - xops[0] = operands[0]; - xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - xops[2] = operands[1]; - xops[3] = adj_offsettable_operand (operands[1], 4); - output_asm_insn (\"loadw %2,%0\;loadw %3,%1\", xops); - return \"\"; - } - - if (GET_CODE (operands[1]) == REG) /* r -> r */ - { - rtx xops[4]; - xops[0] = operands[0]; - xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - xops[2] = operands[1]; - xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"movw %2,%0\;movw %3,%1\", xops); - return \"\"; - } - - abort (); -#undef FP_REG_P -}") - - -(define_insn "" - [(set (match_operand:DF 0 "memory_operand" "=o,m") - (match_operand:DF 1 "register_operand" "*rf,f"))] - "" - "* -{ - rtx xops[4]; - - if (REGNO (operands[1]) >= 16) /* f -> m */ - return \"stord %1,%0\"; - - xops[0] = operands[0]; /* r -> o */ - xops[1] = adj_offsettable_operand (operands[0], 4); - xops[2] = operands[1]; - xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"storw %2,%0\;storw %3,%1\", xops); - return \"\"; -}" -[(set_attr "type" "store,store") - (set_attr "cc" "clobber,unchanged")]) - - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM) - { - if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = force_reg (SFmode, - force_const_mem (SFmode, operands[1])); - else if (GET_CODE (operands[1]) != REG) - operands[1] = force_reg (SFmode, operands[1]); - } - - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = force_const_mem (SFmode, operands[1]); -}") - -;; -;; provide two patterns with different predicates as we don't want combine -;; to recombine a mem -> mem move -;; -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=*rf") - (match_operand:SF 1 "nonimmediate_operand" "*rfm"))] - "" - "* -{ -#define FP_REG_P(X) (GET_CODE (X) == REG && REGNO (X) >= 16) - - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) /* f -> f */ - return \"movs %1,%0\"; - if (GET_CODE (operands[1]) == REG) /* r -> f */ - return - \"subq $8,sp\;storw %1,(sp)\;loads (sp),%0\;addq $8,sp\"; - return \"loads %1,%0\"; /* m -> f */ - } - - if (FP_REG_P (operands[1])) - { - if (GET_CODE (operands[0]) == REG) /* f -> r */ - return - \"subq $8,sp\;stors %1,(sp)\;loadw (sp),%0\;addq $8,sp\"; - abort (); - } - - if (GET_CODE (operands[1]) == MEM) /* m -> r */ - return \"loadw %1,%0\"; - - if (GET_CODE (operands[1]) == REG) /* r -> r */ - return \"movw %1,%0\"; - - abort (); -#undef FP_REG_P -}") - -(define_insn "" - [(set (match_operand:SF 0 "memory_operand" "=m") - (match_operand:SF 1 "register_operand" "*rf"))] - "" - "* -{ - if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) >= 16) - return \"stors %1,%0\"; /* f-> m */ - - return \"storw %1,%0\"; /* r -> m */ -}" -[(set_attr "type" "store")]) - - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) != REG) - operands[1] = force_reg (DImode, operands[1]); -}") - -;; If an operand is a MEM but not offsettable, we can't load it into -;; a register, so we must force the third alternative to be the one -;; reloaded. Hence we show the first as more expensive. -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=?r,r,r") - (match_operand:DI 1 "general_operand" "r,n,o"))] - "" - "* -{ - rtx xoperands[2],yoperands[2]; - - xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - - if (which_alternative == 0) /* r -> r */ - { - output_asm_insn (\"movw %1,%0\", operands); - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"movw %1,%0\", xoperands); - return \"\"; - } - - if (which_alternative == 1) /* n -> r */ - { - if (GET_CODE (operands[1]) == CONST_INT) - { - output_asm_insn (\"loadi %1,%0\", operands); - output_asm_insn (\"loadq $0,%0\", xoperands); - return \"\"; - } - - if (GET_CODE (operands[1]) != CONST_DOUBLE) - abort (); - - yoperands[0] = operands[0]; - yoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); - output_asm_insn (\"loadi %1,%0\", yoperands); - - xoperands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])); - output_asm_insn (\"loadi %1,%0\", xoperands); - return \"\"; - } - /* m -> r */ - output_asm_insn (\"loadw %1,%0\", operands); - xoperands[1] = adj_offsettable_operand (operands[1], 4); - output_asm_insn (\"loadw %1,%0\", xoperands); - return \"\"; -}" -[(set_attr "type" "arith,arith,load") - (set_attr "cc" "clobber,clobber,clobber")]) - -(define_insn "" - [(set (match_operand:DI 0 "memory_operand" "=o") - (match_operand:DI 1 "register_operand" "r"))] - "" - "* -{ - rtx xops[4]; - xops[0] = operands[0]; - xops[1] = adj_offsettable_operand (operands[0], 4); - xops[2] = operands[1]; - xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"storw %2,%0\;storw %3,%1\", xops); - return \"\"; -}" -[(set_attr "type" "store") - (set_attr "cc" "clobber")]) - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && - GET_CODE (operands[1]) != REG) - operands[1] = force_reg (SImode, operands[1]); -}") - -;; Reject both args with `general_operand' if not reloading because a -;; mem -> mem move that was split by 'movsi' can be recombined to -;; mem -> mem by the combiner. -;; -;; As a pseudo register can end up in a stack slot during reloading we must -;; allow a r->m move for the next pattern. -;; The first predicate must be `general_operand' because a predicate must -;; be true for each constraint. -;; -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,m") - (match_operand:SI 1 "general_operand" "r,m,n,i,r"))] - "reload_in_progress || register_operand (operands[0], SImode)" - "* -{ - int val; - - if (which_alternative == 0) - return \"movw %1,%0\"; /* reg -> reg */ - - if (which_alternative == 1) - return \"loadw %1,%0\"; /* mem -> reg */ - - if (which_alternative == 2) - { - val = INTVAL (operands[1]); /* known const ->reg */ - - if (val == -1) - return \"notq $0,%0\"; - - if (val < 0 || val >= 16) - return \"loadi %1,%0\"; - - return \"loadq %1,%0\"; - } - - if (which_alternative == 3) /* unknown const */ - return \"loada %a1,%0\"; - - return \"storw %1,%0\"; -}" -[(set_attr "type" "arith,load,arith,load,store") - (set_attr "cc" "set2,change0,set1,change0,unchanged")]) - - -(define_insn "" - [(set (match_operand:SI 0 "memory_operand" "=m") - (match_operand:SI 1 "int_reg_operand" "r"))] - "" - "storw %1,%0" -[(set_attr "type" "store")]) - -;; movhi -;; -;; loadh mem to reg -;; storh reg to mem -;; -;; -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! register_operand (operands[1], HImode)) - operands[1] = force_reg (HImode, operands[1]); -}") - - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r,r") - (match_operand:HI 1 "general_operand" "r,m,n"))] - "" - "@ - movw %1,%0 - loadh %1,%0 - loadi %1,%0" -[(set_attr "type" "arith,load,arith")]) - -(define_insn "" - [(set (match_operand:HI 0 "memory_operand" "=m") - (match_operand:HI 1 "register_operand" "r"))] - "" - "storh %1,%0" - [(set_attr "type" "store")]) - -;; movqi -;; -;; loadb mem to reg -;; storb reg to mem -;; -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && - ! register_operand (operands[1], QImode)) - operands[1] = force_reg (QImode, operands[1]); -}") - - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r,r,r") - (match_operand:QI 1 "general_operand" "r,m,n"))] - "" - "@ - movw %1,%0 - loadb %1,%0 - loadi %1,%0" -[(set_attr "type" "arith,load,arith")]) - -(define_insn "" - [(set (match_operand:QI 0 "memory_operand" "=m") - (match_operand:QI 1 "register_operand" "r"))] - "" - "storb %1,%0" -[(set_attr "type" "store")]) - - -;; -;; block move -;; -(define_expand "movstrsi" - [(parallel - [(set (match_operand:BLK 0 "memory_operand" "") - (match_operand:BLK 1 "memory_operand" "")) - (use (match_operand:SI 2 "general_operand" "")) - (use (match_operand:SI 3 "const_int_operand" "")) - (clobber (match_scratch:SI 4 "")) - (clobber (match_scratch:SI 5 "")) - (clobber (match_dup 6)) - (clobber (match_dup 7))])] - "" - " -{ - rtx addr0, addr1; - - addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - - operands[6] = addr0; - operands[7] = addr1; - - operands[0] = change_address (operands[0], VOIDmode, addr0); - operands[1] = change_address (operands[1], VOIDmode, addr1); - - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = force_reg (SImode, operands[2]); -}") - -;; -;; there is a problem with this insn in gcc-2.2.3 -;; (clobber (match_dup 2)) does not prevent use of this operand later -;; we always use a scratch register and leave operand 2 unchanged -;; -(define_insn "" - [(set (mem:BLK (match_operand:SI 0 "register_operand" "r")) - (mem:BLK (match_operand:SI 1 "register_operand" "r"))) - (use (match_operand:SI 2 "nonmemory_operand" "rn")) - (use (match_operand:SI 3 "const_int_operand" "n")) - (clobber (match_scratch:SI 4 "=r")) - (clobber (match_scratch:SI 5 "=r")) - (clobber (match_dup 0)) - (clobber (match_dup 1))] - "" - "* -{ - extern void clipper_movstr (); - clipper_movstr (operands); - return \"\"; -}" -[(set_attr "cc" "clobber")]) - - - -;; Extension and truncation insns. -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r") - (sign_extend:SI (match_operand:HI 1 "general_operand" "0,m")))] - "" - "@ - andi $65535,%0\;xori $32768,%0\;subi $32768,%0 - loadh %1,%0" -[(set_attr "type" "arith,load")]) - - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "int_reg_operand" "=r,r") - (sign_extend:HI (match_operand:QI 1 "general_operand" "0,m")))] - "" - "@ - andi $255,%0\;xori $128,%0\;subi $128,%0 - loadb %1,%0" -[(set_attr "type" "arith,load") - (set_attr "cc" "set1,change0")]) - - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r") - (sign_extend:SI (match_operand:QI 1 "general_operand" "0,m")))] - "" - "@ - andi $255,%0\;xori $128,%0\;subi $128,%0 - loadb %1,%0" -[(set_attr "type" "arith,load")]) - - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "fp_reg_operand" "=f") - (float_extend:DF (match_operand:SF 1 "fp_reg_operand" "f")))] - "" - "cnvsd %1,%0") - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "fp_reg_operand" "=f") - (float_truncate:SF (match_operand:DF 1 "fp_reg_operand" "f")))] - "" - "cnvds %1,%0") - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r") - (zero_extend:SI (match_operand:HI 1 "general_operand" "0,m")))] - "" - "@ - andi $65535,%0 - loadhu %1,%0" -[(set_attr "type" "arith,load")]) - - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "int_reg_operand" "=r,r") - (zero_extend:HI (match_operand:QI 1 "general_operand" "0,m")))] - "" - "@ - andi $255,%0 - loadbu %1,%0" -[(set_attr "type" "arith,load") - (set_attr "cc" "clobber,clobber")]) - - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r") - (zero_extend:SI (match_operand:QI 1 "general_operand" "0,m")))] - "" - "@ - andi $255,%0 - loadbu %1,%0" -[(set_attr "type" "arith,load")]) - - - -;; Fix-to-float conversion insns. - -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "fp_reg_operand" "=f") - (float:SF (match_operand:SI 1 "int_reg_operand" "r")))] - "" - "cnvws %1,%0") - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "fp_reg_operand" "=f") - (float:DF (match_operand:SI 1 "int_reg_operand" "r")))] - "" - "cnvwd %1,%0") - - -;; Float-to-fix conversion insns. - -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (fix:SI (fix:SF (match_operand:SF 1 "fp_reg_operand" "f"))))] - "" - "cnvtsw %1,%0") - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (fix:SI (fix:DF (match_operand:DF 1 "fp_reg_operand" "f"))))] - "" - "cnvtdw %1,%0") - -;;- All kinds of add instructions. - -(define_insn "adddf3" - [(set (match_operand:DF 0 "fp_reg_operand" "=f") - (plus:DF (match_operand:DF 1 "fp_reg_operand" "0") - (match_operand:DF 2 "fp_reg_operand" "f")))] - "" - "addd %2,%0" - [(set_attr "type" "fp")]) - - -(define_insn "addsf3" - [(set (match_operand:SF 0 "fp_reg_operand" "=f") - (plus:SF (match_operand:SF 1 "fp_reg_operand" "0") - (match_operand:SF 2 "fp_reg_operand" "f")))] - "" - "adds %2,%0" - [(set_attr "type" "fp")]) - -(define_insn "adddi3" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (plus:DI (match_operand:DI 1 "int_reg_operand" "%0") - (match_operand:DI 2 "int_reg_operand" "r")))] - "" - "* -{ - rtx xoperands[4]; - - xoperands[0] = operands[0]; - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - xoperands[2] = operands[2]; - xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1); - output_asm_insn (\"addw %2,%0\;addwc %3,%1\", xoperands); - return \"\"; -}" -[(set_attr "type" "arith") - (set_attr "cc" "clobber")]) - -(define_insn "addsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r,r") - (plus:SI (match_operand:SI 1 "int_reg_operand" "%0,r,r") - (match_operand:SI 2 "nonmemory_operand" "rn,0,rn")))] - "" - "* -{ - if (which_alternative == 2) /* 3 address version */ - { - if (GET_CODE (operands[2]) == CONST_INT) - return \"loada %a2(%1),%0\"; - return \"loada [%2](%1),%0\"; - } - /* 2 address version */ - if (GET_CODE (operands[2]) == CONST_INT) - { - int val = INTVAL (operands[2]); - - if (val >= 16 || val == 0x80000000) - return \"addi %2,%0\"; - - if (val < 0) /* change to sub */ - { - rtx xops[2]; - - val = -val; - - xops[0] = operands[0]; - xops[1] = GEN_INT (val); - - if (val >= 16) - output_asm_insn (\"subi %1,%0\", xops); - else - output_asm_insn (\"subq %1,%0\", xops); - - return \"\"; - } - - return \"addq %2,%0\"; - } - - if (which_alternative == 0) - return \"addw %2,%0\"; - - return \"addw %1,%0\"; -}" -[(set_attr "type" "arith,arith,arith") - (set_attr "cc" "set1,set1,change0")]) - - -;;- All kinds of subtract instructions. - -(define_insn "subdi3" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (minus:DI (match_operand:DI 1 "int_reg_operand" "0") - (match_operand:DI 2 "int_reg_operand" "r")))] - "" - "* -{ - rtx xoperands[4]; - - xoperands[0] = operands[0]; - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - xoperands[2] = operands[2]; - xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1); - output_asm_insn (\"subw %2,%0\;subwc %3,%1\", xoperands); - return \"\"; -}" -[(set_attr "type" "arith") - (set_attr "cc" "clobber")]) - -(define_insn "subsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (minus:SI (match_operand:SI 1 "int_reg_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "rn")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - int val = INTVAL (operands[2]); - - if (val < 0 || val >= 16) - return \"subi %2,%0\"; - else - return \"subq %2,%0\"; - } - - return \"subw %2,%0\"; -}" -[(set_attr "type" "arith")]) - -(define_insn "subdf3" - [(set (match_operand:DF 0 "fp_reg_operand" "=f") - (minus:DF (match_operand:DF 1 "fp_reg_operand" "0") - (match_operand:DF 2 "fp_reg_operand" "f")))] - "" - "subd %2,%0" - [(set_attr "type" "fp")]) - -(define_insn "subsf3" - [(set (match_operand:SF 0 "fp_reg_operand" "=f") - (minus:SF (match_operand:SF 1 "fp_reg_operand" "0") - (match_operand:SF 2 "fp_reg_operand" "f")))] - "" - "subs %2,%0" - [(set_attr "type" "fp")]) - - -;;- Multiply instructions. - -(define_insn "muldf3" - [(set (match_operand:DF 0 "fp_reg_operand" "=f") - (mult:DF (match_operand:DF 1 "fp_reg_operand" "0") - (match_operand:DF 2 "fp_reg_operand" "f")))] - "" - "muld %2,%0" - [(set_attr "type" "fp")]) - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "fp_reg_operand" "=f") - (mult:SF (match_operand:SF 1 "fp_reg_operand" "0") - (match_operand:SF 2 "fp_reg_operand" "f")))] - "" - "muls %2,%0" - [(set_attr "type" "fp")]) - -(define_insn "mulsidi3" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (mult:DI (sign_extend:DI (match_operand:SI 1 "int_reg_operand" "%0")) - (sign_extend:DI (match_operand:SI 2 "int_reg_operand" "r"))))] - "" - "mulwx %2,%0" -[(set_attr "type" "arith") - (set_attr "cc" "clobber")]) - -(define_insn "umulsidi3" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (mult:DI (zero_extend:DI (match_operand:SI 1 "int_reg_operand" "%0")) - (zero_extend:DI (match_operand:SI 2 "int_reg_operand" "r"))))] - "" - "mulwux %2,%0" -[(set_attr "type" "arith") - (set_attr "cc" "clobber")]) - -(define_insn "mulsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (mult:SI (match_operand:SI 1 "int_reg_operand" "%0") - (match_operand:SI 2 "int_reg_operand" "r")))] - "" - "mulw %2,%0" - [(set_attr "type" "arith") - (set_attr "cc" "clobber")]) - - -;;- Divide and mod instructions. - -(define_insn "divdf3" - [(set (match_operand:DF 0 "fp_reg_operand" "=f") - (div:DF (match_operand:DF 1 "fp_reg_operand" "0") - (match_operand:DF 2 "fp_reg_operand" "f")))] - "" - "divd %2,%0" - [(set_attr "type" "fp")]) - -(define_insn "divsf3" - [(set (match_operand:SF 0 "fp_reg_operand" "=f") - (div:SF (match_operand:SF 1 "fp_reg_operand" "0") - (match_operand:SF 2 "fp_reg_operand" "f")))] - "" - "divs %2,%0" - [(set_attr "type" "fp")]) - -(define_insn "divsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (div:SI (match_operand:SI 1 "int_reg_operand" "0") - (match_operand:SI 2 "int_reg_operand" "r")))] - "" - "divw %2,%0" - [(set_attr "type" "arith") - (set_attr "cc" "clobber")]) - -(define_insn "udivsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (udiv:SI (match_operand:SI 1 "int_reg_operand" "0") - (match_operand:SI 2 "int_reg_operand" "r")))] - "" - "divwu %2,%0" - [(set_attr "type" "arith") - (set_attr "cc" "clobber")]) - - -(define_insn "modsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (mod:SI (match_operand:SI 1 "int_reg_operand" "0") - (match_operand:SI 2 "int_reg_operand" "r")))] - "" - "modw %2,%0" - [(set_attr "type" "arith") - (set_attr "cc" "clobber")]) - -(define_insn "umodsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (umod:SI (match_operand:SI 1 "int_reg_operand" "0") - (match_operand:SI 2 "int_reg_operand" "r")))] - "" - "modwu %2,%0" - [(set_attr "type" "arith") - (set_attr "cc" "clobber")]) - -;; -;; bit and/or instructions -;; -(define_insn "andsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r") - (and:SI (match_operand:SI 1 "int_reg_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] - "" - "@ - andw %2,%0 - andi %2,%0" - [(set_attr "type" "arith")]) - -(define_insn "iorsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r") - (ior:SI (match_operand:SI 1 "int_reg_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] - "" - "@ - orw %2,%0 - ori %2,%0" - [(set_attr "type" "arith")]) - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r") - (xor:SI (match_operand:SI 1 "int_reg_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] - "" - "@ - xorw %2,%0 - xori %2,%0" - [(set_attr "type" "arith")]) - -(define_insn "negdf2" - [(set (match_operand:DF 0 "fp_reg_operand" "=f") - (neg:DF (match_operand:DF 1 "fp_reg_operand" "f")))] - "" - "negd %1,%0" - [(set_attr "type" "fp")]) - -(define_insn "negsf2" - [(set (match_operand:SF 0 "fp_reg_operand" "=f") - (neg:SF (match_operand:SF 1 "fp_reg_operand" "f")))] - "" - "negs %1,%0" - [(set_attr "type" "fp")]) - -(define_insn "negsi2" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (neg:SI (match_operand:SI 1 "int_reg_operand" "r")))] - "" - "negw %1,%0" - [(set_attr "type" "arith")]) - - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (not:SI (match_operand:SI 1 "int_reg_operand" "r")))] - "" - "notw %1,%0" - [(set_attr "type" "arith")]) - - - -;; Right shift on the clipper works by negating the shift count, -;; then emitting a right shift with the shift count negated. This means -;; that all actual shift counts in the RTL will be positive. - -(define_expand "ashrdi3" - [(set (match_operand:DI 0 "int_reg_operand" "") - (ashiftrt:DI (match_operand:DI 1 "int_reg_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (ashiftrt:DI (match_operand:DI 1 "int_reg_operand" "0") - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "shali $%n2,%0" - [(set_attr "type" "arith")]) - -(define_insn "" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (ashiftrt:DI (match_operand:DI 1 "int_reg_operand" "0") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))] - "" - "shal %2,%0" - [(set_attr "type" "arith")]) - -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "int_reg_operand" "") - (ashiftrt:SI (match_operand:SI 1 "int_reg_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "int_reg_operand" "0") - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "shai $%n2,%0" - [(set_attr "type" "arith")]) - -(define_insn "" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "int_reg_operand" "0") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))] - "" - "shaw %2,%0" - [(set_attr "type" "arith")]) - -;; -;; left shift -;; - -(define_insn "ashldi3" - [(set (match_operand:DI 0 "int_reg_operand" "=r,r") - (ashift:DI (match_operand:DI 1 "int_reg_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] - "" - "@ - shal %2,%0 - shali %2,%0" - [(set_attr "type" "arith")]) - - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r") - (ashift:SI (match_operand:SI 1 "int_reg_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] - "" - "* -{ - int val; - - if (which_alternative == 0) - return \"shaw %2,%0\"; - - val = INTVAL (operands[2]); - - if (val == 2) - return \"addw %0,%0\;addw %0,%0\"; - - if (val == 1) - return \"addw %0,%0\"; - - return \"shai %2,%0\"; -}" -[(set_attr "type" "arith")]) - -;; -;; logical shift -;; - -(define_expand "lshrdi3" - [(set (match_operand:DI 0 "int_reg_operand" "") - (lshiftrt:DI (match_operand:DI 1 "int_reg_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (lshiftrt:DI (match_operand:DI 1 "int_reg_operand" "0") - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "shlli $%n2,%0" - [(set_attr "type" "arith")]) - -(define_insn "" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (lshiftrt:DI (match_operand:DI 1 "int_reg_operand" "0") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))] - "" - "shll %2,%0" - [(set_attr "type" "arith")]) - -(define_expand "lshrsi3" - [(set (match_operand:SI 0 "int_reg_operand" "") - (lshiftrt:SI (match_operand:SI 1 "int_reg_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "int_reg_operand" "0") - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "shli $%n2,%0" - [(set_attr "type" "arith")]) - -(define_insn "" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "int_reg_operand" "0") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))] - "" - "shlw %2,%0" - [(set_attr "type" "arith")]) - - -;; -;; rotate insn -;; -(define_expand "rotrdi3" - [(set (match_operand:DI 0 "int_reg_operand" "") - (rotatert:DI (match_operand:DI 1 "int_reg_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (rotatert:DI (match_operand:DI 1 "int_reg_operand" "0") - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "rotli $%n2,%0" - [(set_attr "type" "arith")]) - -(define_insn "" - [(set (match_operand:DI 0 "int_reg_operand" "=r") - (rotatert:DI (match_operand:DI 1 "int_reg_operand" "0") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))] - "" - "rotl %2,%0" - [(set_attr "type" "arith")]) - -(define_expand "rotrsi3" - [(set (match_operand:SI 0 "int_reg_operand" "") - (rotatert:SI (match_operand:SI 1 "int_reg_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (rotatert:SI (match_operand:SI 1 "int_reg_operand" "0") - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "roti $%n2,%0" - [(set_attr "type" "arith")]) - -(define_insn "" - [(set (match_operand:SI 0 "int_reg_operand" "=r") - (rotatert:SI (match_operand:SI 1 "int_reg_operand" "0") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))] - "" - "rotw %2,%0" - [(set_attr "type" "arith")]) - -(define_insn "rotldi3" - [(set (match_operand:DI 0 "int_reg_operand" "=r,r") - (rotate:DI (match_operand:DI 1 "int_reg_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] - "" - "@ - rotl %2,%0 - rotli %2,%0" - [(set_attr "type" "arith")]) - -(define_insn "rotlsi3" - [(set (match_operand:SI 0 "int_reg_operand" "=r,r") - (rotate:SI (match_operand:SI 1 "int_reg_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] - "" - "@ - rotw %2,%0 - roti %2,%0" - [(set_attr "type" "arith")]) - - -;; -;; jump and branch insns -;; -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "b %l0" - [(set_attr "type" "branch")]) - -(define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "register_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "" - "b (%0)" - [(set_attr "type" "branch")]) - -(define_insn "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "breq %l0" - [(set_attr "type" "branch")]) - -(define_insn "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "brne %l0" - [(set_attr "type" "branch")]) - -(define_insn "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "brgt %l0" - [(set_attr "type" "branch")]) - -(define_insn "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "brgtu %l0" - [(set_attr "type" "branch")]) - -(define_insn "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "brlt %l0" - [(set_attr "type" "branch")]) - -(define_insn "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "brltu %l0" - [(set_attr "type" "branch")]) - -(define_insn "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "brge %l0" - [(set_attr "type" "branch")]) - -(define_insn "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "brgeu %l0" - [(set_attr "type" "branch")]) - -(define_insn "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "brle %l0" - [(set_attr "type" "branch")]) - -(define_insn "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "brleu %l0" - [(set_attr "type" "branch")]) - -;; Recognize reversed jumps. -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(cc0) - (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "br%C0 %l1" ; %C0 negates condition - [(set_attr "type" "branch")]) - -;; -;; call instructions -;; -(define_insn "call" - [(call (match_operand:QI 0 "general_operand" "m") - (match_operand:SI 1 "general_operand" ""))] - ;; Operand 1 not used on the clipper. - "" - "call sp,%0") - -(define_insn "call_value" - [(set (match_operand 0 "" "=rf") - (call (match_operand:QI 1 "general_operand" "m") - (match_operand:SI 2 "general_operand" "g")))] - ;; Operand 2 not used on the clipper - "" - "call sp,%1") - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "") - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "r"))] - "" - "b (%0)" - [(set_attr "type" "branch")]) - - -(define_insn "nop" - [(const_int 0)] - "" - "noop" - [(set_attr "type" "arith") - (set_attr "cc" "unchanged")]) - - - -;; while (--foo >= 0) -;; -;; Combiners for 'decrement test and branch' do not work for clipper. -;; These patters are jump_insns that do not allow output reloads and clipper -;; can only decrement and test registers. -;; diff --git a/gcc/config/clipper/clix.h b/gcc/config/clipper/clix.h deleted file mode 100755 index c36e4de..0000000 --- a/gcc/config/clipper/clix.h +++ /dev/null @@ -1,162 +0,0 @@ -/* Definitions of target machine for GNU compiler. Clipper/Clix version. - Copyright (C) 1988, 1993, 1996, 1997 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Names to predefine in the preprocessor for this target machine. */ - -#define CPP_PREDEFINES "-Dclipper -Dunix -Asystem(unix) -Asystem(svr3) -Acpu(clipper) -Amachine(clipper)" - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}} crtbegin.o%s" - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend.o%s crtn.o%s" - -#undef LIB_SPEC - -#define TARGET_MEM_FUNCTIONS - -#undef HAVE_ATEXIT -#define HAVE_ATEXIT - -#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \ -do { \ - unsigned char *s; \ - int i; \ - for (i = 0, s = (unsigned char *)(PTR); i < (LEN); s++, i++) \ - { \ - if ((i % 8) == 0) \ - fputs ("\n\t.byte\t", (FILE)); \ - fprintf ((FILE), "%s0x%x", (i%8?",":""), (unsigned)*s); \ - } \ - fputs ("\n", (FILE)); \ -} while (0) - -#undef ASM_OUTPUT_DOUBLE -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ -{ \ - union { int i[2]; double d; } _d_; \ - _d_.d = VALUE; \ - fprintf (FILE, "\t.long 0x%08x,0x%08x\n", _d_.i[0],_d_.i[1]); \ -} - -#undef ASM_OUTPUT_FLOAT -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ -{ \ - union { int i; float f; } _f_; \ - _f_.f = VALUE; \ - fprintf (FILE, "\t.long 0x%08x\n", _f_.i); \ -} - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - fprintf(FILE, "\t.align %d\n", 1 << (LOG)) - - -#define ASM_LONG ".long" -#define BSS_SECTION_ASM_OP ".bss" -#undef INIT_SECTION_ASM_OP -#define INIT_SECTION_ASM_OP ".section .init,\"x\"" - - -/* Define a few machine-specific details of the implementation of - constructors. - - The __CTORS_LIST__ goes in the .init section. Define CTOR_LIST_BEGIN - and CTOR_LIST_END to contribute to the .init section an instruction to - push a word containing 0 (or some equivalent of that). - - ASM_OUTPUT_CONSTRUCTOR should be defined to push the address of the - constructor. */ - -#define CTOR_LIST_BEGIN \ - asm (INIT_SECTION_ASM_OP); \ - asm ("subq $8,sp"); \ - asm ("loadq $0,r0"); \ - asm ("storw r0,(sp)") - -/* don't need end marker */ - -#undef CTOR_LIST_END - -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - init_section (); \ - fputs ("\tloada ", FILE); \ - assemble_name (FILE, NAME); \ - fputs (",r0\n\tsubq $8,sp\n\tstorw r0,(sp)\n", FILE); \ - } while (0) - - -/* fini psect is 8 aligned */ - -#define DTOR_LIST_BEGIN \ - asm (DTORS_SECTION_ASM_OP); \ - func_ptr __DTOR_LIST__[2] = { (func_ptr) (-1), 0 }; - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ - -#undef ASM_OUTPUT_DESTRUCTOR -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - fini_section (); \ - fprintf (FILE, "%s\t ", ASM_LONG); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ",0\n"); \ - } while (0) - - -/* On clix crt1.o first calls init code and then sets environ and a valid - chrclass. Unfortunately stdio routines bomb with unset chrclass. - Therefore we set chrclass prior to calling global constructors. */ - -#undef DO_GLOBAL_CTORS_BODY -#define DO_GLOBAL_CTORS_BODY \ -do { \ - func_ptr *p, *beg = alloca (0); \ - _setchrclass (0); \ - for (p = beg; *p; p+=2) \ - ; \ - while (p != beg) \ - { p-= 2; (*p) (); } \ -} while (0) - - -#undef DO_GLOBAL_DTORS_BODY -#define DO_GLOBAL_DTORS_BODY \ - func_ptr *f = &__DTOR_LIST__[2]; /* 0,1 contains -1,0 */ \ - int n = 0; \ - while (*f) \ - { \ - f+= 2; /* skip over alignment 0 */ \ - n++; \ - } \ - f -= 2; \ - while (--n >= 0) \ - { \ - (*f) (); \ - f-= 2; /* skip over alignment 0 */ \ - } - - diff --git a/gcc/config/clipper/x-clix b/gcc/config/clipper/x-clix deleted file mode 100755 index 155161f..0000000 --- a/gcc/config/clipper/x-clix +++ /dev/null @@ -1 +0,0 @@ -ALLOCA = alloca.o diff --git a/gcc/config/clipper/xm-clix.h b/gcc/config/clipper/xm-clix.h deleted file mode 100755 index 726660d..0000000 --- a/gcc/config/clipper/xm-clix.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Config file for Clipper running Clix, system V. 3.2 clone */ - - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ - -#include "tm.h" - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 8 -#define HOST_BITS_PER_SHORT 16 -#define HOST_BITS_PER_INT 32 -#define HOST_BITS_PER_LONG 32 -#define HOST_BITS_PER_LONGLONG 64 - -/* This machine uses IEEE floats. */ -/* #define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT */ - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* isinf isn't there, but finite is. */ -#define isinf(x) (!finite(x)) - -#define USG diff --git a/gcc/config/convex/convex.c b/gcc/config/convex/convex.c deleted file mode 100755 index cd2eb55..0000000 --- a/gcc/config/convex/convex.c +++ /dev/null @@ -1,675 +0,0 @@ -/* Subroutines for insn-output.c for Convex. - Copyright (C) 1988, 1993, 1994, 1997 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include -#include "tree.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "insn-attr.h" -#include "output.h" -#include "expr.h" - -/* Tables used in convex.h */ - -char regno_ok_for_index_p_base[1 + LAST_VIRTUAL_REGISTER + 1]; -enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER]; -enum reg_class reg_class_from_letter[256]; - -/* Target cpu index. */ - -int target_cpu; - -/* Boolean to keep track of whether the current section is .text or not. - Used by .align handler in convex.h. */ - -int current_section_is_text; - -/* Communication between output_compare and output_condjump. */ - -static rtx cmp_operand0, cmp_operand1; -static char cmp_modech; - -/* Forwards */ - -static rtx frame_argblock; -static int frame_argblock_size; -static rtx convert_arg_pushes (); -static void expand_movstr_call (); - -/* Here from OVERRIDE_OPTIONS at startup. Initialize constant tables. */ - -init_convex () -{ - int regno; - - /* Set A and S reg classes. */ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (A_REGNO_P (regno)) - { - regno_ok_for_index_p[regno] = 1; - regno_reg_class[regno] = INDEX_REGS; - } - else - { - regno_ok_for_index_p[regno] = 0; - regno_reg_class[regno] = S_REGS; - } - - /* Can't index off the stack pointer, register 0. */ - regno_ok_for_index_p[STACK_POINTER_REGNUM] = 0; - regno_reg_class[STACK_POINTER_REGNUM] = SP_REGS; - - /* Can't index off aliases of the stack pointer. */ - regno_ok_for_index_p[VIRTUAL_INCOMING_ARGS_REGNUM] = 1; - regno_ok_for_index_p[VIRTUAL_STACK_VARS_REGNUM] = 1; - regno_ok_for_index_p[VIRTUAL_STACK_DYNAMIC_REGNUM] = 0; - regno_ok_for_index_p[VIRTUAL_OUTGOING_ARGS_REGNUM] = 0; - - /* Can't index off hard reg -1 == pseudos not assigned */ - regno_ok_for_index_p[-1] = 0; - - /* Set reg class letters */ - reg_class_from_letter['a'] = A_REGS; - reg_class_from_letter['A'] = INDEX_REGS; - reg_class_from_letter['d'] = S_REGS; - - /* Turn off floating point exception enables in the psw. */ - psw_disable_float (); -} - -psw_disable_float () -{ -#if __convex__ && __GNUC__ - register int *p; - asm ("mov fp,%0" : "=a" (p)); - while (p) - { - p[1] &= ~0x1000c400; - p = (int *) p[2]; - } -#endif -} - -/* Here to output code for a compare insn. Output nothing, just - record the operands and their mode. */ - -char * -output_cmp (operand0, operand1, modech) - rtx operand0, operand1; - char modech; -{ - cmp_operand0 = operand0; - cmp_operand1 = operand1; - cmp_modech = modech; - return ""; -} - -/* Output code for a conditional jump. The preceding instruction - is necessarily a compare. Output two instructions, for example - eq.w a1,a2 - jbra.t L5 - for - (cmpsi a1 a2) - (beq L5) - */ - -char * -output_condjump (label, cond, jbr_sense) - rtx label; - char *cond; - char jbr_sense; -{ - rtx operands[3]; - char cmp_op[4]; - char buf[80]; - char jbr_regch; - - strcpy (cmp_op, cond); - - /* [BL] mean the value is being compared against immediate 0. - Use neg.x, which produces the same carry that eq.x #0 would if it - existed. In this case operands[1] is a scratch register, not a - compare operand. */ - - if (cmp_modech == 'B' || cmp_modech == 'L') - { - cmp_modech = cmp_modech - 'A' + 'a'; - strcpy (cmp_op, "neg"); - } - - /* [WH] mean the value being compared resulted from "add.[wh] #-1,rk" - when rk was nonnegative -- we can omit equality compares against -1 - or inequality compares against 0. */ - - else if (cmp_modech == 'W' || cmp_modech == 'H') - { - if (! strcmp (cmp_op, "eq") && cmp_operand1 == constm1_rtx) - jbr_sense ^= 't' ^ 'f'; - else if (! strcmp (cmp_op, "lt") && cmp_operand1 == const0_rtx) - ; - else - cmp_modech = cmp_modech - 'A' + 'a'; - } - - /* Constant must be first; swap operands if necessary. - If lt, le, ltu, leu are swapped, change to le, lt, leu, ltu - and reverse the sense of the jump. */ - - if (! REG_P (cmp_operand1)) - { - operands[0] = cmp_operand1; - operands[1] = cmp_operand0; - if (cmp_op[0] == 'l') - { - cmp_op[1] ^= 'e' ^ 't'; - jbr_sense ^= 't' ^ 'f'; - } - } - else - { - operands[0] = cmp_operand0; - operands[1] = cmp_operand1; - } - - operands[2] = label; - - if (S_REG_P (operands[1])) - jbr_regch = 's'; - else if (A_REG_P (operands[1])) - jbr_regch = 'a'; - else - abort (); - - if (cmp_modech == 'W' || cmp_modech == 'H') - sprintf (buf, "jbr%c.%c %%l2", jbr_regch, jbr_sense); - else - sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2", - cmp_op, cmp_modech, jbr_regch, jbr_sense); - output_asm_insn (buf, operands); - return ""; -} - -/* Return 1 if OP is valid for cmpsf. - In IEEE mode, +/- zero compares are not handled by - the immediate versions of eq.s and on some machines, lt.s, and le.s. - So disallow 0.0 as the immediate operand of xx.s compares in IEEE mode. */ - -int -nonmemory_cmpsf_operand (op, mode) - rtx op; - enum machine_mode mode; -{ -#if _IEEE_FLOAT_ - if (op == CONST0_RTX (SFmode)) - return 0; -#endif - - return nonmemory_operand (op, mode); -} - -/* Convex /bin/as does not like unary minus in some contexts. - Simplify CONST addresses to remove it. */ - -rtx -simplify_for_convex (x) - rtx x; -{ - switch (GET_CODE (x)) - { - case MINUS: - if (GET_CODE (XEXP (x, 1)) == CONST_INT - && INTVAL (XEXP (x, 1)) < 0) - { - PUT_CODE (x, PLUS); - XEXP (x, 1) = GEN_INT (- INTVAL (XEXP (x, 1))); - } - break; - - case CONST: - return simplify_for_convex (XEXP (x, 0)); - } - - return x; -} - -/* Routines to separate CONST_DOUBLEs into component parts. */ - -int -const_double_high_int (x) - rtx x; -{ - if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) - return CONST_DOUBLE_LOW (x); - else - return CONST_DOUBLE_HIGH (x); -} - -int -const_double_low_int (x) - rtx x; -{ - if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) - return CONST_DOUBLE_HIGH (x); - else - return CONST_DOUBLE_LOW (x); -} - -/* Inline block copy. */ - -void -expand_movstr (operands) - rtx *operands; -{ - rtx dest = operands[0]; - rtx src = operands[1]; - int align = INTVAL (operands[3]); - int nregs, maxsize; - unsigned len; - enum machine_mode mode; - rtx reg, load, store, prev_store, prev_store_2; - int size; - - /* Decide how many regs to use, depending on load latency, and what - size pieces to move, depending on whether machine does unaligned - loads and stores efficiently. */ - - if (TARGET_C1) - { - /* ld.l latency is 4, no alignment problems. */ - nregs = 3, maxsize = 8; - } - else if (TARGET_C2) - { - /* loads are latency 2 if we avoid ld.l not at least word aligned. */ - if (align >= 4) - nregs = 2, maxsize = 8; - else - nregs = 2, maxsize = 4; - } - else if (TARGET_C34) - { - /* latency is 4 if aligned, horrible if not. */ - nregs = 3, maxsize = align; - } - else if (TARGET_C38) - { - /* latency is 2 if at least word aligned, 3 or 4 if unaligned. */ - if (align >= 4) - nregs = 2, maxsize = 8; - else - nregs = 3, maxsize = 8; - } - else - abort (); - - /* Caller is not necessarily prepared for us to fail in this - expansion. So fall back by generating memcpy call here. */ - - if (GET_CODE (operands[2]) != CONST_INT - || (len = INTVAL (operands[2])) > (unsigned) 32 * maxsize) - { - expand_movstr_call (operands); - return; - } - - reg = 0; - prev_store = prev_store_2 = 0; - - while (len > 0) - { - if (len >= 8 && maxsize >= 8) - mode = DImode; - else if (len >= 4 && maxsize >= 4) - mode = SImode; - else if (len >= 2 && maxsize >= 2) - mode = HImode; - else - mode = QImode; - - /* If no temp pseudo to reuse, or not the right mode, make one */ - if (! reg || GET_MODE (reg) != mode) - reg = gen_reg_rtx (mode); - - /* Get src and dest in the right mode */ - if (GET_MODE (src) != mode) - src = change_address (src, mode, 0), - dest = change_address (dest, mode, 0); - - /* Make load and store patterns for this piece */ - load = gen_rtx (SET, VOIDmode, reg, src); - store = gen_rtx (SET, VOIDmode, dest, reg); - - /* Emit the load and the store from last time. - When we emit a store, we can reuse its temp reg. */ - emit_insn (load); - if (prev_store) - { - reg = SET_SRC (prev_store); - emit_insn (prev_store); - } - else - reg = 0; - - /* Queue up the store, for next time or the time after that. */ - if (nregs == 2) - prev_store = store; - else - prev_store = prev_store_2, prev_store_2 = store; - - /* Advance to next piece. */ - size = GET_MODE_SIZE (mode); - src = adj_offsettable_operand (src, size); - dest = adj_offsettable_operand (dest, size); - len -= size; - } - - /* Finally, emit the last stores. */ - if (prev_store) - emit_insn (prev_store); - if (prev_store_2) - emit_insn (prev_store_2); -} - -static void -expand_movstr_call (operands) - rtx *operands; -{ - emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0, - VOIDmode, 3, - XEXP (operands[0], 0), Pmode, - XEXP (operands[1], 0), Pmode, - convert_to_mode (TYPE_MODE (sizetype), operands[2], - TREE_UNSIGNED (sizetype)), - TYPE_MODE (sizetype)); -} - -#if _IEEE_FLOAT_ -#define MAX_FLOAT 3.4028234663852886e+38 -#define MIN_FLOAT 1.1754943508222875e-38 -#else -#define MAX_FLOAT 1.7014117331926443e+38 -#define MIN_FLOAT 2.9387358770557188e-39 -#endif - -int -check_float_value (mode, dp, overflow) - enum machine_mode mode; - REAL_VALUE_TYPE *dp; - int overflow; -{ - REAL_VALUE_TYPE d = *dp; - - if (overflow) - { - *dp = MAX_FLOAT; - return 1; - } - - if (mode == SFmode) - { - if (d > MAX_FLOAT) - { - *dp = MAX_FLOAT; - return 1; - } - else if (d < -MAX_FLOAT) - { - *dp = -MAX_FLOAT; - return 1; - } - else if ((d > 0 && d < MIN_FLOAT) || (d < 0 && d > -MIN_FLOAT)) - { - *dp = 0.0; - return 1; - } - } - - return 0; -} - -/* Output the label at the start of a function. - Precede it with the number of formal args so debuggers will have - some idea of how many args to print. */ - -void -asm_declare_function_name (file, name, decl) - FILE *file; - char *name; - tree decl; -{ - tree parms; - int nargs = list_length (DECL_ARGUMENTS (decl)); - - char *p, c; - extern char *version_string; - static char vers[4]; - int i; - - p = version_string; - for (i = 0; i < 3; ) { - c = *p; - if (c - '0' < (unsigned) 10) - vers[i++] = c; - if (c == 0 || c == ' ') - vers[i++] = '0'; - else - p++; - } - fprintf (file, "\tds.b \"g%s\"\n", vers); - - if (nargs < 100) - fprintf (file, "\tds.b \"+%02d\\0\"\n", nargs); - else - fprintf (file, "\tds.b \"+00\\0\"\n"); - - ASM_OUTPUT_LABEL (file, name); -} - -/* Print an instruction operand X on file FILE. - CODE is the code from the %-spec that requested printing this operand; - if `%z3' was used to print operand 3, then CODE is 'z'. */ -/* Convex codes: - %u prints a CONST_DOUBLE's high word - %v prints a CONST_DOUBLE's low word - %z prints a CONST_INT shift count as a multiply operand -- viz. 1 << n. - */ - -print_operand (file, x, code) - FILE *file; - rtx x; - char code; -{ - long u[2]; - REAL_VALUE_TYPE d; - - switch (GET_CODE (x)) - { - case REG: - fprintf (file, "%s", reg_names[REGNO (x)]); - break; - - case MEM: - output_address (XEXP (x, 0)); - break; - - case CONST_DOUBLE: - REAL_VALUE_FROM_CONST_DOUBLE (d, x); - switch (GET_MODE (x)) { - case DFmode: -#if 0 /* doesn't work, produces dfloats */ - REAL_VALUE_TO_TARGET_DOUBLE (d, u); -#else - { - union { double d; int i[2]; } t; - t.d = d; - u[0] = t.i[0]; - u[1] = t.i[1]; - } -#endif - if (code == 'u') - fprintf (file, "#%#x", u[0]); - else if (code == 'v') - fprintf (file, "#%#x", u[1]); - else - outfloat (file, d, "%.17e", "#", ""); - break; - case SFmode: - outfloat (file, d, "%.9e", "#", ""); - break; - default: - if (code == 'u') - fprintf (file, "#%d", CONST_DOUBLE_HIGH (x)); - else - fprintf (file, "#%d", CONST_DOUBLE_LOW (x)); - } - break; - - default: - if (code == 'z') - { - if (GET_CODE (x) != CONST_INT) - abort (); - fprintf (file, "#%d", 1 << INTVAL (x)); - } - else - { - putc ('#', file); - output_addr_const (file, x); - } - } -} - -/* Print a memory operand whose address is X, on file FILE. */ - -print_operand_address (file, addr) - FILE *file; - rtx addr; -{ - rtx index = 0; - rtx offset = 0; - - if (GET_CODE (addr) == MEM) - { - fprintf (file, "@"); - addr = XEXP (addr, 0); - } - - switch (GET_CODE (addr)) - { - case REG: - index = addr; - break; - - case PLUS: - index = XEXP (addr, 0); - if (REG_P (index)) - offset = XEXP (addr, 1); - else - { - offset = XEXP (addr, 0); - index = XEXP (addr, 1); - if (! REG_P (index)) - abort (); - } - break; - - default: - offset = addr; - break; - } - - if (offset) - output_addr_const (file, offset); - - if (index) - fprintf (file, "(%s)", reg_names[REGNO (index)]); -} - -/* Output a float to FILE, value VALUE, format FMT, preceded by PFX - and followed by SFX. */ - -outfloat (file, value, fmt, pfx, sfx) - FILE *file; - REAL_VALUE_TYPE value; - char *fmt, *pfx, *sfx; -{ - char buf[64]; - fputs (pfx, file); - REAL_VALUE_TO_DECIMAL (value, fmt, buf); - fputs (buf, file); - fputs (sfx, file); -} - -/* Here during RTL generation of return. If we are at the final return - in a function, go through the function and replace pushes with stores - into a frame arg block. This is similar to what ACCUMULATE_OUTGOING_ARGS - does, but we must index off the frame pointer, not the stack pointer, - and the calling sequence does not require the arg block to be at the - top of the stack. */ - -replace_arg_pushes () -{ - /* Doesn't work yet. */ -} - -/* Output the insns needed to do a call. operands[] are - 0 - MEM, the place to call - 1 - CONST_INT, the number of bytes in the arg list - 2 - CONST_INT, the number of arguments - 3 - CONST_INT, the number of bytes to pop - 4 - address of the arg list. - */ - -char * -output_call (insn, operands) - rtx insn, *operands; -{ - if (operands[4] == stack_pointer_rtx) - output_asm_insn ("mov sp,ap", operands); - else - abort (); - - if (TARGET_ARGCOUNT) - output_asm_insn ("pshea %a2", operands); - - output_asm_insn ("calls %0", operands); - - output_asm_insn ("ld.w 12(fp),ap", operands); - - if (operands[4] == stack_pointer_rtx && operands[3] != const0_rtx) - output_asm_insn ("add.w %3,sp", operands); - - return ""; -} - - -/* Here after reloading, before the second scheduling pass. */ - -emit_ap_optimizations () -{ - /* Removed for now. */ -} - diff --git a/gcc/config/convex/convex.h b/gcc/config/convex/convex.h deleted file mode 100755 index f455f96..0000000 --- a/gcc/config/convex/convex.h +++ /dev/null @@ -1,1503 +0,0 @@ -/* Definitions of target machine for GNU compiler. Convex version. - Copyright (C) 1988, 1994, 1995, 1996 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -/* Standard GCC variables that we reference. */ - -extern int target_flags; - -/* Convex machine-specific flags - -mc1 target instruction set, libraries, scheduling - -mc2 - -mc32 - -mc34 - -mc38 - -margcount use standard calling sequence, with arg count word - -mno-argcount don't push arg count, depend on symbol table - -margcount-nop place arg count in a nop instruction (faster than push) - -mvolatile-cache use data cache for volatile mem refs (default) - -mvolatile-nocache bypass data cache for volatile mem refs - -mlong32 cc- and libc-compatible 32-bit longs - -mlong64 64-bit longs -*/ - -/* Macro to define tables used to set -mXXX 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. */ - -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT 0 -#endif - -#define TARGET_SWITCHES \ - { { "c1", 001 }, \ - { "c2", 002 }, \ - { "c32", 004 }, \ - { "c34", 010 }, \ - { "c38", 020 }, \ - { "argcount", 0100 }, \ - { "argcount-nop", 0200 }, \ - { "no-argcount", -0300 }, \ - { "volatile-cache", -0400 }, \ - { "no-volatile-cache", 0400 }, \ - { "volatile-nocache", 0400 }, \ - { "long64", 01000 }, \ - { "long32", -01000 }, \ - { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}} - -/* Macros used in the machine description to test the flags. */ - -#define TARGET_C1 (target_cpu == 0) -#define TARGET_C2 (target_cpu == 1) -#define TARGET_C34 (target_cpu == 2) -#define TARGET_C38 (target_cpu == 3) -#define TARGET_ARGCOUNT (target_flags & 0100) -#define TARGET_ARGCOUNT_NOP (target_flags & 0200) -#define TARGET_LONG64 (target_flags & 01000) -#define TARGET_VOLATILE_NOCACHE (target_flags & 0400) - -#define OVERRIDE_OPTIONS \ -{ \ - init_convex (); \ - if ((target_flags & 077) != ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 077)) \ - target_flags &= ~ (TARGET_DEFAULT | TARGET_CPU_DEFAULT); \ - if (target_flags & 001) \ - target_cpu = 0; \ - else if (target_flags & 006) \ - target_cpu = 1; \ - else if (target_flags & 010) \ - target_cpu = 2; \ - else if (target_flags & 020) \ - target_cpu = 3; \ -} - -/* Names to predefine in the preprocessor for this target machine. */ - -#define CPP_PREDEFINES "-Dconvex -Dunix -Asystem(unix) -Acpu(convex) -Amachine(convex)" - -/* Print subsidiary information on the compiler version in use. */ - -#define TARGET_VERSION fprintf (stderr, " (convex)"); - -/* Target-dependent specs. - Some libraries come in c1 and c2+ versions; use the appropriate ones. - Make a target-dependent __convex_cxx__ define to relay the target cpu - to the program being compiled. */ - -#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1 - -/* C1 default */ - -#if _IEEE_FLOAT_ - -#define CPP_SPEC \ -"%{!mc2:%{!mc32:%{!mc34:%{!mc38:-D__convex_c1__}}}} \ - %{mc2:-D__convex_c2__} \ - %{mc32:-D__convex_c32__} \ - %{mc34:-D__convex_c34__} \ - %{mc38:-D__convex_c38__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_IEEE_FLOAT_ \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#else - -#define CPP_SPEC \ -"%{!mc2:%{!mc32:%{!mc34:%{!mc38:-D__convex_c1__}}}} \ - %{mc2:-D__convex_c2__} \ - %{mc32:-D__convex_c32__} \ - %{mc34:-D__convex_c34__} \ - %{mc38:-D__convex_c38__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_CONVEX_FLOAT_ \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#endif - -#define LIB_SPEC \ -"%{!mc2:%{!mc32:%{!mc34:%{!mc38:-lC1%{traditional:_old}%{p:_p}%{pg:_p}}}}} \ - %{mc2:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc32:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc34:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc38:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - -lc%{traditional:_old}%{p:_p}%{pg:_p}" - -#endif - -#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 2 - -/* C2 default */ - -#if _IEEE_FLOAT_ - -#define CPP_SPEC \ -"%{mc1:-D__convex_c1__} \ - %{!mc1:%{!mc32:%{!mc34:%{!mc38:-D__convex_c2__}}}} \ - %{mc32:-D__convex_c32__} \ - %{mc34:-D__convex_c34__} \ - %{mc38:-D__convex_c38__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_IEEE_FLOAT_ \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#else - -#define CPP_SPEC \ -"%{mc1:-D__convex_c1__} \ - %{!mc1:%{!mc32:%{!mc34:%{!mc38:-D__convex_c2__}}}} \ - %{mc32:-D__convex_c32__} \ - %{mc34:-D__convex_c34__} \ - %{mc38:-D__convex_c38__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_CONVEX_FLOAT_ \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#endif - -#define LIB_SPEC \ -"%{mc1:-lC1%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{!mc1:%{!mc32:%{!mc34:%{!mc38:-lC2%{traditional:_old}%{p:_p}%{pg:_p}}}}} \ - %{mc32:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc34:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc38:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - -lc%{traditional:_old}%{p:_p}%{pg:_p}" - -#endif - -#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 4 - -/* C32 default */ - -#if _IEEE_FLOAT_ - -#define CPP_SPEC \ -"%{mc1:-D__convex_c1__} \ - %{mc2:-D__convex_c2__} \ - %{!mc1:%{!mc2:%{!mc34:%{!mc38:-D__convex_c32__}}}} \ - %{mc34:-D__convex_c34__} \ - %{mc38:-D__convex_c38__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_IEEE_FLOAT_ \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#else - -#define CPP_SPEC \ -"%{mc1:-D__convex_c1__} \ - %{mc2:-D__convex_c2__} \ - %{!mc1:%{!mc2:%{!mc34:%{!mc38:-D__convex_c32__}}}} \ - %{mc34:-D__convex_c34__} \ - %{mc38:-D__convex_c38__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_CONVEX_FLOAT_ \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#endif - -#define LIB_SPEC \ -"%{mc1:-lC1%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc2:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{!mc1:%{!mc2:%{!mc34:%{!mc38:-lC2%{traditional:_old}%{p:_p}%{pg:_p}}}}} \ - %{mc34:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc38:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - -lc%{traditional:_old}%{p:_p}%{pg:_p}" - -#endif - -#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 010 - -/* C34 default */ - -#if _IEEE_FLOAT_ - -#define CPP_SPEC \ -"%{mc1:-D__convex_c1__} \ - %{mc2:-D__convex_c2__} \ - %{mc32:-D__convex_c32__} \ - %{!mc1:%{!mc2:%{!mc32:%{!mc38:-D__convex_c34__}}}} \ - %{mc38:-D__convex_c38__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_IEEE_FLOAT_ \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#else - -#define CPP_SPEC \ -"%{mc1:-D__convex_c1__} \ - %{mc2:-D__convex_c2__} \ - %{mc32:-D__convex_c32__} \ - %{!mc1:%{!mc2:%{!mc32:%{!mc38:-D__convex_c34__}}}} \ - %{mc38:-D__convex_c38__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_CONVEX_FLOAT_ \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#endif - -#define LIB_SPEC \ -"%{mc1:-lC1%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc2:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc32:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{!mc1:%{!mc2:%{!mc32:%{!mc38:-lC2%{traditional:_old}%{p:_p}%{pg:_p}}}}} \ - %{mc38:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - -lc%{traditional:_old}%{p:_p}%{pg:_p}" - -#endif - -#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 020 - -/* C38 default */ - -#if _IEEE_FLOAT_ - -#define CPP_SPEC \ -"%{mc1:-D__convex_c1__} \ - %{mc2:-D__convex_c2__} \ - %{mc32:-D__convex_c32__} \ - %{mc34:-D__convex_c34__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_IEEE_FLOAT_ \ - %{!mc1:%{!mc2:%{!mc32:%{!mc34:-D__convex_c38__}}}} \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#else - -#define CPP_SPEC \ -"%{mc1:-D__convex_c1__} \ - %{mc2:-D__convex_c2__} \ - %{mc32:-D__convex_c32__} \ - %{mc34:-D__convex_c34__} \ - %{fno-builtin:-D__NO_INLINE} \ - -D__NO_INLINE_MATH -D__NO_INLINE_STDLIB \ - -D_CONVEX_FLOAT_ \ - %{!mc1:%{!mc2:%{!mc32:%{!mc34:-D__convex_c38__}}}} \ - %{.S:-P} \ - %{!traditional:-D__stdc__} \ - %{!traditional:-D_LONGLONG} \ - %{!traditional:-Ds64_t=long\\ long -Du64_t=unsigned\\ long\\ long} \ - %{!ansi:-D_POSIX_SOURCE} \ - %{!ansi:-D_CONVEX_SOURCE}" - -#endif - -#define LIB_SPEC \ -"%{mc1:-lC1%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc2:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc32:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{mc34:-lC2%{traditional:_old}%{p:_p}%{pg:_p}} \ - %{!mc1:%{!mc2:%{!mc32:%{!mc34:-lC2%{traditional:_old}%{p:_p}%{pg:_p}}}}} \ - -lc%{traditional:_old}%{p:_p}%{pg:_p}" - -#endif - -#if _IEEE_FLOAT_ - -/* ieee default */ - -#define ASM_SPEC "-fi" - -#define LINK_SPEC \ -"-E%{traditional:no}posix \ - -X \ - %{F} %{M*} %{y*} \ - -fi \ - -A__iob=___ap$iob \ - -A_use_libc_sema=___ap$use_libc_sema \ - %{traditional:-A___gcc_cleanup=__cleanup} \ - %{!traditional:-A___gcc_cleanup=___ap$do_registered_functions} \ - -L/usr/lib" - -#define STARTFILE_SPEC \ -"%{!pg:%{!p:/usr/lib/crt/crt0.o}} \ - %{!pg:%{p:/usr/lib/crt/mcrt0.o}} \ - %{pg:/usr/lib/crt/gcrt0.o} \ - /usr/lib/crt/fpmode_i.o" - -#else - -/* native default */ - -#define ASM_SPEC "-fn" - -#define LINK_SPEC \ -"-E%{traditional:no}posix \ - -X \ - %{F} %{M*} %{y*} \ - -fn \ - -A__iob=___ap$iob \ - -A_use_libc_sema=___ap$use_libc_sema \ - %{traditional:-A___gcc_cleanup=__cleanup} \ - %{!traditional:-A___gcc_cleanup=___ap$do_registered_functions} \ - -L/usr/lib" - -#define STARTFILE_SPEC \ -"%{!pg:%{!p:/usr/lib/crt/crt0.o}} \ - %{!pg:%{p:/usr/lib/crt/mcrt0.o}} \ - %{pg:/usr/lib/crt/gcrt0.o}" - -#endif - -/* Use /path/libgcc.a instead of -lgcc, makes bootstrap work more smoothly. */ - -#define LINK_LIBGCC_SPECIAL_1 - -/* Since IEEE support was added to gcc, most things seem to like it - better if we disable exceptions and check afterward for infinity. */ - -#if __convex__ -#if _IEEE_FLOAT_ -#define REAL_VALUE_ISNAN(x) 0 -#define REAL_VALUE_ISINF(x) ((*(short *) &(x) & 0x7ff0) == 0x7ff0) -#else -#define REAL_VALUE_ISNAN(x) 0 -#define REAL_VALUE_ISINF(x) ((*(short *) &(x) & 0xfff0) == 0x8000) -#endif -#endif - -/* Target machine storage layout */ - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. */ -#define BITS_BIG_ENDIAN 1 - -/* Define this if most significant byte of a word is the lowest numbered. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this if most significant word of a multiword number is numbered. */ -#define WORDS_BIG_ENDIAN 1 - -/* Number of bits in an addressable storage unit */ -#define BITS_PER_UNIT 8 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; - if using 16-bit ints on a 68000, this would still be 32. - But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 64 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 8 - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 32 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 64 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 16 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 32 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* A bitfield declared as `int' forces `int' alignment for the struct. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* No data type wants to be aligned rounder than this. */ -/* beware of doubles in structs -- 64 is incompatible with cc */ -#define BIGGEST_ALIGNMENT 32 - -/* Set this nonzero if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 0 - -/* Define sizes of basic C types to conform to ordinary usage -- these - types depend on BITS_PER_WORD otherwise. */ -#define CHAR_TYPE_SIZE 8 -#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 64 -/* This prevents cexp.c from depending on LONG_TYPE_SIZE. */ -#define MAX_LONG_TYPE_SIZE 64 - -/* Declare the standard types used by builtins to match convex stddef.h -- - with int rather than long. */ - -#define SIZE_TYPE "unsigned int" -#define PTRDIFF_TYPE "int" - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. */ -#define FIRST_PSEUDO_REGISTER 16 - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - For Convex, these are AP, FP, and SP. */ -#define FIXED_REGISTERS \ - { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 } - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. */ -#define CALL_USED_REGISTERS \ - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } - -/* List the order in which to allocate registers. Each register must be - listed once, even those in FIXED_REGISTERS. - For Convex, put S0 (the return register) last. */ -#define REG_ALLOC_ORDER \ - { 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 0, 8, 14, 15 } - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. */ -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - On Convex, S registers can hold any type, A registers any nonfloat. */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) \ - (S_REGNO_P (REGNO) \ - || (GET_MODE_SIZE (MODE) <= 4 && (MODE) != SFmode)) - -/* 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_SIZE (MODE1) <= 4 && (MODE1) != SFmode) \ - == (GET_MODE_SIZE (MODE2) <= 4 && (MODE2) != SFmode)) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -#define S0_REGNUM 0 -#define A0_REGNUM 8 - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM A0_REGNUM - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM (A0_REGNUM + 7) - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms - may be accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED 1 - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM (A0_REGNUM + 6) - -/* Register in which static-chain is passed to a function. - Use S0, not an A reg, because this rare use would otherwise prevent - an A reg from being available to global-alloc across calls. */ -#define STATIC_CHAIN_REGNUM S0_REGNUM - -/* Register in which address to store a structure value - is passed to a function. */ -#define STRUCT_VALUE_REGNUM (A0_REGNUM + 1) - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -/* Convex has classes A (address) and S (scalar). - A is further divided into SP_REGS (stack pointer) and INDEX_REGS. - SI_REGS is S_REGS + INDEX_REGS -- all the regs except SP. */ - -enum reg_class { - NO_REGS, S_REGS, INDEX_REGS, SP_REGS, A_REGS, SI_REGS, - ALL_REGS, LIM_REG_CLASSES -}; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Since GENERAL_REGS is the same class as ALL_REGS, - don't give it a different class number; just make it an alias. */ - -#define GENERAL_REGS ALL_REGS - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ - {"NO_REGS", "S_REGS", "INDEX_REGS", "SP_REGS", "A_REGS", "SI_REGS", \ - "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS \ - { 0, 0x00ff, 0xfe00, 0x0100, 0xff00, 0xfeff, 0xffff } - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) (regno_reg_class[REGNO]) - -#define S_REGNO_P(REGNO) (((REGNO) - S0_REGNUM) < (unsigned) 8) -#define A_REGNO_P(REGNO) (((REGNO) - A0_REGNUM) < (unsigned) 8) - -#define S_REG_P(X) (REG_P (X) && S_REGNO_P (REGNO (X))) -#define A_REG_P(X) (REG_P (X) && A_REGNO_P (REGNO (X))) - -/* The class value for index registers, and the one for base regs. */ - -#define INDEX_REG_CLASS INDEX_REGS -#define BASE_REG_CLASS INDEX_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ -/* a => A_REGS - d => S_REGS ('s' is taken) - A => INDEX_REGS (i.e., A_REGS except sp) */ - -#define REG_CLASS_FROM_LETTER(C) \ - reg_class_from_letter[(unsigned char) (C)] - -/* 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' is used to pass any CONST_INT and reject any CONST_DOUBLE. - CONST_DOUBLE integers are handled by G and H constraint chars. */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) 1 - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. */ -/* Convex uses G, H: - value usable in ld.d (low word 0) or ld.l (high word all sign) */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - (((C) == 'G' && LD_D_P (VALUE)) || \ - ((C) == 'H' && LD_L_P (VALUE)) || \ - 0) - -#define LD_D_P(X) (const_double_low_int (X) == 0) - -#define LD_L_P(X) (const_double_low_int (X) >= 0 \ - ? const_double_high_int (X) == 0 \ - : const_double_high_int (X) == -1) - -/* Optional extra constraints for this machine. - For Convex, 'Q' means that OP is a volatile MEM. - For volatile scalars, we use instructions that bypass the data cache. */ - -#define EXTRA_CONSTRAINT(OP, C) \ - ((C) == 'Q' ? (GET_CODE (OP) == MEM && MEM_VOLATILE_P (OP) \ - && ! TARGET_C1 && TARGET_VOLATILE_NOCACHE) \ - : 0) - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. */ - -/* Put 2-word constants that can't be immediate operands into memory. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) \ - ((GET_CODE (X) != CONST_DOUBLE \ - || GET_MODE (X) == SFmode \ - || LD_L_P (X) || LD_D_P (X)) ? (CLASS) : NO_REGS) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ -#define CLASS_MAX_NREGS(CLASS, MODE) ((GET_MODE_SIZE (MODE) + 7) / 8) - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -#define STACK_GROWS_DOWNWARD - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD - -/* Define this if should default to -fcaller-saves. */ -#define DEFAULT_CALLER_SAVES - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ -#define STARTING_FRAME_OFFSET 0 - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. */ -#define PUSH_ROUNDING(BYTES) (((BYTES) + 3) & ~3) - -/* Offset of first parameter from the argument pointer register value. */ -#define FIRST_PARM_OFFSET(FNDECL) 0 - -/* Value is the number of bytes of arguments automatically - popped when returning from a subroutine call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - SIZE is the number of bytes of arguments passed on the stack. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) (SIZE) - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), S0_REGNUM) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ - -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, S0_REGNUM) - -/* Define this if PCC uses the nonreentrant convention for returning - structure and union values. */ - -#define PCC_STATIC_STRUCT_RETURN - -/* 1 if N is a possible register number for a function value. - On the Convex, S0 is the only register thus used. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == S0_REGNUM) - -/* 1 if N is a possible register number for function argument passing. */ - -#define FUNCTION_ARG_REGNO_P(N) 0 - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. */ -/* On convex, simply count the arguments in case TARGET_ARGCOUNT is set. */ - -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ - -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ - ((CUM) = 0) - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - ((CUM) += 1) - -/* Define where to put the arguments to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). - - Convex: all args go on the stack. But return the arg count - as the "next arg register" to be passed to gen_call. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - ((MODE) == VOIDmode ? GEN_INT ((CUM)) : 0) - -/* This macro generates the assembly code for function entry. - FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - 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. */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) \ -{ \ - int size = ((SIZE) + 7) & -8; \ - if (size != 0) \ - fprintf (FILE, "\tsub.w #%d,sp\n", size); \ -} - -/* This macro generates the assembly code for function exit, - on machines that need it. If FUNCTION_EPILOGUE is not defined - then individual return instructions are generated for each - return statement. Args are same as for FUNCTION_PROLOGUE. */ - -#define FUNCTION_EPILOGUE(FILE, SIZE) \ -{ \ - /* Follow function with a zero to stop c34 icache prefetching. */ \ - fprintf (FILE, "\tds.h 0\n"); \ -} - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. */ - -/* On convex, the code for a trampoline is - ld.w #,s0 - jmp */ - -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - fprintf (FILE, "\tld.w #69696969,s0\n"); \ - fprintf (FILE, "\tjmp 52525252\n"); \ -} - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 12 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (TRAMP, 2)), CXT); \ - emit_move_insn (gen_rtx (MEM, Pmode, plus_constant (TRAMP, 8)), FNADDR); \ - emit_call_insn (gen_call_pop (gen_rtx (MEM, QImode, \ - gen_rtx (SYMBOL_REF, Pmode, \ - "__enable_execute_stack")), \ - const0_rtx, const0_rtx, const0_rtx)); \ -} - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - fprintf (FILE, "\tldea LP%d,a1\n\tcallq mcount\n", (LABELNO)); - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. */ - -#define EXIT_IGNORE_STACK 1 - -/* Store in the variable DEPTH the initial difference between the - frame pointer reg contents and the stack pointer reg contents, - as of the start of the function body. This depends on the layout - of the fixed parts of the stack frame and on how registers are saved. */ -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ -{ (DEPTH) = (get_frame_size () + 7) & -8; } - -/* Addressing modes, and classification of registers for them. */ - -/* #define HAVE_POST_INCREMENT 0 */ -/* #define HAVE_POST_DECREMENT 0 */ - -/* #define HAVE_PRE_DECREMENT 0 */ -/* #define HAVE_PRE_INCREMENT 0 */ - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_INDEX_P(regno) \ - ((regno) <= LAST_VIRTUAL_REGISTER \ - ? regno_ok_for_index_p[regno] \ - : regno_ok_for_index_p[reg_renumber[regno]]) - -#define REGNO_OK_FOR_BASE_P(regno) REGNO_OK_FOR_INDEX_P (regno) - -/* Maximum number of registers that can appear in a valid memory address. */ - -#define MAX_REGS_PER_ADDRESS 1 - -/* 1 if X is an rtx for a constant that is a valid address. */ - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ - || GET_CODE (X) == HIGH) - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ - -/* For convex, bounce 2-word constants that can't be immediate operands. */ - -#define LEGITIMATE_CONSTANT_P(X) \ - (GET_CODE (X) != CONST_DOUBLE \ - || GET_MODE (X) == SFmode \ - || LD_L_P (X) || LD_D_P (X)) - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) \ - (REGNO (X) > LAST_VIRTUAL_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. */ -#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_INDEX_P (X) - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) - -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - For Convex, valid addresses are - indirectable or (MEM indirectable) - where indirectable is - const, reg, (PLUS reg const) - - We don't use indirection since with insn scheduling, load + indexing - is better. */ - -/* 1 if X is an address that we could indirect through. */ -#define INDIRECTABLE_ADDRESS_P(X) \ - (CONSTANT_ADDRESS_P (X) \ - || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ - || (GET_CODE (X) == PLUS \ - && GET_CODE (XEXP (X, 0)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ - && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ - || (GET_CODE (X) == PLUS \ - && GET_CODE (XEXP (X, 1)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 1)) \ - && CONSTANT_ADDRESS_P (XEXP (X, 0)))) - -/* Go to ADDR if X is a valid address. */ -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ register rtx xfoob = (X); \ - if (INDIRECTABLE_ADDRESS_P (xfoob)) \ - goto ADDR; \ - if (GET_CODE (xfoob) == PRE_DEC && XEXP (xfoob, 0) == stack_pointer_rtx) \ - goto ADDR; \ -} - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. - - For Convex, nothing needs to be done. */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {} - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {} - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE 1 */ - -/* Define this if the case instruction drops through after the table - when the index is out of range. Don't define it if the case insn - jumps to the default label instead. */ -/* #define CASE_DROPS_THROUGH */ - -/* Specify the tree operation to be used to convert reals to integers. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* This is the kind of divide that is easiest to do in the general case. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* This flag, if defined, says the same insns that convert to a signed fixnum - also convert validly to an unsigned one. */ -#define FIXUNS_TRUNC_LIKE_FIX_TRUNC - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 8 - -/* Define this if zero-extension is slow (more than one real instruction). */ -/* #define SLOW_ZERO_EXTEND */ - -/* Nonzero if access to memory by bytes is slow and undesirable. */ -#define SLOW_BYTE_ACCESS (! TARGET_C2) - -/* Define if shifts truncate the shift count - which implies one can omit a sign-extension or zero-extension - of a shift count. */ -/* #define SHIFT_COUNT_TRUNCATED */ - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* On Convex, it is as good to call a constant function address as to - call an address kept in a register. */ -#define NO_FUNCTION_CSE - -/* When a prototype says `char' or `short', really pass an `int'. */ -#define PROMOTE_PROTOTYPES - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -#define Pmode SImode - -/* A function address in a call instruction - is a byte address (for indexing purposes) - so give the MEM rtx a byte's mode. */ -#define FUNCTION_MODE QImode - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. */ - -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - case CONST_INT: \ - case CONST_DOUBLE: \ - return 0; - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. */ - -#define RTX_COSTS(RTX,CODE,OUTER_CODE) \ - case PLUS: \ - if (regno_pointer_flag != 0 \ - && GET_CODE (XEXP (RTX, 0)) == REG \ - && REGNO_POINTER_FLAG (REGNO (XEXP (RTX, 0))) \ - && GET_CODE (XEXP (RTX, 1)) == CONST_INT) \ - return 0; \ - else break; \ - case MULT: \ - return 4 * (char) (0x03060403 >> target_cpu * 8); \ - case ASHIFT: \ - case LSHIFTRT: \ - case ASHIFTRT: \ - return 4 * (char) (0x03010403 >> target_cpu * 8); \ - case MEM: \ - return 5; - -/* Compute the cost of an address. This is meant to approximate the size - and/or execution delay of an insn using that address. If the cost is - approximated by the RTL complexity, including CONST_COSTS above, as - is usually the case for CISC machines, this macro should not be defined. - For aggressively RISCy machines, only one insn format is allowed, so - this macro should be a constant. The value of this macro only matters - for valid addresses. */ - -#define ADDRESS_COST(RTX) 0 - -/* Specify the cost of a branch insn; roughly the number of extra insns that - should be added to avoid a branch. */ - -#define BRANCH_COST 0 - -/* Adjust the cost of dependences. */ - -#define ADJUST_COST(INSN,LINK,DEP,COST) \ -{ \ - /* Antidependencies don't block issue. */ \ - if (REG_NOTE_KIND (LINK) != 0) \ - (COST) = 0; \ - /* C38 situations where delay depends on context */ \ - else if (TARGET_C38 \ - && GET_CODE (PATTERN (INSN)) == SET \ - && GET_CODE (PATTERN (DEP)) == SET) \ - { \ - enum attr_type insn_type = get_attr_type (INSN); \ - enum attr_type dep_type = get_attr_type (DEP); \ - /* index register must be ready one cycle early */ \ - if (insn_type == TYPE_MLDW || insn_type == TYPE_MLDL \ - || (insn_type == TYPE_MST \ - && reg_mentioned_p (SET_DEST (PATTERN (DEP)), \ - SET_SRC (PATTERN (INSN))))) \ - (COST) += 1; \ - /* alu forwarding off alu takes two */ \ - if (dep_type == TYPE_ALU \ - && insn_type != TYPE_ALU \ - && ! (insn_type == TYPE_MST \ - && SET_DEST (PATTERN (DEP)) == SET_SRC (PATTERN (INSN)))) \ - (COST) += 1; \ - } \ -} - -/* Convex uses Vax or IEEE floats. - Follow the host format. */ -#define TARGET_FLOAT_FORMAT HOST_FLOAT_FORMAT - -/* But must prevent real.c from constructing Vax dfloats */ -#define REAL_VALUE_ATOF(X,S) atof (X) -extern double atof(); - -/* Check a `double' value for validity for a particular machine mode. */ -#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \ - OVERFLOW = check_float_value (MODE, &D, OVERFLOW) - -/* Tell final.c how to eliminate redundant test instructions. */ - -/* Here we define machine-dependent flags and fields in cc_status - (see `conditions.h'). No extra ones are needed for convex. */ - -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. */ - -#define NOTICE_UPDATE_CC(EXP,INSN) {} - -/* Control the assembler format that we output. */ - -/* Output at beginning of assembler file. */ - -#if _IEEE_FLOAT_ -#define ASM_FILE_START(FILE) fprintf (FILE, ";NO_APP\n.fpmode ieee\n") -#else -#define ASM_FILE_START(FILE) fprintf (FILE, ";NO_APP\n.fpmode native\n") -#endif - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON ";APP\n" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF ";NO_APP\n" - -/* Alignment with Convex's assembler goes like this: - .text can be .aligned up to a halfword. - .data and .bss can be .aligned up to a longword. - .lcomm is not supported, explicit declarations in .bss must be used instead. - We get alignment for word and longword .text data by conventionally - using .text 2 for word-aligned data and .text 3 for longword-aligned - data. This requires that the data's size be a multiple of its alignment, - which seems to be always true. */ - -/* Output before read-only data. */ - -#define TEXT_SECTION_ASM_OP (current_section_is_text = 1, ".text") - -/* Output before writable data. */ - -#define DATA_SECTION_ASM_OP (current_section_is_text = 0, ".data") - -/* Output before uninitialized data. */ - -#define BSS_SECTION_ASM_OP (current_section_is_text = 0, ".bss") - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - if (current_section_is_text && (LOG) > 1) \ - fprintf (FILE, ".text %d\n", LOG); \ - else if (current_section_is_text) \ - fprintf (FILE, ".text\n.align %d\n", 1 << (LOG)); \ - else \ - fprintf (FILE, ".align %d\n", 1 << (LOG)) - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{ \ - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \ - "sp", "a1", "a2", "a3", "a4", "a5", "ap", "fp", \ -} - -/* This is BSD, so it wants DBX format. */ - -#define DBX_DEBUGGING_INFO - -/* How to renumber registers for dbx and gdb. */ - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* Do not break .stabs pseudos into continuations. */ - -#define DBX_CONTIN_LENGTH 0 - -/* This is the char to use for continuation (in case we need to turn - continuation back on). */ - -#define DBX_CONTIN_CHAR '?' - -/* Don't use stab extensions until GDB v4 port is available for convex. */ - -#define DEFAULT_GDB_EXTENSIONS 0 -#define DBX_NO_XREFS - -/* This is how to output the definition of a user-level label named NAME, - such as the label on a static function or variable NAME. */ - -#define ASM_OUTPUT_LABEL(FILE,NAME) \ - do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) - -/* This is how to output a command to make the user-level label named NAME - defined for reference from other files. */ - -#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ - do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) - -/* The prefix to add to user-visible assembler symbols. */ - -#define USER_LABEL_PREFIX "_" - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ - -#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - fprintf (FILE, "%s%d:\n", PREFIX, NUM) - -/* Put case tables in .text 2, where they will be word-aligned */ - -#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ - ASM_OUTPUT_ALIGN (FILE, 2); \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM) - -#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \ - ASM_OUTPUT_ALIGN (FILE, 1) - -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*%s%d", PREFIX, NUM) - -/* This is how to output an assembler line defining a `double' constant. */ - -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ - outfloat (FILE, VALUE, "%.17e", "\tds.d ", "\n") - -/* This is how to output an assembler line defining a `float' constant. */ - -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ - outfloat (FILE, VALUE, "%.9e", "\tds.s ", "\n") - -/* This is how to output an assembler line defining an `int' constant. */ - -#define ASM_OUTPUT_INT(FILE,VALUE) \ -{ \ - fprintf (FILE, "\tds.w "); \ - output_addr_const (FILE, simplify_for_convex (VALUE)); \ - fprintf (FILE, "\n"); \ -} - -/* Likewise for a `long long int' constant. */ - -#define ASM_OUTPUT_DOUBLE_INT(FILE,VALUE) \ -{ \ - if (GET_CODE (VALUE) == CONST_DOUBLE) \ - fprintf (FILE, "\tds.w %d,%d\n", \ - const_double_high_int (VALUE), const_double_low_int (VALUE)); \ - else if (GET_CODE (VALUE) == CONST_INT) \ - { \ - int val = INTVAL (VALUE); \ - fprintf (FILE, "\tds.w %d,%d\n", val < 0 ? -1 : 0, val); \ - } \ - else \ - abort (); \ -} - -/* Likewise for `char' and `short' constants. */ - -#define ASM_OUTPUT_SHORT(FILE,VALUE) \ -( fprintf (FILE, "\tds.h "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ -( fprintf (FILE, "\tds.b "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* This is how to output an assembler line for a numeric constant byte. */ - -#define ASM_OUTPUT_BYTE(FILE,VALUE) \ - fprintf (FILE, "\tds.b %#x\n", (VALUE)) - -/* This is how to output a string */ - -#define ASM_OUTPUT_ASCII(FILE,STR,SIZE) do { \ - int i; \ - fprintf ((FILE), "\tds.b \""); \ - for (i = 0; i < (SIZE); i++) { \ - register int c = (STR)[i] & 0377; \ - if (c >= ' ' && c < 0177 && c != '\\' && c != '"') \ - putc (c, (FILE)); \ - else \ - fprintf ((FILE), "\\%03o", c);} \ - fprintf ((FILE), "\"\n");} while (0) - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tpsh.%c %s\n", \ - S_REGNO_P (REGNO) ? 'l' : 'w', \ - reg_names[REGNO]) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tpop.%c %s\n", \ - S_REGNO_P (REGNO) ? 'l' : 'w', \ - reg_names[REGNO]) - -/* This is how to output an element of a case-vector that is absolute. */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\tds.w L%d\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. - (not used on Convex) */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\tds.w L%d-L%d\n", VALUE, REL) - -/* This is how to output an assembler line - that says to advance the location counter by SIZE bytes. */ - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\tds.b %u(0)\n", (SIZE)) - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs (".comm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (ROUNDED))) - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -( bss_section (), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ":\tbs.b %u\n", (ROUNDED))) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) - -/* Output an arg count before function entries. */ - -#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ - asm_declare_function_name (FILE, NAME, DECL) - -/* Define the parentheses used to group arithmetic operations - in assembler code. */ - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* Define results of standard character escape sequences. */ -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - -/* Print an instruction operand X on file FILE. - CODE is the code from the %-spec that requested printing this operand; - if `%z3' was used to print operand 3, then CODE is 'z'. */ - -#define PRINT_OPERAND(FILE, X, CODE) \ - print_operand (FILE, X, CODE) - -/* Print a memory operand whose address is X, on file FILE. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ - print_operand_address (FILE, ADDR) - -/* Do not put out GNU stabs for constructors and destructors. - ld bounces them. */ - -#define FASCIST_ASSEMBLER - -/* __gcc_cleanup is loader-aliased to __ap$do_registered_functions if we - are linking against standard libc, 0 if old (-traditional) libc. */ - -#define EXIT_BODY \ -{ \ - extern void __gcc_cleanup (); \ - if (__gcc_cleanup != _cleanup) \ - __gcc_cleanup (); \ - _cleanup (); \ -} - -/* Header for convex.c. - Here at the end so we can use types defined above. */ - -extern int target_cpu; -extern int current_section_is_text; -extern enum reg_class regno_reg_class[]; -extern enum reg_class reg_class_from_letter[]; -extern char regno_ok_for_index_p_base[]; -#define regno_ok_for_index_p (regno_ok_for_index_p_base + 1) - -extern int const_double_low_int (); -extern int const_double_high_int (); -extern char *output_cmp (); -extern char *output_condjump (); -extern char *output_call (); -extern void gen_ap_for_call (); -extern int check_float_value (); -extern void asm_declare_function_name (); diff --git a/gcc/config/convex/convex.md b/gcc/config/convex/convex.md deleted file mode 100755 index cb6f64d..0000000 --- a/gcc/config/convex/convex.md +++ /dev/null @@ -1,1885 +0,0 @@ -;;- Machine description for GNU compiler, Convex Version -;; Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc. - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;; Attribute specifications - -; Target CPU -(define_attr "cpu" "c1,c32,c34,c38" - (const (symbol_ref "(enum attr_cpu) target_cpu"))) - -;; Instruction classification - -(define_attr "type" - "alu,xalu,mldw,mldl,mldb,mst,adds,addd,mulw,mull,muls,muld,divw,divl,divs,divd,shfw,shfl,cvts,cvtd" - (const_string "alu")) - -;; Instruction times - -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "mldw")) 2 0) -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "mldl")) 4 0) -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "mldw,mldl")) 2 0) -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "mldw,mldl")) 4 0) -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "mldw,mldl")) 2 0) - -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "mldb")) 9 0) -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "mldb")) 36 0) -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "mldb")) 21 0) - -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "xalu")) 1 0) -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "xalu")) 1 0) -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "xalu")) 5 0) -(define_function_unit "mem" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "xalu")) 2 0) - -(define_function_unit "add" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "adds,addd")) 3 2) -(define_function_unit "add" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "adds,addd")) 2 1) -(define_function_unit "add" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "adds,addd")) 5 2) -(define_function_unit "add" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "adds,addd")) 2 1) - -(define_function_unit "mul" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "mulw,muls")) 3 2) -(define_function_unit "mul" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "mulw,muls")) 4 2) -(define_function_unit "mul" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "mulw,muls")) 6 2) -(define_function_unit "mul" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "mulw,muls")) 3 2) - -(define_function_unit "mul" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "mull,muld")) 4 3) -(define_function_unit "mul" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "mull")) 10 7) -(define_function_unit "mul" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "muld")) 5 2) -(define_function_unit "mul" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "mull,muld")) 7 3) -(define_function_unit "mul" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "mull,muld")) 4 3) - -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "divw")) 24 24) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "divw")) 44 6) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "divw")) 14 10) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "divw")) 11 10) - -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "divl")) 41 42) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "divl")) 76 5) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "divl")) 22 18) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "divl")) 19 18) - -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "divs")) 22 22) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "divs")) 8 6) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "divs")) 13 9) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "divs")) 10 9) - -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "divd")) 37 38) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "divd")) 12 8) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "divd")) 20 16) -(define_function_unit "div" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "divd")) 17 16) - -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "cvts,cvtd")) 4 3) -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "cvts")) 9 7) -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "cvtd")) 9 6) -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "cvts")) 6 2) -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c34") (eq_attr "type" "cvtd")) 6 1) -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "cvts,cvtd")) 3 1) - -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c1") (eq_attr "type" "shfw,shfl")) 3 2) -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "shfw")) 7 5) -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c32") (eq_attr "type" "shfl")) 7 4) -(define_function_unit "misc" 1 0 - (and (eq_attr "cpu" "c38") (eq_attr "type" "shfw,shfl")) 3 1) - -(define_function_unit "mystery_latch" 1 1 - (and (eq_attr "type" "!alu,mldw,mldl,adds,addd") (eq_attr "cpu" "c32")) 2 2) - -;(define_function_unit "ip" 1 1 -; (and (eq_attr "cpu" "c1") -; (eq_attr "type" "divw,divl,divs,divd,xalu")) 2 2) -;(define_function_unit "ip" 1 1 -; (and (eq_attr "cpu" "c1") -; (eq_attr "type" "!divw,divl,divs,divd,xalu")) 1 1) -;(define_function_unit "ip" 1 1 -; (and (eq_attr "cpu" "c32") -; (eq_attr "type" "mull,muld,divl,divd,shfl,cvtd,xalu")) 2 2) -;(define_function_unit "ip" 1 1 -; (and (eq_attr "cpu" "c32") -; (eq_attr "type" "!mull,muld,divl,divd,shfl,cvtd,xalu")) 1 1) -;(define_function_unit "ip" 1 1 -; (and (eq_attr "cpu" "c34") -; (eq_attr "type" "addd,mull,muld,divl,divd,cvtd,xalu")) 2 2) -;(define_function_unit "ip" 1 1 -; (and (eq_attr "cpu" "c34") -; (eq_attr "type" "!addd,mull,muld,divl,divd,cvtd,xalu")) 1 1) - -;; Make the first thing a real insn in case of genattrtab bug - -(define_insn "nop" - [(const_int 0)] - "" - "nop") - -;; Moves - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - "if (GET_CODE (operands[0]) != REG) - operands[1] = force_reg (DFmode, operands[1]);") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=d,d,d,d,d,<,m") - (match_operand:DF 1 "general_operand" "d,Q,m,G,H,d,d"))] - "register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode)" - "@ - mov %1,%0 - ldb.d %1,%0 - ld.d %1,%0 - ld.d %u1,%0 - ld.l %v1,%0 - psh.l %1 - st.d %1,%0" - [(set_attr "type" "alu,mldb,mldl,alu,alu,alu,mst")]) - -;; This is here so we can load any result of RTL constant folding -;; but do not use it on constants that can be loaded from memory. -;; It is never better and can be worse. - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=d") - (match_operand:DF 1 "const_double_operand" "F"))] - "CONST_DOUBLE_MEM (operands[1]) == const0_rtx" - "ld.u %u1,%0\;ld.w %v1,%0" - [(set_attr "type" "xalu")]) - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - "if (GET_CODE (operands[0]) != REG) - operands[1] = force_reg (SFmode, operands[1]);") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=d,d,d,d,<,m") - (match_operand:SF 1 "general_operand" "d,Q,m,F,d,d"))] - "register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode)" - "@ - mov.s %1,%0 - ldb.s %1,%0 - ld.s %1,%0 - ld.s %1,%0 - psh.w %1 - st.s %1,%0" - [(set_attr "type" "alu,mldb,mldw,alu,alu,mst")]) - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - "if (GET_CODE (operands[0]) != REG) - operands[1] = force_reg (DImode, operands[1]);") - -(define_insn "" - [(set (match_operand:DI 0 "general_operand" "=d,d,d,d,d,<,m") - (match_operand:DI 1 "general_operand" "d,Q,m,G,HI,d,d"))] - "register_operand (operands[0], DImode) - || register_operand (operands[1], DImode)" - "@ - mov %1,%0 - ldb.l %1,%0 - ld.l %1,%0 - ld.d %u1,%0 - ld.l %1,%0 - psh.l %1 - st.l %1,%0" - [(set_attr "type" "alu,mldb,mldl,alu,alu,alu,mst")]) - -;; This is here so we can load any result of RTL constant folding -;; but do not use it on constants that can be loaded from memory. -;; It is never better and can be worse. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (match_operand:DI 1 "const_double_operand" "F"))] - "CONST_DOUBLE_MEM (operands[1]) == const0_rtx" - "ld.u %u1,%0\;ld.w %v1,%0" - [(set_attr "type" "xalu")]) - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - "if (GET_CODE (operands[0]) != REG) - operands[1] = force_reg (SImode, operands[1]);") - -(define_insn "" - [(set (match_operand:SI 0 "push_operand" "=<,<") - (match_operand:SI 1 "nonmemory_operand" "Ad,i"))] - "" - "@ - psh.w %1 - pshea %a1") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d,r,d,r,r,m") - (match_operand:SI 1 "general_operand" "d,r,Q,m,i,r"))] - "register_operand (operands[0], SImode) - || register_operand (operands[1], SImode)" - "@ - mov.w %1,%0 - mov %1,%0 - ldb.w %1,%0 - ld.w %1,%0 - ld.w %1,%0 - st.w %1,%0" - [(set_attr "type" "alu,alu,mldb,mldw,alu,mst")]) - -(define_expand "movstrictsi" - [(set (strict_low_part (match_operand:SI 0 "general_operand" "")) - (match_operand:SI 1 "general_operand" ""))] - "" - "if (GET_CODE (operands[0]) != REG) - operands[1] = force_reg (SImode, operands[1]);") - -(define_insn "" - [(set (strict_low_part (match_operand:SI 0 "general_operand" "=d,r,d,r,r,m")) - (match_operand:SI 1 "general_operand" "d,r,Q,m,i,r"))] - "register_operand (operands[0], SImode) - || register_operand (operands[1], SImode)" - "@ - mov.w %1,%0 - mov %1,%0 - ldb.w %1,%0 - ld.w %1,%0 - ld.w %1,%0 - st.w %1,%0" - [(set_attr "type" "alu,alu,mldb,mldw,alu,mst")]) - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - "if (GET_CODE (operands[0]) != REG) - operands[1] = force_reg (HImode, operands[1]);") - -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=d,r,d,r,r,<,m") - (match_operand:HI 1 "general_operand" "d,r,Q,m,i,Ad,r"))] - "register_operand (operands[0], HImode) - || register_operand (operands[1], HImode)" - "@ - mov.w %1,%0 - mov %1,%0 - ldb.h %1,%0 - ld.h %1,%0 - ld.w %1,%0 - psh.w %1 - st.h %1,%0" - [(set_attr "type" "alu,alu,mldb,mldw,alu,alu,mst")]) - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - "if (GET_CODE (operands[0]) != REG) - operands[1] = force_reg (QImode, operands[1]);") - -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=d,r,d,r,r,<,m") - (match_operand:QI 1 "general_operand" "d,r,Q,m,i,Ad,r"))] - "register_operand (operands[0], QImode) - || register_operand (operands[1], QImode)" - "@ - mov.w %1,%0 - mov %1,%0 - ldb.b %1,%0 - ld.b %1,%0 - ld.w %1,%0 - psh.w %1 - st.b %1,%0" - [(set_attr "type" "alu,alu,mldb,mldw,alu,alu,mst")]) - -;; Expand block moves manually to get code that pipelines the loads. - -(define_expand "movstrsi" - [(set (match_operand:BLK 0 "memory_operand" "=m") - (match_operand:BLK 1 "memory_operand" "m")) - (use (match_operand:SI 2 "const_int_operand" "i")) - (use (match_operand:SI 3 "const_int_operand" "i"))] - "" - " expand_movstr (operands); DONE; ") - -;; Extension and truncation insns. -;; Those for integer source operand -;; are ordered widest source type first. - -(define_insn "truncsiqi2" - [(set (match_operand:QI 0 "register_operand" "=d,a") - (truncate:QI (match_operand:SI 1 "register_operand" "d,a")))] - "" - "cvtw.b %1,%0") - -(define_insn "truncsihi2" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (truncate:HI (match_operand:SI 1 "register_operand" "d,a")))] - "" - "cvtw.h %1,%0") - -(define_insn "trunchiqi2" - [(set (match_operand:QI 0 "register_operand" "=r") - (truncate:QI (match_operand:HI 1 "register_operand" "0")))] - "" - "") - -(define_insn "truncdisi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI (match_operand:DI 1 "register_operand" "d")))] - "" - "cvtl.w %1,%0") - -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (sign_extend:DI (match_operand:SI 1 "register_operand" "d")))] - "" - "cvtw.l %1,%0") - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (sign_extend:SI (match_operand:HI 1 "register_operand" "d,a")))] - "" - "cvth.w %1,%0") - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (sign_extend:HI (match_operand:QI 1 "register_operand" "d,a")))] - "" - "cvtb.w %1,%0") - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (sign_extend:SI (match_operand:QI 1 "register_operand" "d,a")))] - "" - "cvtb.w %1,%0") - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (float_extend:DF (match_operand:SF 1 "register_operand" "d")))] - "" - "cvts.d %1,%0" - [(set_attr "type" "cvts")]) - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (float_truncate:SF (match_operand:DF 1 "register_operand" "d")))] - "" - "cvtd.s %1,%0" - [(set_attr "type" "cvtd")]) - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))] - "" - "and #0xffff,%0") - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (zero_extend:HI (match_operand:QI 1 "register_operand" "0")))] - "" - "and #0xff,%0") - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))] - "" - "and #0xff,%0") - -(define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (zero_extend:DI (match_operand:SI 1 "register_operand" "0")))] - "" - "ld.u #0,%0") - -;; Fix-to-float conversion insns. -;; Note that the ones that start with SImode come first. -;; That is so that an operand that is a CONST_INT -;; (and therefore lacks a specific machine mode). -;; will be recognized as SImode (which is always valid) -;; rather than as QImode or HImode. - -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (float:SF (match_operand:SI 1 "register_operand" "d")))] - "" - "cvtw.s %1,%0" - [(set_attr "type" "cvts")]) - -(define_insn "floatdisf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (float:SF (match_operand:DI 1 "register_operand" "d")))] - "" - "cvtl.s %1,%0" - [(set_attr "type" "cvtd")]) - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (float:DF (match_operand:SI 1 "register_operand" "d")))] - "! TARGET_C1" - "cvtw.d %1,%0" - [(set_attr "type" "cvts")]) - -(define_insn "floatdidf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (float:DF (match_operand:DI 1 "register_operand" "d")))] - "" - "cvtl.d %1,%0" - [(set_attr "type" "cvtd")]) - -;; These are a little slower than gcc's normal way of doing unsigned -;; DI floats (if the DI number is "negative") but they avoid double -;; rounding and they avoid explicit constants. - -(define_expand "floatunsdidf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (float:DF (match_operand:DI 1 "register_operand" "d"))) - (set (cc0) (compare:DI (match_dup 3) (match_dup 1))) - (set (pc) - (if_then_else (le (cc0) (const_int 0)) - (label_ref (match_dup 4)) - (pc))) - (set (match_dup 2) (lshiftrt:DI (match_dup 1) (const_int 1))) - (set (match_dup 0) (float:DF (match_dup 2))) - (set (match_dup 0) (plus:DF (match_dup 0) (match_dup 0))) - (match_dup 4) - (set (match_dup 0) (match_dup 0))] - "" - " -{ - operands[2] = gen_reg_rtx (DImode); - operands[3] = force_reg (DImode, const0_rtx); - operands[4] = gen_label_rtx (); -}") - -(define_expand "floatunsdisf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (float:SF (match_operand:DI 1 "register_operand" "d"))) - (set (cc0) (compare:DI (match_dup 3) (match_dup 1))) - (set (pc) - (if_then_else (le (cc0) (const_int 0)) - (label_ref (match_dup 4)) - (pc))) - (set (match_dup 2) (lshiftrt:DI (match_dup 1) (const_int 1))) - (set (match_dup 0) (float:SF (match_dup 2))) - (set (match_dup 0) (plus:SF (match_dup 0) (match_dup 0))) - (match_dup 4) - (set (match_dup 0) (match_dup 0))] - "" - " -{ - operands[2] = gen_reg_rtx (DImode); - operands[3] = force_reg (DImode, const0_rtx); - operands[4] = gen_label_rtx (); -}") - -;; These patterns are identical to gcc's default action -;; if DI->DF and DI->SF are not present. There are here -;; only to prevent SI->*F from promoting to DI->*F. - -(define_expand "floatunssidf2" - [(set (match_dup 2) - (zero_extend:DI (match_operand:SI 1 "register_operand" ""))) - (set (match_operand:DF 0 "register_operand" "") - (float:DF (match_dup 2)))] - "" - "operands[2] = gen_reg_rtx (DImode);") - -(define_expand "floatunssisf2" - [(set (match_dup 2) - (zero_extend:DI (match_operand:SI 1 "register_operand" ""))) - (set (match_operand:SF 0 "register_operand" "") - (float:SF (match_dup 2)))] - "" - "operands[2] = gen_reg_rtx (DImode);") - -;; Float-to-fix conversion insns. - -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "d"))))] - "" - "cvts.w %1,%0" - [(set_attr "type" "cvts")]) - -(define_insn "fix_truncsfdi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "d"))))] - "" - "cvts.l %1,%0" - [(set_attr "type" "cvts")]) - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "d"))))] - "" - "cvtd.l %1,%0" - [(set_attr "type" "cvtd")]) - -(define_insn "fix_truncdfdi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "d"))))] - "" - "cvtd.l %1,%0" - [(set_attr "type" "cvtd")]) - -;;- All kinds of add instructions. - -(define_insn "adddf3" - [(set (match_operand:DF 0 "register_operand" "=d") - (plus:DF (match_operand:DF 1 "register_operand" "%0") - (match_operand:DF 2 "register_operand" "d")))] - "" - "add.d %2,%0" - [(set_attr "type" "addd")]) - -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=d") - (plus:SF (match_operand:SF 1 "register_operand" "%0") - (match_operand:SF 2 "nonmemory_operand" "dF")))] - "" - "add.s %2,%0" - [(set_attr "type" "adds")]) - -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (plus:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "register_operand" "d")))] - "" - "add.l %2,%0") - -(define_expand "addsi3" - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (match_operand:SI 1 "register_operand" "%A") - (match_operand:SI 2 "immediate_operand" "i")))] - "operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx" - "ldea %a2(%1),%0") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (match_operand:SI 1 "register_operand" "%a") - (match_operand:SI 2 "nonmemory_operand" "ri")))] - "operands[1] == stack_pointer_rtx && operands[0] != stack_pointer_rtx" - "mov %1,%0\;add.w %2,%0") - -(define_insn "" - [(set (match_operand:SI 0 "push_operand" "=<") - (plus:SI (match_operand:SI 1 "register_operand" "A") - (match_operand:SI 2 "immediate_operand" "i")))] - "operands[1] != stack_pointer_rtx" - "pshea %a2(%1)" - [(set_attr "type" "mst")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,a,a") - (plus:SI (match_operand:SI 1 "register_operand" "%0,0,A") - (match_operand:SI 2 "nonmemory_operand" "di,ri,i")))] - "TARGET_C1" - "@ - add.w %2,%0 - add.w %2,%0 - ldea %a2(%1),%0") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,a,r") - (plus:SI (match_operand:SI 1 "register_operand" "%0,0,A") - (match_operand:SI 2 "nonmemory_operand" "di,ri,i")))] - "" - "@ - add.w %2,%0 - add.w %2,%0 - ldea %a2(%1),%0") - -(define_insn "addhi3" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (plus:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "nonmemory_operand" "di,ai")))] - "" - "add.h %2,%0") - -(define_insn "addqi3" - [(set (match_operand:QI 0 "register_operand" "=d,d") - (plus:QI (match_operand:QI 1 "register_operand" "%0,0") - (match_operand:QI 2 "nonmemory_operand" "d,i")))] - "" - "@ - add.b %2,%0 - add.w %2,%0") - -;;- All kinds of subtract instructions. - -(define_insn "subdf3" - [(set (match_operand:DF 0 "register_operand" "=d") - (minus:DF (match_operand:DF 1 "register_operand" "0") - (match_operand:DF 2 "register_operand" "d")))] - "" - "sub.d %2,%0" - [(set_attr "type" "addd")]) - -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=d") - (minus:SF (match_operand:SF 1 "register_operand" "0") - (match_operand:SF 2 "nonmemory_operand" "dF")))] - "" - "sub.s %2,%0" - [(set_attr "type" "adds")]) - -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (minus:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "register_operand" "d")))] - "" - "sub.l %2,%0") - -(define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=d,a,?d,?a") - (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,0,di,ai") - (match_operand:SI 2 "nonmemory_operand" "di,ai,0,0")))] - "" - "@ - sub.w %2,%0 - sub.w %2,%0 - sub.w %1,%0\;neg.w %0,%0 - sub.w %1,%0\;neg.w %0,%0") - -(define_insn "subhi3" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (minus:HI (match_operand:HI 1 "register_operand" "0,0") - (match_operand:HI 2 "nonmemory_operand" "di,ai")))] - "" - "sub.h %2,%0") - -(define_insn "subqi3" - [(set (match_operand:QI 0 "register_operand" "=d,d") - (minus:QI (match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "d,i")))] - "" - "@ - sub.b %2,%0 - sub.w %2,%0") - -;;- Multiply instructions. - -(define_insn "muldf3" - [(set (match_operand:DF 0 "register_operand" "=d") - (mult:DF (match_operand:DF 1 "register_operand" "%0") - (match_operand:DF 2 "register_operand" "d")))] - "" - "mul.d %2,%0" - [(set_attr "type" "muld")]) - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=d") - (mult:SF (match_operand:SF 1 "register_operand" "%0") - (match_operand:SF 2 "nonmemory_operand" "dF")))] - "" - "mul.s %2,%0" - [(set_attr "type" "muls")]) - -(define_insn "muldi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (mult:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "register_operand" "d")))] - "" - "mul.l %2,%0" - [(set_attr "type" "mull")]) - -(define_insn "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (mult:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "di,ai")))] - "" - "mul.w %2,%0" - [(set_attr "type" "mulw")]) - -(define_insn "mulhi3" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (mult:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "nonmemory_operand" "di,ai")))] - "" - "mul.h %2,%0" - [(set_attr "type" "mulw")]) - -(define_insn "mulqi3" - [(set (match_operand:QI 0 "register_operand" "=d,d") - (mult:QI (match_operand:QI 1 "register_operand" "%0,0") - (match_operand:QI 2 "nonmemory_operand" "d,i")))] - "" - "@ - mul.b %2,%0 - mul.w %2,%0" - [(set_attr "type" "mulw,mulw")]) - -;;- Divide instructions. - -(define_insn "divdf3" - [(set (match_operand:DF 0 "register_operand" "=d") - (div:DF (match_operand:DF 1 "register_operand" "0") - (match_operand:DF 2 "register_operand" "d")))] - "" - "div.d %2,%0" - [(set_attr "type" "divd")]) - -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=d") - (div:SF (match_operand:SF 1 "register_operand" "0") - (match_operand:SF 2 "nonmemory_operand" "dF")))] - "" - "div.s %2,%0" - [(set_attr "type" "divs")]) - -(define_insn "divdi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (div:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:DI 2 "register_operand" "d")))] - "" - "div.l %2,%0" - [(set_attr "type" "divl")]) - -(define_expand "udivsi3" - [(set (match_dup 3) - (zero_extend:DI (match_operand:SI 1 "register_operand" ""))) - (set (match_dup 4) - (zero_extend:DI (match_operand:SI 2 "register_operand" ""))) - (set (match_dup 3) - (div:DI (match_dup 3) (match_dup 4))) - (set (match_operand:SI 0 "register_operand" "") - (subreg:SI (match_dup 3) 0))] - "" - "operands[3] = gen_reg_rtx (DImode); - operands[4] = gen_reg_rtx (DImode); ") - -(define_insn "udivdi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (udiv:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "register_operand" "d")))] - "" - "psh.l %2\;psh.l %1\;callq udiv64\;pop.l %0\;add.w #8,sp") - -(define_insn "divsi3" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (div:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "di,ai")))] - "" - "div.w %2,%0" - [(set_attr "type" "divw")]) - -(define_insn "divhi3" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (div:HI (match_operand:HI 1 "register_operand" "0,0") - (match_operand:HI 2 "nonmemory_operand" "di,ai")))] - "" - "div.h %2,%0" - [(set_attr "type" "divw")]) - -(define_insn "divqi3" - [(set (match_operand:QI 0 "register_operand" "=d") - (div:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "d")))] - "" - "div.b %2,%0" - [(set_attr "type" "divw")]) - -;;- Bit clear instructions. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (and:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "" "")))] - "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - || (GET_CODE (operands[2]) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (operands[2]) == -1)" - "and %2,%0") - -(define_insn "anddi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (and:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "register_operand" "d")))] - "" - "and %2,%0") - -(define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (and:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "di,ai")))] - "" - "and %2,%0") - -(define_insn "andhi3" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (and:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "nonmemory_operand" "di,ai")))] - "" - "and %2,%0") - -(define_insn "andqi3" - [(set (match_operand:QI 0 "register_operand" "=d,a") - (and:QI (match_operand:QI 1 "register_operand" "%0,0") - (match_operand:QI 2 "nonmemory_operand" "di,ai")))] - "" - "and %2,%0") - -;;- Bit set instructions. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (ior:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "" "")))] - "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0) - || (GET_CODE (operands[2]) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (operands[2]) == 0)" - "or %2,%0") - -(define_insn "iordi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (ior:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "register_operand" "d")))] - "" - "or %2,%0") - -(define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (ior:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "di,ai")))] - "" - "or %2,%0") - -(define_insn "iorhi3" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (ior:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "nonmemory_operand" "di,ai")))] - "" - "or %2,%0") - -(define_insn "iorqi3" - [(set (match_operand:QI 0 "register_operand" "=d,a") - (ior:QI (match_operand:QI 1 "register_operand" "%0,0") - (match_operand:QI 2 "nonmemory_operand" "di,ai")))] - "" - "or %2,%0") - -;;- xor instructions. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (xor:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "" "")))] - "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0) - || (GET_CODE (operands[2]) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (operands[2]) == 0)" - "xor %2,%0") - -(define_insn "xordi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (xor:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "register_operand" "d")))] - "" - "xor %2,%0") - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (xor:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "nonmemory_operand" "di,ai")))] - "" - "xor %2,%0") - -(define_insn "xorhi3" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (xor:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "nonmemory_operand" "di,ai")))] - "" - "xor %2,%0") - -(define_insn "xorqi3" - [(set (match_operand:QI 0 "register_operand" "=d,a") - (xor:QI (match_operand:QI 1 "register_operand" "%0,0") - (match_operand:QI 2 "nonmemory_operand" "di,ai")))] - "" - "xor %2,%0") - -(define_insn "negdf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (neg:DF (match_operand:DF 1 "register_operand" "d")))] - "" - "neg.d %1,%0" - [(set_attr "type" "addd")]) - -(define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (neg:SF (match_operand:SF 1 "register_operand" "d")))] - "" - "neg.s %1,%0" - [(set_attr "type" "adds")]) - -(define_insn "negdi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (neg:DI (match_operand:DI 1 "register_operand" "d")))] - "" - "neg.l %1,%0") - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (neg:SI (match_operand:SI 1 "register_operand" "d,a")))] - "" - "neg.w %1,%0") - -(define_insn "neghi2" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (neg:HI (match_operand:HI 1 "register_operand" "d,a")))] - "" - "neg.h %1,%0") - -(define_insn "negqi2" - [(set (match_operand:QI 0 "register_operand" "=d") - (neg:QI (match_operand:QI 1 "register_operand" "d")))] - "" - "neg.b %1,%0") - -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (not:DI (match_operand:DI 1 "register_operand" "d")))] - "" - "not %1,%0") - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (not:SI (match_operand:SI 1 "register_operand" "d,a")))] - "" - "not %1,%0") - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "register_operand" "=d,a") - (not:HI (match_operand:HI 1 "register_operand" "d,a")))] - "" - "not %1,%0") - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "register_operand" "=d,a") - (not:QI (match_operand:QI 1 "register_operand" "d,a")))] - "" - "not %1,%0") - -;;- Shifts -;; -;; The extreme profusion of patterns here is due to the different-speed -;; shifts on different machines, and the C1's lack of word shift S-register -;; instructions. - -;; SImode - -;; Arithmetic left 1, 1 cycle on all machines via add - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (match_operand:SI 1 "register_operand" "0") - (const_int 1)))] - "" - "add.w %0,%0") - -;; C34 general shift is 1 cycle - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (ashift:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "di,ai")))] - "TARGET_C34" - "@ - shf.w %2,%0 - shf %2,%0" - [(set_attr "type" "shfw,shfw")]) - -;; else shift left 0..7 is 1 cycle if we use an A register - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a,?d") - (ashift:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "immediate_operand" "ai,di")))] - "TARGET_C1 && INTVAL (operands[2]) < (unsigned) 8" - "@ - shf %2,%0 - shf %2,%0" - [(set_attr "type" "alu,shfl")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a,?d") - (ashift:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "immediate_operand" "ai,di")))] - "INTVAL (operands[2]) < (unsigned) 8" - "@ - shf %2,%0 - shf.w %2,%0" - [(set_attr "type" "alu,shfw")]) - -;; else general left shift - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (ashift:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "di,ai")))] - "TARGET_C1" - "@ - shf %2,%0 - shf %2,%0" - [(set_attr "type" "shfl,shfw")]) - -;; but C2 left shift by a constant is faster via multiply - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "const_int_operand" "i")))] - "TARGET_C2 && INTVAL (operands[2]) < (unsigned) 32" - "mul.w %z2,%0" - [(set_attr "type" "mulw")]) - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "=d,a") - (ashift:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "nonmemory_operand" "di,ai")))] - "" - "@ - shf.w %2,%0 - shf %2,%0" - [(set_attr "type" "shfw,shfw")]) - -;; Logical right, general -;; The hardware wants the negative of the shift count - -(define_expand "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "") - (neg:SI (match_operand:SI 2 "nonmemory_operand" ""))))] - "" - "operands[2] = negate_rtx (SImode, operands[2]);") - -;; C1 lacks word shift S reg - -(define_insn "" - [(set - (match_operand:SI 0 "register_operand" "=a,?d") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "ai,di"))))] - "TARGET_C1" - "@ - shf %2,%0 - ld.u #0,%0\;shf %2,%0" - [(set_attr "type" "shfw,shfl")]) - -;; general case - -(define_insn "" - [(set - (match_operand:SI 0 "register_operand" "=d,a") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "di,ai"))))] - "" - "@ - shf.w %2,%0 - shf %2,%0" - [(set_attr "type" "shfw,shfw")]) - -;; Patterns without neg produced by constant folding - -(define_insn "" - [(set - (match_operand:SI 0 "register_operand" "=a,?d") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "immediate_operand" "i,i")))] - "TARGET_C1" - "@ - shf #%n2,%0 - ld.u #0,%0\;shf #%n2,%0" - [(set_attr "type" "shfw,shfl")]) - -(define_insn "" - [(set - (match_operand:SI 0 "register_operand" "=d,a") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "immediate_operand" "i,i")))] - "" - "@ - shf.w #%n2,%0 - shf #%n2,%0" - [(set_attr "type" "shfw,shfw")]) - -;; Arithmetic right, general -;; Sign-extend to 64 bits, then shift that. Works for 0..32. - -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "") - (neg:SI (match_operand:SI 2 "nonmemory_operand" ""))))] - "" - "operands[2] = negate_rtx (SImode, operands[2]);") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,&d") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,d") - (neg:SI - (match_operand:SI 2 "nonmemory_operand" "di,di"))))] - "" - "cvtw.l %1,%0\;shf %2,%0" - [(set_attr "type" "shfl,shfl")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "cvtw.l %1,%0\;shf #%n2,%0" - [(set_attr "type" "shfl")]) - -;; DImode -;; Arithmetic left, 1-cycle - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (ashift:DI (match_operand:DI 1 "register_operand" "0") - (const_int 1)))] - "" - "add.l %0,%0") - -;; Arithmetic left, general - -(define_insn "ashldi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (ashift:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "di")))] - "" - "shf %2,%0" - [(set_attr "type" "shfl")]) - -;; Can omit zero- or sign-extend if shift is 32 or more. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0")) - (match_operand:SI 2 "const_int_operand" "i")))] - "INTVAL (operands[2]) >= 32" - "shf %2,%0" - [(set_attr "type" "shfl")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (ashift:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "0")) - (match_operand:SI 2 "const_int_operand" "i")))] - "INTVAL (operands[2]) >= 32" - "shf %2,%0" - [(set_attr "type" "shfl")]) - -;; Logical right, general - -(define_expand "lshrdi3" - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (neg:SI (match_operand:SI 2 "nonmemory_operand" ""))))] - "" - "operands[2] = negate_rtx (SImode, operands[2]);") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "di"))))] - "" - "shf %2,%0" - [(set_attr "type" "shfl")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - "shf #%n2,%0" - [(set_attr "type" "shfl")]) - -;; Arithmetic right, general -;; Use -;; ((a >> b) ^ signbit) - signbit -;; where signbit is (1 << 63) >> b -;; Works for 0..63. Does not work for 64; unfortunate but valid. - -(define_expand "ashrdi3" - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (neg:SI (match_operand:SI 2 "nonmemory_operand" "")))) - (set (match_dup 3) (lshiftrt:DI (match_dup 3) (neg:SI (match_dup 2)))) - (set (match_dup 0) (xor:DI (match_dup 0) (match_dup 3))) - (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 3)))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - switch (INTVAL (operands[2])) - { - case 32: - emit_insn (gen_ashrdi3_32 (operands[0], operands[1])); - DONE; - } - - operands[2] = negate_rtx (SImode, operands[2]); - operands[3] = force_reg (DImode, immed_double_const (0, 1 << 31, DImode)); -}") - -;; Arithmetic right 32, a common case that can save a couple of insns. - -(define_expand "ashrdi3_32" - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (const_int 32))) - (set (match_dup 0) - (sign_extend:DI (subreg:SI (match_dup 0) 0)))] - "" - "") - -;; __builtin instructions - -(define_insn "sqrtdf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (sqrt:DF (match_operand:DF 1 "register_operand" "0")))] - "! TARGET_C1 && flag_fast_math" - "sqrt.d %0" - [(set_attr "type" "divd")]) - -(define_insn "sqrtsf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (sqrt:SF (match_operand:SF 1 "register_operand" "0")))] - "! TARGET_C1 && flag_fast_math" - "sqrt.s %0" - [(set_attr "type" "divs")]) - -(define_insn "sindf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] - "! TARGET_C1 && flag_fast_math" - "sin.d %0") - -(define_insn "sinsf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] - "! TARGET_C1 && flag_fast_math" - "sin.s %0") - -(define_insn "cosdf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] - "! TARGET_C1 && flag_fast_math" - "cos.d %0") - -(define_insn "cossf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] - "! TARGET_C1 && flag_fast_math" - "cos.s %0") - -(define_insn "ftruncdf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (fix:DF (match_operand:DF 1 "register_operand" "d")))] - "! TARGET_C1" - "frint.d %1,%0" - [(set_attr "type" "cvtd")]) - -(define_insn "ftruncsf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (fix:SF (match_operand:SF 1 "register_operand" "d")))] - "! TARGET_C1" - "frint.s %1,%0" - [(set_attr "type" "cvts")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d")) - (const_int 1)))] - "" - "tzc %1,%0\;le.w #32,%0\;jbrs.f L0%=\;ld.w #-1,%0\\nL0%=:") - -(define_expand "ffssi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d")) - (const_int 1))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int 1)))] - "" - "") - -(define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (abs:SF (match_operand:SF 1 "register_operand" "0")))] - "" - "and #0x7fffffff,%0") - -(define_expand "absdf2" - [(set (subreg:DI (match_operand:DF 0 "register_operand" "=d") 0) - (and:DI (subreg:DI (match_operand:DF 1 "register_operand" "d") 0) - (match_dup 2)))] - "" - "operands[2] = force_reg (DImode, - immed_double_const (-1, 0x7fffffff, DImode));") - -;;- Compares - -(define_insn "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "register_operand" "d") - (match_operand:DI 1 "register_operand" "d")))] - "" - "* return output_cmp (operands[0], operands[1], 'l');") - -(define_insn "" - [(set (cc0) (match_operand:DI 0 "register_operand" "d")) - (clobber (match_scratch:DI 1 "=d"))] - "next_insn_tests_no_inequality (insn)" - "* return output_cmp (operands[0], operands[1], 'L');") - -(define_insn "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "d,a") - (match_operand:SI 1 "nonmemory_operand" "di,ai")))] - "" - "* return output_cmp (operands[0], operands[1], 'w');") - -(define_insn "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "register_operand" "d,a") - (match_operand:HI 1 "nonmemory_operand" "di,ai")))] - "" - "* return output_cmp (operands[0], operands[1], 'h');") - -; cmpqi is intentionally omitted. -; -; gcc will sign-extend or zero-extend the operands to the next -; wider mode, HImode. -; -; For reg .cmp. constant, we just go with the halfword immediate -; instruction. Perhaps the widening insn can be cse'd or combined away. -; If not, we're still as good as loading a byte constant into a register -; to do a reg-reg byte compare. -; -; The following patterns pick up cases that can use reg .cmp. reg after all. - -(define_insn "" - [(set (cc0) - (compare - (sign_extend:HI (match_operand:QI 0 "register_operand" "d")) - (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))))] - "" - "* return output_cmp (operands[0], operands[1], 'b');") - -(define_insn "" - [(set (cc0) - (compare - (ashift:HI (subreg:HI (match_operand:QI 0 "register_operand" "d") 0) - (const_int 8)) - (ashift:HI (subreg:HI (match_operand:QI 1 "register_operand" "d") 0) - (const_int 8))))] - "" - "* return output_cmp (operands[0], operands[1], 'b');") - -(define_insn "" - [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "d") - (match_operand:QI 1 "register_operand" "d")))] - "" - "* return output_cmp (operands[0], operands[1], 'b');") - -(define_insn "" - [(set (cc0) (match_operand:QI 0 "register_operand" "d")) - (clobber (match_scratch:QI 1 "=d"))] - "next_insn_tests_no_inequality (insn)" - "* return output_cmp (operands[0], operands[1], 'B');") - -(define_insn "" - [(set (cc0) (subreg (match_operand:QI 0 "register_operand" "d") 0)) - (clobber (match_scratch:QI 1 "=d"))] - "next_insn_tests_no_inequality (insn)" - "* return output_cmp (operands[0], operands[1], 'B');") - -(define_insn "" - [(set (cc0) - (zero_extend (subreg (match_operand:QI 0 "register_operand" "d") 0))) - (clobber (match_scratch:QI 1 "=d"))] - "next_insn_tests_no_inequality (insn)" - "* return output_cmp (operands[0], operands[1], 'B');") - -(define_insn "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "register_operand" "d") - (match_operand:DF 1 "register_operand" "d")))] - "" - "* return output_cmp (operands[0], operands[1], 'd');") - -(define_insn "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "register_operand" "d") - (match_operand:SF 1 "nonmemory_cmpsf_operand" "dF")))] - "" - "* return output_cmp (operands[0], operands[1], 's');") - -;; decrement-and-set-cc0 insns. -;; -;; The most important case where we can use the carry bit from an -;; arithmetic insn to eliminate a redundant compare is the decrement in -;; constructs like while (n--) and while (--n >= 0). -;; -;; We do it with combine patterns instead of NOTICE_UPDATE_CC because -;; the decrement needs to be kept at the end of the block during scheduling. -;; -;; These patterns must have memory alternatives because reload refuses -;; to do output reloads for an insn that sets cc0 (since it does not -;; want to clobber cc0 with its moves). Convex moves do not clobber -;; cc0, but there is no evident way to get reload to know that. - -(define_insn "" - [(set (cc0) - (match_operand:SI 0 "register_operand" "+r,*m")) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))] - "next_insn_tests_no_inequality (insn)" - "* -{ - if (which_alternative == 0) - { - output_cmp (operands[0], constm1_rtx, 'W'); - return \"add.w #-1,%0\"; - } - else - { - output_cmp (gen_rtx (REG, SImode, 7), constm1_rtx, 'W'); - return \"psh.w s7\;ld.w %0,s7\;add.w #-1,s7\;st.w s7,%0\;pop.w s7\"; - } -}") - -(define_insn "" - [(set (cc0) - (plus:SI (match_operand:SI 0 "register_operand" "+r,*m") - (const_int -1))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))] - "find_reg_note (next_cc0_user (insn), REG_NONNEG, 0)" - "* -{ - if (which_alternative == 0) - { - output_cmp (operands[0], const0_rtx, 'W'); - return \"add.w #-1,%0\"; - } - else - { - output_cmp (gen_rtx (REG, SImode, 7), const0_rtx, 'W'); - return \"psh.w s7\;ld.w %0,s7\;add.w #-1,s7\;st.w s7,%0\;pop.w s7\"; - } -}") - -(define_insn "" - [(set (cc0) - (match_operand:HI 0 "register_operand" "+r,*m")) - (set (match_dup 0) - (plus:HI (match_dup 0) - (const_int -1)))] - "next_insn_tests_no_inequality (insn)" - "* -{ - if (which_alternative == 0) - { - output_cmp (operands[0], constm1_rtx, 'H'); - return \"add.h #-1,%0\"; - } - else - { - output_cmp (gen_rtx (REG, HImode, 7), constm1_rtx, 'H'); - return \"psh.w s7\;ld.h %0,s7\;add.h #-1,s7\;st.h s7,%0\;pop.w s7\"; - } -}") - -(define_insn "" - [(set (cc0) - (plus:HI (match_operand:HI 0 "register_operand" "+r,*m") - (const_int -1))) - (set (match_dup 0) - (plus:HI (match_dup 0) - (const_int -1)))] - "find_reg_note (next_cc0_user (insn), REG_NONNEG, 0)" - "* -{ - if (which_alternative == 0) - { - output_cmp (operands[0], const0_rtx, 'H'); - return \"add.h #-1,%0\"; - } - else - { - output_cmp (gen_rtx (REG, HImode, 7), const0_rtx, 'H'); - return \"psh.w s7\;ld.h %0,s7\;add.h #-1,s7\;st.h s7,%0\;pop.w s7\"; - } -}") - -;;- Jumps - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "jbr %l0") - -(define_insn "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"eq\", 't'); ") - -(define_insn "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"eq\", 'f'); ") - -(define_insn "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"le\", 'f'); ") - -(define_insn "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"leu\", 'f'); ") - -(define_insn "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"lt\", 't'); ") - -(define_insn "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"ltu\", 't'); ") - -(define_insn "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"lt\", 'f'); ") - -(define_insn "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"ltu\", 'f'); ") - -(define_insn "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"le\", 't'); ") - -(define_insn "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return output_condjump (operands[0], \"leu\", 't'); ") - -(define_insn "" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"eq\", 'f'); ") - -(define_insn "" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"eq\", 't'); ") - -(define_insn "" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"le\", 't'); ") - -(define_insn "" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"leu\", 't'); ") - -(define_insn "" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"lt\", 'f'); ") - -(define_insn "" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"ltu\", 'f'); ") - -(define_insn "" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"lt\", 't'); ") - -(define_insn "" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"ltu\", 't'); ") - -(define_insn "" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"le\", 'f'); ") - -(define_insn "" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return output_condjump (operands[0], \"leu\", 'f'); ") - -;;- Calls - -(define_expand "call_pop" - [(parallel [(call (match_operand:QI 0 "memory_operand" "m") - (match_operand:SI 1 "const_int_operand" "i")) - (match_operand:SI 2 "const_int_operand" "i") - (match_operand:SI 3 "const_int_operand" "i") - (reg:SI 8)])] - "" - "") - -(define_insn "" - [(call (match_operand:QI 0 "memory_operand" "m") - (match_operand:SI 1 "const_int_operand" "i")) - (match_operand:SI 2 "const_int_operand" "i") - (match_operand:SI 3 "const_int_operand" "i") - (match_operand:SI 4 "" "")] - "" - "* return output_call (insn, &operands[0]);") - -(define_expand "call_value_pop" - [(parallel [(set (match_operand 0 "" "=g") - (call (match_operand:QI 1 "memory_operand" "m") - (match_operand:SI 2 "const_int_operand" "i"))) - (match_operand:SI 3 "const_int_operand" "i") - (match_operand:SI 4 "const_int_operand" "i") - (reg:SI 8)])] - "" - "") - -(define_insn "" - [(set (match_operand 0 "" "=g") - (call (match_operand:QI 1 "memory_operand" "m") - (match_operand:SI 2 "const_int_operand" "i"))) - (match_operand:SI 3 "const_int_operand" "i") - (match_operand:SI 4 "const_int_operand" "i") - (match_operand:SI 5 "" "")] - "" - "* return output_call (insn, &operands[1]); ") - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - emit_call_insn (gen_call_pop (operands[0], const0_rtx, - const0_rtx, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "") - -(define_expand "return" - [(return)] - "" - " replace_arg_pushes (); ") - -(define_insn "" - [(return)] - "" - "rtn") - -(define_expand "prologue" - [(const_int 0)] - "" - " -{ - emit_ap_optimizations (); - DONE; -}") - -(define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "address_operand" "p")) - (use (label_ref (match_operand 1 "" "")))] - "" - "jmp %a0") - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "address_operand" "p"))] - "" - "jmp %a0") diff --git a/gcc/config/convex/fixinc.convex b/gcc/config/convex/fixinc.convex deleted file mode 100755 index 0dc5f30..0000000 --- a/gcc/config/convex/fixinc.convex +++ /dev/null @@ -1,416 +0,0 @@ - -# This is a shell archive. Remove anything before this line, -# then unpack it by saving it in a file and typing "sh file". -# -# Wrapped by on Fri Mar 12 08:41:28 CST 1993 -# Contents: include/ include/limits.h include/math.h include/stddef.h -# include/stdlib.h - -echo mkdir - include -mkdir include -chmod u=rwx,g=rwx,o=rx include - -echo x - include/limits.h -sed 's/^@//' > "include/limits.h" <<'@//E*O*F include/limits.h//' -#ifndef _LIMITS_H -#define _LIMITS_H - -#include_next - -/* Minimum and maximum values a `char' can hold. */ -#ifdef __CHAR_UNSIGNED__ -#undef CHAR_MIN -#define CHAR_MIN 0 -#undef CHAR_MAX -#define CHAR_MAX 255 -#endif - -#endif /* _LIMITS_H */ -@//E*O*F include/limits.h// -chmod u=rw,g=rw,o=r include/limits.h - -echo x - include/math.h -sed 's/^@//' > "include/math.h" <<'@//E*O*F include/math.h//' -#ifndef _MATH_H -#define _MATH_H - -#include_next - -#undef HUGE_VAL - -#if _IEEE_FLOAT_ -#define HUGE_VAL 1.79769313486231570e+308 -#else -#define HUGE_VAL 8.98846567431157854e+307 -#endif - -#if __OPTIMIZE__ && ! __NO_INLINE - -#define frexp(x,y) __inline_frexp ((x), (y)) -#define ldexp(x,y) __inline_ldexp ((x), (y)) -#define irint(x) __inline_irint (x) -#define frexpf(x,y) __inline_frexpf ((x), (y)) -#define ldexpf(x,y) __inline_ldexpf ((x), (y)) -#define irintf(x) __inline_irintf (x) - -#if __convex_c2__ || __convex_c32__ || __convex_c34__ || __convex_c38__ - -#define atan(x) __inline_atan (x) -#define ceil(x) __inline_ceil (x) -#define cos(x) __inline_cos (x) -#define exp(x) __inline_exp (x) -#define floor(x) __inline_floor (x) -#define log(x) __inline_log (x) -#define log10(x) __inline_log10 (x) -#define modf(x,y) __inline_modf ((x), (y)) -#define rint(x) __inline_rint (x) -#define sin(x) __inline_sin (x) -#define sqrt(x) __inline_sqrt (x) - -#define atanf(x) __inline_atanf (x) -#define ceilf(x) __inline_ceilf (x) -#define cosf(x) __inline_cosf (x) -#define expf(x) __inline_expf (x) -#define floorf(x) __inline_floorf (x) -#define logf(x) __inline_logf (x) -#define log10f(x) __inline_log10f (x) -#define modff(x,y) __inline_modff ((x), (y)) -#define rintf(x) __inline_rintf (x) -#define sinf(x) __inline_sinf (x) -#define sqrtf(x) __inline_sqrtf (x) - -#endif /* __convex_c[23*]__ */ - -#endif /* __OPTIMIZE__ */ - -static __inline__ __const__ double __inline_atan (double x) -{ - double z; - __asm__ ("atan.d %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ float __inline_atanf (float x) -{ - float z; - __asm__ ("atan.s %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ double __inline_cos (double x) -{ - double z; - __asm__ ("cos.d %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ float __inline_cosf (float x) -{ - float z; - __asm__ ("cos.s %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ double __inline_exp (double x) -{ - double z; - __asm__ ("exp.d %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ float __inline_expf (float x) -{ - float z; - __asm__ ("exp.s %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ double __inline_log (double x) -{ - double z; - __asm__ ("ln.d %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ float __inline_logf (float x) -{ - float z; - __asm__ ("ln.s %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ double __inline_sin (double x) -{ - double z; - __asm__ ("sin.d %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ float __inline_sinf (float x) -{ - float z; - __asm__ ("sin.s %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ double __inline_sqrt (double x) -{ - double z; - __asm__ ("sqrt.d %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ float __inline_sqrtf (float x) -{ - float z; - __asm__ ("sqrt.s %0" : "=d" (z) : "0" (x)); - return z; -} - -static __inline__ __const__ double __inline_ceil (double x) -{ - double z; - __asm__ ("frint.d %1,%0" : "=d" (z) : "d" (x)); - if (z < x) z += 1.0; - return z; -} - -static __inline__ __const__ float __inline_ceilf (float x) -{ - float z; - __asm__ ("frint.s %1,%0" : "=d" (z) : "d" (x)); - if (z < x) z += 1.0F; - return z; -} - -static __inline__ __const__ double __inline_floor (double x) -{ - double z; - __asm__ ("frint.d %1,%0" : "=d" (z) : "d" (x)); - if (z > x) z -= 1.0; - return z; -} - -static __inline__ __const__ float __inline_floorf (float x) -{ - float z; - __asm__ ("frint.s %1,%0" : "=d" (z) : "d" (x)); - if (z > x) z -= 1.0F; - return z; -} - -static __inline__ __const__ double __inline_log10 (double x) -{ - return 0.43429448190325182765 * __inline_log (x); -} - -static __inline__ __const__ float __inline_log10f (float x) -{ - return 0.43429448190325182765F * __inline_logf (x); -} - -static __inline__ double __inline_modf (double x, double *np) -{ - double intpart; - __asm__ ("frint.d %1,%0" : "=d" (intpart) : "d" (x)); - *np = intpart; - return x - intpart; -} - -static __inline__ float __inline_modff (float x, float *np) -{ - float intpart; - __asm__ ("frint.s %1,%0" : "=d" (intpart) : "d" (x)); - *np = intpart; - return x - intpart; -} - -static __inline__ double __inline_frexp (double x, int *np) -{ - union u { double d; unsigned long long ll; } u; - if ((u.d = x) == 0) - *np = 0; - else - { -#if _IEEE_FLOAT_ - *np = ((u.ll >> 52) & 03777) - 01776; - u.ll = (u.ll & 0x800fffffffffffffLL) | 0x3fe0000000000000LL; -#else - *np = ((u.ll >> 52) & 03777) - 02000; - u.ll = (u.ll & 0x800fffffffffffffLL) | 0x4000000000000000LL; -#endif - } - return u.d; -} - -static __inline__ float __inline_frexpf (float x, int *np) -{ - union u { float f; unsigned int i; } u; - if ((u.f = x) == 0) - *np = 0; - else - { -#if _IEEE_FLOAT_ - *np = ((u.i >> 23) & 0377) - 0176; - u.i = (u.i & 0x807fffff) | 0x3f000000; -#else - *np = ((u.i >> 23) & 0377) - 0200; - u.i = (u.i & 0x807fffff) | 0x40000000; -#endif - } - return u.f; -} - -static __inline__ double __inline_ldexp (double x, int n) -{ - extern int errno; - union { double d; long long ll; unsigned sexp : 12; } u; - if ((u.d = x) != 0) - { - int exp = n + (u.sexp & 03777); - long long nn = (long long) n << 52; -#if _IEEE_FLOAT_ - if (exp <= 0) - u.ll &= 0x8000000000000000LL, errno = 34; - else if (exp > 03776) - u.ll = u.ll & 0x8000000000000000LL | 0x7fefffffffffffffLL, errno = 34; -#else - if (exp <= 0) - u.ll = 0, errno = 34; - else if (exp > 03777) - u.ll |= 0x7fffffffffffffffLL, errno = 34; -#endif - else - u.ll += nn; - } - return u.d; -} - -static __inline__ float __inline_ldexpf (float x, int n) -{ - extern int errno; - union { float f; int i; unsigned sexp : 9; } u; - if ((u.f = x) != 0) - { - int exp = n + (u.sexp & 0377); - int nn = n << 23; -#if _IEEE_FLOAT_ - if (exp <= 0) - u.i &= 0x80000000, errno = 34; - else if (exp > 0376) - u.i = u.i & 0x80000000 | 0x7f7fffff, errno = 34; -#else - if (exp <= 0) - u.i = 0, errno = 34; - else if (exp > 0377) - u.i |= 0x7fffffff, errno = 34; -#endif - else - u.i += nn; - } - return u.f; -} - -static __inline__ __const__ double __inline_rint (double x) -{ - double z; - union { double d; unsigned long long ll; } u; - u.d = x; -#if _IEEE_FLOAT_ - u.ll = (u.ll & 0x8000000000000000LL) | 0x3fe0000000000000LL; -#else - u.ll = (u.ll & 0x8000000000000000LL) | 0x4000000000000000LL; -#endif - __asm__ ("frint.d %1,%0" : "=d" (z) : "d" (x + u.d)); - return z; -} - -static __inline__ __const__ float __inline_rintf (float x) -{ - float z; - union { float f; unsigned int i; } u; - u.f = x; -#if _IEEE_FLOAT_ - u.i = (u.i & 0x80000000) | 0x3f000000; -#else - u.i = (u.i & 0x80000000) | 0x40000000; -#endif - __asm__ ("frint.s %1,%0" : "=d" (z) : "d" (x + u.f)); - return z; -} - -static __inline__ __const__ int __inline_irint (double x) -{ - union { double d; unsigned long long ll; } u; - u.d = x; -#if _IEEE_FLOAT_ - u.ll = (u.ll & 0x8000000000000000LL) | 0x3fe0000000000000LL; -#else - u.ll = (u.ll & 0x8000000000000000LL) | 0x4000000000000000LL; -#endif - return x + u.d; -} - -static __inline__ __const__ int __inline_irintf (float x) -{ - union { float f; unsigned int i; } u; - u.f = x; -#if _IEEE_FLOAT_ - u.i = (u.i & 0x80000000) | 0x3f000000; -#else - u.i = (u.i & 0x80000000) | 0x40000000; -#endif - return x + u.f; -} - -#endif /* _MATH_H */ -@//E*O*F include/math.h// -chmod u=rw,g=rw,o=r include/math.h - -echo x - include/stddef.h -sed 's/^@//' > "include/stddef.h" <<'@//E*O*F include/stddef.h//' -#ifndef _STDDEF_H -#define _STDDEF_H - -#ifndef __WCHAR_T -#define __WCHAR_T - -#ifdef __GNUG__ -/* In C++, wchar_t is a distinct basic type, - and we can expect __wchar_t to be defined by cc1plus. */ -typedef __wchar_t wchar_t; -#else -/* In C, cpp tells us which type to make an alias for. */ -typedef __WCHAR_TYPE__ wchar_t; -#endif - -#endif /* __WCHAR_T */ - -#include_next - -#endif /* _STDDEF_H */ -@//E*O*F include/stddef.h// -chmod u=rw,g=rw,o=r include/stddef.h - -echo x - include/stdlib.h -sed 's/^@//' > "include/stdlib.h" <<'@//E*O*F include/stdlib.h//' -#ifndef _STDLIB_H -#define _STDLIB_H - -#if _CONVEX_SOURCE - -#define alloca __non_builtin_alloca -#include_next -#undef alloca - -#else - -#include_next - -#endif /* _CONVEX_SOURCE */ - -#endif /* _STDLIB_H */ -@//E*O*F include/stdlib.h// -chmod u=rw,g=rw,o=r include/stdlib.h - -exit 0 diff --git a/gcc/config/convex/x-convex b/gcc/config/convex/x-convex deleted file mode 100755 index 8029ac5..0000000 --- a/gcc/config/convex/x-convex +++ /dev/null @@ -1,5 +0,0 @@ -# ld can make exe's c2-only if this lib is searched even though not loaded -CCLIBFLAGS = -tm c1 - -# Use -pcc to avoid surprises. -CC = cc -pcc diff --git a/gcc/config/convex/xm-convex.h b/gcc/config/convex/xm-convex.h deleted file mode 100755 index aaaa3b1..0000000 --- a/gcc/config/convex/xm-convex.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Configuration for GNU C-compiler for Convex. - Copyright (C) 1989, 1993, 1997 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 8 -#define HOST_BITS_PER_SHORT 16 -#define HOST_BITS_PER_INT 32 -#define HOST_BITS_PER_LONG 32 -#define HOST_BITS_PER_LONGLONG 64 - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* Convex ships /tmp as a separate file system - thus it - usually has more free space than /usr/tmp */ - -#define P_tmpdir "/tmp/" - -/* Convex uses Vax or IEEE floats. - Both formats have Vax semantics. */ - -#define HOST_FLOAT_FORMAT VAX_FLOAT_FORMAT diff --git a/gcc/config/d10v/abi b/gcc/config/d10v/abi deleted file mode 100755 index 70ae6dc..0000000 --- a/gcc/config/d10v/abi +++ /dev/null @@ -1,131 +0,0 @@ - -*- Text -*- - -This document describes the proposed ABI for the d10v. - -The register calling convention is: - - +-------+-----------------------+-----------------------+ - | Reg. | At prologue | After epilogue | - +-------+-----------------------+-----------------------+ - | R0 | Argument #1 | Return value, word 1 | - +-------+-----------------------+-----------------------+ - | R1 | Argument #2 | Return value, word 2 | - +-------+-----------------------+-----------------------+ - | R2 | Argument #3 | Return value, word 3 | - +-------+-----------------------+-----------------------+ - | R3 | Argument #4 | Return value, word 4 | - +-------+-----------------------+-----------------------+ - | R4 | Static chain if needed| Don't care | - +-------+-----------------------+-----------------------+ - | R5 | Work | Don't care | - +-------+-----------------------+-----------------------+ - | R6 | Work | Previous value | - +-------+-----------------------+-----------------------+ - | R7 | Work | Previous value | - +-------+-----------------------+-----------------------+ - | R8 | Work | Previous value | - +-------+-----------------------+-----------------------+ - | R9 | Work | Previous value | - +-------+-----------------------+-----------------------+ - | R10 | Work | Previous value | - +-------+-----------------------+-----------------------+ - | R11 | Frame ptr if needed | Previous value | - +-------+-----------------------+-----------------------+ - | R12 | Work | Don't care | - +-------+-----------------------+-----------------------+ - | R13 | Return address | Don't care | - +-------+-----------------------+-----------------------+ - | R14 | memory base (0) | memory base (0) | - +-------+-----------------------+-----------------------+ - | R15 | Stack pointer | Previous value | - +-------+-----------------------+-----------------------+ - | A0 | Work | Previous value | - +-------+-----------------------+-----------------------+ - | A1 | Work | Previous value | - +-------+-----------------------+-----------------------+ - - -The 'int' type is 16 bits, unless the -mint32 switch is used. The 'long' type -is always 32 bits, the 'short' type is always 16 bits, and pointers are 16 -bits. - -The 'double' type is treated as 'float' and uses 32-bits unless the -mdouble64 -switch is used. The long double type still uses 64 bits. - -If more than 4 words of arguments are passed, they are passed on the stack. - -The GCC compiler will omit the frame pointer for all functions except those -that dynamically grow the stack frame (ie, the GNU extensions of variable sized -arrays or calls to alloca). The GCC compiler will always eliminate the -pseudo argument pointer the compiler synthesizes in favor of the stack or frame -pointer. - -The GCC compiler only passes the static chain when calling nested functions, -which is a GNU extension. - -The stack starts at high memory and descends downward. The heap starts at the -end of the bss section and ascends upward. The stack is assumed to be aligned -to a word boundary. - -Register r14 will be used as the index register in accessing global/static -variables if no index register is used. The crt0 that we provide will place a -zero in it, and the compiler will expect that. - -The varargs/stdarg support defines the va_list type as follows: - - typedef struct __va_list_tag { - short *__va_arg_ptr; /* start of the register save area */ - int __va_arg_num; /* argument number */ - } va_list[1]; - -It is an array so that passing it to vprintf and friends passes just a pointer -to the structure. Calls to varargs/stdarg functions push the four words -corresponding to the first four arguments on the stack immediately before -adjusting the stack pointer any further. - -The stack frame when a function is called looks like: - -high | .... | - +-------------------------------+ - | Argument word #8 | - +-------------------------------+ - | Argument word #7 | - +-------------------------------+ - | Argument word #6 | - +-------------------------------+ - | Argument word #5 | -low SP----> +-------------------------------+ - -After the prologue is executed, the stack frame will look like: - -high | .... | - +-------------------------------+ - | Argument word #8 | - +-------------------------------+ - | Argument word #7 | - +-------------------------------+ - | Argument word #6 | - +-------------------------------+ - | Argument word #5 | - Prev sp +-------------------------------+ - | | - | Save for arguments 1..4 if | - | the func. uses stdarg/varargs | - | | - +-------------------------------+ - | | - | Local variables | - | | - +-------------------------------+ - | | - | Save area for preserved regs | - | | - +-------------------------------+ - | | - | alloca space if used | - | | - +-------------------------------+ - | | - | Space for outgoing arguments | - | | -low SP----> +-------------------------------+ diff --git a/gcc/config/d10v/d10v.c b/gcc/config/d10v/d10v.c deleted file mode 100755 index 27deaf7..0000000 --- a/gcc/config/d10v/d10v.c +++ /dev/null @@ -1,3880 +0,0 @@ -/* CYGNUS LOCAL -- meissner/d10v abi change */ -/* Subroutines used for Mitsubishi D10V. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. - Contributed by Cygnus Support. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "recog.h" -#include "tree.h" -#include "expr.h" -#include "obstack.h" -#include "except.h" -#include "function.h" - -/* Operands to compare before the appropriate branch is done. */ -struct rtx_def *compare_op0; -struct rtx_def *compare_op1; - -/* Whether or not a hard register can accept a register */ -unsigned char hard_regno_mode_ok[ (int)MAX_MACHINE_MODE ][FIRST_PSEUDO_REGISTER]; - -/* Whether to try and avoid moves between two different modes */ -unsigned char modes_tieable_p[ (NUM_MACHINE_MODES) * (NUM_MACHINE_MODES) ]; - -/* Map register number to smallest register class. */ -enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER]; - -/* Map class letter into register class */ -enum reg_class reg_class_from_letter[256]; - -/* Values of the -mbranch-cost=n string. */ -int d10v_branch_cost = 1; -char *d10v_branch_cost_string = (char *)0; - -/* Values of the -mcond-exec=n string. */ -int d10v_cond_exec = 4; -char *d10v_cond_exec_string = (char *)0; - -static void d10v_split_constant32 PROTO ((rtx x, int values[])); -static void d10v_split_constant64 PROTO ((rtx x, int values[])); - -/* Cached value of d10v_stack_info */ -static d10v_stack_t *d10v_stack_cache = (d10v_stack_t *)0; - - -/* Sometimes certain combinations of command options do not make - sense on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. - - Don't use this macro to turn on various extra optimizations for - `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ - -void -override_options () -{ - int regno, i, ok_p; - enum machine_mode mode1, mode2; - - /* Set up the branch cost information */ - if (d10v_branch_cost_string) - d10v_branch_cost = atoi (d10v_branch_cost_string); - - /* Set up max # instructions to use with conditional execution */ - if (d10v_cond_exec_string) - d10v_cond_exec = atoi (d10v_cond_exec_string); - - /* Setup hard_regno_mode_ok/modes_tieable_p */ - for (mode1 = VOIDmode; - (int)mode1 < NUM_MACHINE_MODES; - mode1 = (enum machine_mode)((int)mode1 + 1)) - { - int size = GET_MODE_SIZE (mode1); - int int_p = GET_MODE_CLASS (mode1) == MODE_INT; - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - if (mode1 == CCmode || mode1 == CC_REVmode) - ok_p = (regno == F0_REGNUM); - - else if (CR_P (regno)) - ok_p = 0; - - else if (ACCUM_P (regno)) - ok_p = (mode1 == SImode); - - else if (GPR_P (regno)) - { - if (mode1 == QImode || mode1 == HImode) - ok_p = 1; - else - ok_p = GPR_EVEN_P (regno); - } - else - ok_p = 0; - - hard_regno_mode_ok[ (int)mode1 ][ regno ] = ok_p; - } - - /* A C expression that is nonzero if it is desirable to choose - register allocation so as to avoid move instructions between a - value of mode MODE1 and a value of mode MODE2. - - If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, - MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1, - MODE2)' must be zero. */ - for (mode2 = VOIDmode; - (int)mode2 <= NUM_MACHINE_MODES; - mode2 = (enum machine_mode)((int)mode2 + 1)) - { - if (mode1 == mode2) - ok_p = 1; - - else if (mode1 == HImode || mode2 == QImode) - ok_p = (mode2 == HImode || mode2 == QImode); - - else - ok_p = 0; - - modes_tieable_p[ ((int)mode1 * (NUM_MACHINE_MODES)) + (int)mode2 ] = ok_p; - } - } - - /* A C expression whose value is a register class containing hard - register REGNO. In general there is more than one such class; - choose a class which is "minimal", meaning that no smaller class - also contains the register. */ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - enum reg_class class; - - switch (regno) - { - case GPR_FIRST + 4: - case GPR_FIRST + 5: - case GPR_FIRST + 6: - case GPR_FIRST + 7: - case GPR_FIRST + 8: - case GPR_FIRST + 9: - case GPR_FIRST + 10: - case GPR_FIRST + 11: - case GPR_FIRST + 12: - case GPR_FIRST + 14: - case GPR_FIRST + 15: - class = EVEN_REGS; - break; - - case ARG_FIRST + 0: /* r0 */ - class = ARG0_REGS; - break; - - case ARG_FIRST + 1: /* r1 */ - class = ARG1_REGS; - break; - - case ARG_FIRST + 2: /* r2 */ - class = ARG2_REGS; - break; - - case ARG_FIRST + 3: /* r3 */ - class = ARG3_REGS; - break; - - case GPR_FIRST + 13: /* r13 */ - class = RETURN_REGS; - break; - - case AP_FIRST: - class = GENERAL_REGS; - break; - - case ACCUM_FIRST + 0: - case ACCUM_FIRST + 1: - class = ACCUM_REGS; - break; - - case CR_FIRST + 7: - class = REPEAT_REGS; - break; - - case CR_FIRST + 0: - case CR_FIRST + 1: - case CR_FIRST + 2: - case CR_FIRST + 3: - case CR_FIRST + 4: - case CR_FIRST + 5: - case CR_FIRST + 6: - case CR_FIRST + 8: - case CR_FIRST + 9: - case CR_FIRST + 10: - case CR_FIRST + 11: - case CR_FIRST + 12: - case CR_FIRST + 13: - case CR_FIRST + 14: - case CR_FIRST + 15: - class = CR_REGS; - break; - - case F0_REGNUM: - class = F0_REGS; - break; - - case F1_REGNUM: - class = F1_REGS; - break; - - case CARRY_REGNUM: - class = CARRY_REGS; - break; - } - - regno_reg_class[regno] = class; - } - - /* A C expression which defines the machine-dependent operand - constraint letters for register classes. If CHAR is such a - letter, the value should be the register class corresponding to - it. Otherwise, the value should be `NO_REGS'. The register - letter `r', corresponding to class `GENERAL_REGS', will not be - passed to this macro; you do not need to handle it. - - The following letters are unavailable, due to being used as - constraints: - '0'..'9' - '<', '>' - 'E', 'F', 'G', 'H' - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' - 'Q', 'R', 'S', 'T', 'U' - 'V', 'X' - 'g', 'i', 'm', 'n', 'o', 'p', 'r', 's' */ - - for (i = 0; i < 256; i++) - reg_class_from_letter[i] = NO_REGS; - - reg_class_from_letter['C'] = CARRY_REGS; - reg_class_from_letter['a'] = ACCUM_REGS; - reg_class_from_letter['b'] = ARG0_REGS; - reg_class_from_letter['c'] = CR_REGS; - reg_class_from_letter['d'] = GENERAL_REGS; - reg_class_from_letter['e'] = EVEN_REGS; - reg_class_from_letter['f'] = F0_REGS; - reg_class_from_letter['h'] = ARG1_REGS; - reg_class_from_letter['j'] = ARG2_REGS; - reg_class_from_letter['l'] = RETURN_REGS; - reg_class_from_letter['q'] = ARG3_REGS; - reg_class_from_letter['x'] = CC_REGS; - reg_class_from_letter['y'] = F1_REGS; - reg_class_from_letter['z'] = REPEAT_REGS; -} - - -/* Define this macro if references to a symbol must be treated - differently depending on something about the variable or function - named by the symbol (such as what section it is in). - - The macro definition, if any, is executed immediately after the - rtl for DECL has been created and stored in `DECL_RTL (DECL)'. - The value of the rtl will be a `mem' whose address is a - `symbol_ref'. - - The usual thing for this macro to do is to record a flag in the - `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified - name string in the `symbol_ref' (if one bit is not enough - information). */ - -void -encode_section_info (decl) - tree decl; -{ - /* Mark functions so that we use the @word modifier to get a word - address instead of a byte address. We use the side_effects bit - on the identifier node to indicate word addresses are needed. */ - if (TREE_CODE (decl) == FUNCTION_DECL) - { - rtx symref = XEXP (DECL_RTL (decl), 0); - tree symid = get_identifier (XSTR (symref, 0)); - - SYMBOL_REF_FLAG (symref) = TRUE; - TREE_SIDE_EFFECTS (symid) = TRUE; - } -} - - -/* Return true if the register is a GPR */ - -int -gpr_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == REG) - { - int regno = REGNO (op); - if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER) - return GPR_P (regno); - - return register_operand (op, mode); - } - - else if (GET_CODE (op) == SUBREG) - { - rtx inner = SUBREG_REG (op); - if (GET_CODE (inner) == REG) - { - int regno = REGNO (SUBREG_REG (op)); - if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER) - return GPR_P (regno); - - return register_operand (op, mode); - } - - else if (GET_CODE (inner) == MEM && !reload_completed) - return d10v_legitimate_address_p (GET_MODE (inner), inner, 0); - } - - return FALSE; -} - -/* Return true if the register is an accumulator */ - -int -accum_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == REG) - { - int regno = REGNO (op); - if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER) - return ACCUM_P (regno); - - return register_operand (op, mode); - } - - else if (GET_CODE (op) == SUBREG) - { - rtx inner = SUBREG_REG (op); - if (GET_CODE (inner) == REG) - { - int regno = REGNO (SUBREG_REG (op)); - if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER) - return ACCUM_P (regno); - - return register_operand (op, mode); - } - - else if (GET_CODE (inner) == MEM && !reload_completed) - return d10v_legitimate_address_p (GET_MODE (inner), inner, 0); - } - - return FALSE; -} - -/* Return true if an operand is a register or is the constant 0. */ - -int -reg_or_0_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return INTVAL (op) == 0; - - else - return gpr_operand (op, mode); -} - -/* Return true if an operand is a register or a signed 16-bit constant. */ - -int -arith16_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -32768, 32767); - - else - return gpr_operand (op, mode); -} - -/* Return true if an operand is a register or a 4-bit unsigned constants, - or 4-bit negative unsigned constants. */ - -int -arith_4bit_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -16, 16) && INTVAL (op) != 0; - - else - return gpr_operand (op, mode); -} - -/* Return true if an operand is a register or a non negative constant. */ - -int -arith_nonnegative_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return (INTVAL (op) >= 0); - - else - return gpr_operand (op, mode); -} - -/* Return true if an operand is a register or a signed 32-bit constant. */ - -int -arith32_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return TRUE; - - else - return gpr_operand (op, mode); -} - -/* Return true if an operand is a register or a signed 64-bit constant. */ - -int -arith64_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE) - return TRUE; - - else - return gpr_operand (op, mode); -} - -/* Return true if an operand is a register or a constant with the lower 16-bits of 0. */ - -int -arith_lower0_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return ((INTVAL (op) & 0xffff) == 0); - - else - return gpr_operand (op, mode); -} - -int -ldi_shift_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (TARGET_SMALL_INSNS && optimize && GET_CODE (op) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (op); - int i; - - if (IN_RANGE_P (value, -8, 7)) - return FALSE; - - for (i = 1; i < 16; i++) - { - if (((value >> i) << i) == value && IN_RANGE_P (value >> i, -8, 7)) - return i; - } - } - - return FALSE; -} - -/* Return true if the operand is either the PC, a return, or a label_ref. */ - -int -pc_or_label_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (op == pc_rtx) - return TRUE; - - if (GET_CODE (op) == LABEL_REF) - return TRUE; - - if (GET_CODE (op) == RETURN && direct_return () && (d10v_stack_info ())->total_size == 0) - return TRUE; - - return FALSE; -} - -/* Return true if a memory operand is a short memory operand. */ - -int -short_memory_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - rtx addr; - - if (GET_CODE (op) != MEM) - return FALSE; - - addr = XEXP (op, 0); - switch (GET_CODE (addr)) - { - default: - break; - - case POST_INC: - case POST_DEC: - case PRE_DEC: - case REG: - return TRUE; - } - - return FALSE; -} - -/* Return true if an operand is simple, suitable for use in a conditional move */ - -int -cond_move_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (mode != QImode && mode != HImode && mode != SImode && mode != SFmode) - return FALSE; - - else if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) - return gpr_operand (op, mode) || (mode == SImode && accum_operand (op, mode)); - - else if (GET_CODE (op) == CONST_INT && (mode == QImode || mode == HImode)) - return IN_RANGE_P (INTVAL (op), -8, 7); - - /* Don't allow post dec/inc, since we might not get the side effects correct. */ - else if (GET_CODE (op) == MEM) - return (GET_CODE (XEXP (op, 0)) == REG); - - return FALSE; -} - -/* Return true if an operand is simple, suitable for use in conditional execution. - Unlike cond_move, we can allow auto inc/dec. */ - -int -cond_exec_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (mode != QImode && mode != HImode && mode != SImode && mode != SFmode) - return FALSE; - - else if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) - return gpr_operand (op, mode) || (mode == SImode && accum_operand (op, mode)); - - else if (GET_CODE (op) == CONST_INT && (mode == QImode || mode == HImode)) - return IN_RANGE_P (INTVAL (op), -8, 7); - - else if (GET_CODE (op) == MEM) - return short_memory_operand (op, mode); - - return FALSE; -} - -/* Return true if an operand is F0. */ - -int -carry_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != CCmode && GET_MODE (op) != CC_REVmode) - return FALSE; - - if (REGNO (op) != CARRY_REGNUM) - return FALSE; - - return 1; -} - -int -f0_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != CCmode && GET_MODE (op) != CC_REVmode) - return FALSE; - - if (REGNO (op) != F0_REGNUM) - return FALSE; - - return 1; -} - -/* Return true if an operand is F1. */ - -int -f1_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != CCmode && GET_MODE (op) != CC_REVmode) - return FALSE; - - if (REGNO (op) != F1_REGNUM) - return FALSE; - - return 1; -} - -/* Return true if an operand is F0 or F1. */ - -int -f_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != CCmode && GET_MODE (op) != CC_REVmode) - return FALSE; - - if (REGNO (op) != F0_REGNUM && REGNO (op) != F1_REGNUM) - return FALSE; - - return 1; -} - -/* Return true if the code is a test of f0 */ - -int -f0_compare_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - int i; - rtx x; - - if (GET_MODE (op) != CCmode && GET_MODE (op) != CC_REVmode) - return FALSE; - - if (GET_CODE (op) != NE && GET_CODE (op) != EQ) - return FALSE; - - x = XEXP (op, 0); - if (GET_CODE (x) != REG || REGNO (x) != F0_REGNUM) - return FALSE; - - x = XEXP (op, 1); - if (GET_CODE (x) != CONST_INT || INTVAL (x) != 0) - return FALSE; - - return TRUE; -} - -/* Return true if the code is a relational operations (EQ, LE, etc.) */ - -int -compare_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - int i; - rtx x; - - if (GET_MODE (op) != CCmode && GET_MODE (op) != CC_REVmode) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '<') - return FALSE; - - /* Don't allow paradoxical SUBREGs */ - for (i = 0; i < 2; i++) - { - x = XEXP (op, i); - while (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - if (!(GET_CODE (x) == REG || (i == 1 && GET_CODE (x) == CONST_INT))) - return FALSE; - } - - return TRUE; -} - -/* Return true if the code is a equality operation (EQ, NE) */ - -int -equality_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - int i; - rtx x; - - if (GET_MODE (op) != CCmode && GET_MODE (op) != CC_REVmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case EQ: - case NE: - break; - } - - /* Don't allow paradoxical SUBREGs */ - for (i = 0; i < 2; i++) - { - x = XEXP (op, i); - while (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - if (!(GET_CODE (x) == REG || (i == 1 && GET_CODE (x) == CONST_INT))) - return FALSE; - } - - return TRUE; -} - -/* Return true if the code is a signed relational operations (LT, LE, etc.) */ - -int -signed_compare_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - int i; - rtx x; - - if (GET_MODE (op) != CCmode && GET_MODE (op) != CC_REVmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case LT: - case LE: - case GT: - case GE: - break; - } - - /* Don't allow paradoxical SUBREGs */ - for (i = 0; i < 2; i++) - { - x = XEXP (op, i); - while (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - if (!(GET_CODE (x) == REG || (i == 1 && GET_CODE (x) == CONST_INT))) - return FALSE; - } - - return TRUE; -} - -/* Return true if the code is a unsigned relational operations (LEU, etc.) */ - -int -unsigned_compare_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - int i; - rtx x; - - if (GET_MODE (op) != CCmode && GET_MODE (op) != CC_REVmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case LTU: - case LEU: - case GTU: - case GEU: - break; - } - - /* Don't allow paradoxical SUBREGs */ - for (i = 0; i < 2; i++) - { - x = XEXP (op, i); - while (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - if (!(GET_CODE (x) == REG || (i == 1 && GET_CODE (x) == CONST_INT))) - return FALSE; - } - - return TRUE; -} - -/* Return true if the unary operator can go inside of a exef0{f,t} || operation. */ - -int -unary_parallel_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx op0; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '1') - return FALSE; - - op0 = XEXP (op, 0); - while (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - switch (GET_CODE (op)) - { - case NEG: - case NOT: - case SIGN_EXTEND: - case ZERO_EXTEND: - if (GET_MODE (op) == HImode && GET_CODE (op0) == REG && GPR_P (REGNO (op0))) - return TRUE; - - break; - } - - return FALSE; -} - -/* Return true if the binary operator can go inside of a exef0{f,t} || operation. */ - -int -binary_parallel_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx op0, op1; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '2' && GET_RTX_CLASS (GET_CODE (op)) != 'c') - return FALSE; - - op0 = XEXP (op, 0); - op1 = XEXP (op, 1); - - while (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - while (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - - if (GET_CODE (op0) != REG) - return FALSE; - - /* reg1 op= reg2 */ - if (GET_CODE (op1) == REG) - { - switch (GET_CODE (op)) - { - case PLUS: - case MINUS: - if (GET_MODE (op) == SImode && GPR_P (REGNO (op0)) && GPR_P (REGNO (op1))) - return TRUE; - - /* fall through */ - - case MULT: - case AND: - case IOR: - case XOR: - case ASHIFT: - case ASHIFTRT: - case LSHIFTRT: - return (GET_MODE (op) == HImode && GPR_P (REGNO (op0)) && GPR_P (REGNO (op1))); - } - } - - /* reg op= constant */ - else if (GET_CODE (op1) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (op1); - int log; - - if (GET_MODE (op) == HImode) - switch (GET_CODE (op)) - { - case PLUS: - case MINUS: - return IN_RANGE_P (value, -16, 16); - - case IOR: - case XOR: - if (value == 0) - return TRUE; - - log = exact_log2 (value); - return IN_RANGE_P (log, 0, 15); - - case AND: - if ((value & 0xffff) == 0xffff) - return TRUE; - - log = exact_log2 (~value); - return IN_RANGE_P (log, 0, 15); - } - } - - return FALSE; -} - -/* Return true if the {sign,zero} extend operator from memory can go inside - of a exef0{f,t} || operation. */ - -int -extend_parallel_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '1') - return FALSE; - - switch (GET_CODE (op)) - { - case SIGN_EXTEND: - case ZERO_EXTEND: - if (GET_MODE (op) == HImode && short_memory_operand (XEXP (op, 0), QImode)) - return TRUE; - - break; - } - - return FALSE; -} - -/* Return true if the {smin,smax} operator can go inside of a exef0{f,t} || operation. */ - -int -minmax_parallel_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != 'c') - return FALSE; - - switch (GET_CODE (op)) - { - case SMIN: - case SMAX: - if (GET_MODE (op) == HImode - && gpr_operand (XEXP (op,0), mode) - && gpr_operand (XEXP (op, 1))) - return TRUE; - - if (GET_MODE (op) == SImode - && accum_operand (XEXP (op,0), mode) - && accum_operand (XEXP (op, 1))) - return TRUE; - - break; - } - - return FALSE; -} - - -/* Return true if a 32-bit integer constant can be loaded by two parallel - ldi constants. */ - -int -parallel_ldi (value) - HOST_WIDE_INT value; -{ - int low = SIGN_EXTEND_SHORT (value); - int high = SIGN_EXTEND_SHORT (value >> 16); - - return IN_RANGE_P (low, -8, 7) && IN_RANGE_P (high, -8, 7); -} - - -/* Return true if the two operands reference adjacement memory locations so that - a ld2w/st2w instruction can be used. The insn argument is the last insn of - the peephole, so that REG_DEAD notes are useful. */ - -int -adjacent_memory_operands (op1, op2, insn) - rtx op1; - rtx op2; - rtx insn; -{ - rtx addr1, addr2; - rtx const1, const2; - enum rtx_code code1, code2; - - if (GET_CODE (op1) != MEM || GET_MODE (op1) != HImode) - return FALSE; - - if (GET_CODE (op2) != MEM || GET_MODE (op2) != HImode) - return FALSE; - - addr1 = XEXP (op1, 0); - addr2 = XEXP (op2, 0); - code1 = GET_CODE (addr1); - code2 = GET_CODE (addr2); - if (((code1 == POST_INC && code2 == POST_INC)) - || ((code1 == POST_DEC && code2 == POST_DEC)) - || ((code1 == PRE_DEC && code2 == PRE_DEC))) - { - addr1 = XEXP (addr1, 0); - addr2 = XEXP (addr2, 0); - return (GET_CODE (addr1) == REG && GET_CODE (addr2) == REG - && REGNO (addr1) == REGNO (addr2)); - } - - else if ((code1 == POST_INC || code1 == POST_DEC || code1 == PRE_DEC) - && code2 != POST_INC && code2 != POST_DEC && code2 != PRE_DEC) - { - addr1 = XEXP (addr1, 0); - return (GET_CODE (addr1) == REG && code2 == REG - && REGNO (addr1) == REGNO (addr2) - && find_reg_note (insn, REG_DEAD, addr1)); - } - - else if (code1 == POST_INC || code1 == POST_DEC || code1 == PRE_DEC - || code2 == POST_INC || code2 == POST_DEC || code2 == PRE_DEC) - return FALSE; - - if (code1 == CONST) - addr1 = XEXP (addr1, 0); - - if (code2 == CONST) - code2 = GET_CODE (addr2); - - const1 = const0_rtx; - const2 = const0_rtx; - addr1 = eliminate_constant_term (addr1, &const1); - addr2 = eliminate_constant_term (addr2, &const2); - - if (!rtx_equal_p (addr1, addr2)) - return FALSE; - - if (GET_CODE (const1) == CONST_INT - && GET_CODE (const2) == CONST_INT - && INTVAL (const1) == INTVAL (const2) - 2) - return TRUE; - - return FALSE; -} - - -/* Expand a divmod operation */ - -void -d10v_expand_divmod (operands, unsigned_p) - rtx operands[]; - int unsigned_p; -{ - rtx ret = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, (unsigned_p) ? "__udivmodhi4" : "__divmodhi4"), - NULL_RTX, TRUE, SImode, 2, - operands[1], HImode, - operands[2], HImode); - - emit_move_insn (operands[0], gen_rtx (SUBREG, HImode, ret, 1)); - emit_move_insn (operands[3], gen_rtx (SUBREG, HImode, ret, 0)); -} - - -/* A C statement to initialize the variable parts of a trampoline. - ADDR is an RTX for the address of the trampoline; FNADDR is an RTX - for the address of the nested function; STATIC_CHAIN is an RTX for - the static chain value that should be passed to the function when - it is called. */ - -void -initialize_trampoline (addr, fnaddr, static_chain) - rtx addr; - rtx fnaddr; - rtx static_chain; -{ - rtx byte_addr = gen_reg_rtx (Pmode); - rtx reg1 = gen_reg_rtx (Pmode); - rtx reg2 = gen_reg_rtx (Pmode); - - emit_move_insn (byte_addr, addr); - - /* ldi.l r7, */ - emit_move_insn (gen_rtx (MEM, HImode, gen_rtx (POST_INC, HImode, byte_addr)), - GEN_INT (0xE000 | ((STATIC_CHAIN_REGNUM - GPR_FIRST) << 4))); - - emit_move_insn (gen_rtx (MEM, HImode, gen_rtx (POST_INC, HImode, byte_addr)), - static_chain); - - /* bra.l */ - emit_move_insn (gen_rtx (MEM, HImode, gen_rtx (POST_INC, HImode, byte_addr)), - GEN_INT (0xE400)); - - emit_move_insn (reg1, fnaddr); - emit_move_insn (reg2, addr); - emit_insn (gen_subhi3 (reg1, reg1, reg2)); - emit_move_insn (gen_rtx (MEM, HImode, byte_addr), reg1); - - error ("Trampolines currently don't work"); -} - - -/* Emit the appropriate comparison code for two operands. Return TRUE if - F0 contains a true value for the condition to be successful, FALSE if - not. - - Arguments: - - code Which comparison to emit - op{0,1} Operands - temp Temporary register that we can clobber (not used right now) - insn Whole insn - mode Mode of the operands - output_p Whether to actually emit code or just return true/false. */ - -int -emit_comparison (code, op0, op1, temp, insn, mode, output_p) - enum rtx_code code; - rtx op0, op1, temp, insn; - enum machine_mode mode; - int output_p; -{ - int ret = FALSE; - char *template = (char *)0; - int op1_int_p = CONSTANT_P (op1); - rtx xop[10]; - - /* Skip subregs that we find. */ - while (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - while (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - - xop[0] = op0; - xop[1] = op1; - xop[2] = temp; - - /* 16-bit comparisons */ - if (mode == HImode) - { - switch (code) - { - default: - break; - - case EQ: - template = (!op1_int_p) ? "cmpeq %0,%1" : "cmpeqi %0,%1"; - ret = TRUE; - break; - - case NE: - template = (!op1_int_p) ? "cmpeq %0,%1" : "cmpeqi %0,%1"; - ret = FALSE; - break; - - case LT: - template = (!op1_int_p) ? "cmp %0,%1" : "cmpi %0,%1"; - ret = TRUE; - break; - - case LE: - if (!op1_int_p) - { /* convert LE x,y to !GT x,y (ie, LT y,x) */ - template = "cmp %1,%0"; - ret = FALSE; - break; - } - else if (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 32767) - { - /* If some sum of a symbol/label and a constant ends up - as 32768, it would be the linker's task to fix that up. */ - if (output_p) - xop[3] = plus_constant_for_output (op1, 1); - - template = "cmpi %0,%3"; - ret = TRUE; - break; - } - else - { - template = "cmpeqi %0,%1"; - ret = TRUE; - break; - } - - case GT: - if (!op1_int_p) - { /* convert GT x,y to LT y,x */ - template = "cmp %1,%0"; - ret = TRUE; - break; - } - else if (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 32767) - { - if (output_p) - xop[3] = plus_constant_for_output (op1, 1); - - template = "cmpi %0,%3"; - ret = FALSE; - break; - } - else - { - template = "cmpeq %0,%0"; - ret = FALSE; - break; - } - - case GE: - template = (!op1_int_p) ? "cmp %0,%1" : "cmpi %0,%1"; - ret = FALSE; - break; - - case LTU: - template = (!op1_int_p) ? "cmpu %0,%1" : "cmpui %0,%1"; - ret = TRUE; - break; - - case LEU: - if (!op1_int_p) - { /* convert LEU x,y to !GTU x,y (ie, LTU y,x) */ - template = "cmpu %1,%0"; - ret = FALSE; - break; - } - else if (GET_CODE (op1) != CONST_INT || ~INTVAL (op1) & 65535) - { - if (output_p) - xop[3] = plus_constant_for_output (op1, 1); - - template = "cmpui %0,%3"; - ret = TRUE; - break; - } - else - { - template = "cmpeq %0,%0"; - ret = TRUE; - break; - } - - case GTU: - if (!op1_int_p) - { /* convert GTU x,y to LTU y,x */ - template = "cmpu %1,%0"; - ret = TRUE; - break; - } - else if (GET_CODE (op1) != CONST_INT || ~INTVAL (op1) & 65535) - { /* convert GTU x,y to !LTU x,y+1 */ - if (output_p) - xop[3] = plus_constant_for_output (op1, 1); - - template = "cmpui %0,%3"; - ret = FALSE; - break; - } - else - { - /* Convert GTU x,65535 to !EQ x,x */ - template = "cmpeq %0,%0"; - ret = FALSE; - break; - } - - case GEU: - template = (!op1_int_p) ? "cmpu %0,%1" : "cmpui %0,%1"; - ret = FALSE; - break; - } - } - - /* 32-bit comparisons in the accumulators. */ - else if (mode == SImode - && GET_CODE (op0) == REG && ACCUM_P (REGNO (op0)) - && GET_CODE (op1) == REG && ACCUM_P (REGNO (op1))) - { - switch (code) - { - default: - break; - - case EQ: - template = "cmpeq %0,%1"; - ret = TRUE; - break; - - case NE: - template = "cmpeq %0,%1"; - ret = FALSE; - break; - - case LT: - template = "cmp %0,%1"; - ret = TRUE; - break; - - case LE: - /* convert LE x,y to !GT x,y (ie, LT y,x) */ - template = "cmp %1,%0"; - ret = FALSE; - break; - - case GT: - /* convert GT x,y to LT y,x */ - template = "cmp %1,%0"; - ret = TRUE; - break; - - case GE: - template = "cmp %0,%1"; - ret = FALSE; - break; - } - } - - /* 32-bit comparisons in the general purpose registers. */ - else if (mode == SImode - && GET_CODE (op0) == REG && GPR_OR_PSEUDO_P (REGNO (op0)) - && GET_CODE (op1) == REG && GPR_OR_PSEUDO_P (REGNO (op1))) - { - switch (code) - { - default: - break; - - case EQ: - template = "cmpeq %U0,%U1\n\texef0t || cmpeq %L0,%L1"; - ret = TRUE; - break; - - case NE: - template = "cmpeq %U0,%U1\n\texef0t || cmpeq %L0,%L1"; - ret = FALSE; - break; - - case LT: - template = "cmpeq %U0,%U1\n\tcmp %U0,%U1\n\texef1t || cmpu %L0,%L1"; - ret = TRUE; - break; - - case LE: - /* convert LE x,y to !GT x,y (ie, LT y,x) */ - template = "cmpeq %U1,%U0\n\tcmp %U1,%U0\n\texef1t || cmpu %L1,%L0"; - ret = FALSE; - break; - - case GT: - /* convert GT x,y to LT y,x */ - template = "cmpeq %U1,%U0\n\tcmp %U1,%U0\n\texef1t || cmpu %L1,%L0"; - ret = TRUE; - break; - - case GE: - /* convert GE x,y to !LT x,y */ - template = "cmpeq %U0,%U1\n\tcmp %U0,%U1\n\texef1t || cmpu %L0,%L1"; - ret = FALSE; - break; - - case LTU: - template = "cmpeq %U0,%U1\n\tcmpu %U0,%U1\n\texef1t || cmpu %L0,%L1"; - ret = TRUE; - break; - - case LEU: - /* convert LEU x,y to !GTU x,y (ie, LTU y,x) */ - template = "cmpeq %U1,%U0\n\tcmpu %U1,%U0\n\texef1t || cmpu %L1,%L0"; - ret = FALSE; - break; - - case GTU: - /* convert GTU x,y to LTU y,x */ - template = "cmpeq %U1,%U0\n\tcmpu %U1,%U0\n\texef1t || cmpu %L1,%L0"; - ret = TRUE; - break; - - case GEU: - /* convert GEU x,y to !LTU x,y */ - template = "cmpeq %U0,%U1\n\tcmpu %U0,%U1\n\texef1t || cmpu %L0,%L1"; - ret = FALSE; - break; - } - } - - /* 32-bit comparison against 0 in the general purpose registers. */ - else if (mode == SImode - && GET_CODE (op0) == REG && GPR_OR_PSEUDO_P (REGNO (op0)) - && GET_CODE (op1) == CONST_INT && INTVAL (op1) == 0) - { - switch (code) - { - default: - break; - - case EQ: - case LEU: /* convert LEU x,0 to EQ x,0 */ - template = "cmpeqi %U0,0\n\texef0t || cmpeqi %L0,0"; - ret = TRUE; - break; - - case NE: - case GTU: /* convert GTU x,0 to NE x,0 */ - template = "cmpeqi %U0,0\n\texef0t || cmpeqi %L0,0"; - ret = FALSE; - break; - - case LT: - template = "cmpi %U0,0"; - ret = TRUE; - break; - - case LE: - template = "cmpeqi %U0,0\n\tcmpi %U0,0\n\texef1t || cmpeqi %L0,0"; - ret = TRUE; - break; - - case GT: - /* convert GT x,0 to !LE x,0 */ - template = "cmpeqi %U0,0\n\tcmpi %U0,0\n\texef1t || cmpeqi %L0,0"; - ret = FALSE; - break; - - case GE: - /* convert GE x,0 to !LT x,0 */ - template = "cmpi %U0,0\n"; - ret = FALSE; - break; - - case LTU: - /* LTU x,0 is always false */ - template = "cmpeq %U0,%U0"; - ret = FALSE; - break; - - case GEU: - /* GEU x,0 is always true */ - template = "cmpeq %U0,%U0"; - ret = TRUE; - break; - } - } - - /* 32-bit comparison against a constant with -8..7 in the lower 16 bits */ - else if (mode == SImode - && GET_CODE (op0) == REG && GPR_OR_PSEUDO_P (REGNO (op0)) - && GET_CODE (op1) == CONST_INT - && IN_RANGE_P (SIGN_EXTEND_SHORT (INTVAL (op1)), -8, 7)) - { - switch (code) - { - default: - break; - - case EQ: - template = "cmpeqi %U0,%U1\n\texef0t || cmpeqi %L0,%L1"; - ret = TRUE; - break; - - case NE: - template = "cmpeqi %U0,%U1\n\texef0t || cmpeqi %L0,%L1"; - ret = FALSE; - break; - } - } - - /* Abort on unhandled cases. */ - if (!template) - { - if (!insn) - insn = gen_rtx (SET, VOIDmode, - gen_rtx (REG, CCmode, F0_REGNUM), - gen_rtx (code, CCmode, op0, op1)); - - fatal_insn ("emit_comparison:", insn); - return TRUE; - } - - /* If we are outputing, do it now. */ - if (output_p) - output_asm_insn (template, xop); - - return ret; -} - - -/* Returns a mode from class `MODE_CC' to be used when comparison - operation code OP is applied to rtx X and Y. For example, on the - Sparc, `SELECT_CC_MODE' is defined as (see *note Jump Patterns::. - for a description of the reason for this definition) - - #define SELECT_CC_MODE(OP,X,Y) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ - : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ - || GET_CODE (X) == NEG) \ - ? CC_NOOVmode : CCmode)) - - You need not define this macro if `EXTRA_CC_MODES' is not defined. */ -int -select_cc_mode (op, x, y) - enum rtx_code op; - rtx x; - rtx y; -{ - int ret = emit_comparison (op, x, y, NULL_RTX, NULL_RTX, GET_MODE (x), FALSE); - - fprintf (stderr, "select_cc_mode: emit_comparison returned %d\n", ret); - debug_rtx (x); - debug_rtx (y); - - return (ret ? (int)CCmode : (int)CC_REVmode); -} - - -/* Emit the code to set F0 based on comparing op0 and op1. Use CCmode for - comparisons that set F0 to 1 if the comparison is true, and CC_REVmode - for comparisons that set F0 to 0 if the comparison is true. */ - -Rtx -expand_comparison (code, op0, op1, reg_p) - enum rtx_code code; - rtx op0; - rtx op1; - rtx *reg_p; -{ - rtx f0, seq; - enum machine_mode mode; - - start_sequence (); - if (GET_MODE (op0) == DImode) - { - int unsigned_p = (code == GTU || code == GEU || code == LTU || code == LEU); - - if (op1 == CONST0_RTX (DImode)) - op0 = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, (unsigned_p) ? "__ucmpdi0" : "__cmpdi0"), - NULL_RTX, TRUE, HImode, 1, op0, DImode); - else - op0 = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode, (unsigned_p) ? "__ucmpdi" : "__cmpdi"), - NULL_RTX, TRUE, HImode, 2, - op0, DImode, - op1, DImode); - - op1 = const1_rtx; - } - - mode = (emit_comparison (code, op0, op1, NULL_RTX, NULL_RTX, GET_MODE (op0), FALSE) ? CCmode : CC_REVmode); - f0 = gen_rtx (REG, mode, F0_REGNUM); - - emit_insn (gen_rtx (SET, VOIDmode, f0, gen_rtx (code, mode, op0, op1))); - seq = gen_sequence (); - end_sequence (); - - *reg_p = f0; - return seq; -} - - -/* Emit the instructions to move 1 word. */ - -char * -emit_move_word (op0, op1, insn) - rtx op0; - rtx op1; - rtx insn; -{ - char *ret = ""; - int shift; - - if (REG_P (op0) && REG_P (op1)) - { - int reg0 = REGNO (op0); - int reg1 = REGNO (op1); - - if (GPR_P (reg0) && GPR_P (reg1)) - ret = "mv %0,%1"; - - else if (GPR_P (reg0) && CR_P (reg1)) - ret = "mvfc %0,%1"; - - else if (CR_P (reg0) && GPR_P (reg1)) - ret = "mvtc %1,%0"; - - else if (GPR_P (reg0) && reg1 == F0_REGNUM) - ret = "setf0t %0"; - - else - fatal_insn ("emit_move_word:", insn); - } - - else if (REG_P (op0) && GPR_P (REGNO (op0)) && GET_CODE (op1) == MEM) - ret = "ld %0,%M1"; - - else if (GET_CODE (op0) == MEM && REG_P (op1) && GPR_P (REGNO (op1))) - ret = "st %1,%M0"; - - else if (GET_CODE (op0) == MEM && GET_CODE (op1) == CONST_INT && INTVAL (op1) == 0) - ret = "st %.,%M0"; - - /* XXX: We should do LABEL_REF's that are not part switch statements with the - @word modifier, but if we do, that breaks switch statements which need to - index into the array of labels. Using casesi is clumsy because it converts - the switch value to SI before the call. */ - else if (REG_P (op0) && GPR_P (REGNO (op0)) - && GET_CODE (op1) == SYMBOL_REF && SYMBOL_REF_FLAG (op1)) - ret = "ldi %0,%1@word"; - - else if (REG_P (op0) && GPR_P (REGNO (op0)) - && GET_CODE (op1) == CONST_INT - && ldi_shift_operand (op1, HImode)) - ret = "ldi %0,%s1\n\tslli %0,%S1"; - - else if (REG_P (op0) && GPR_P (REGNO (op0)) - && (GET_CODE (op1) == CONST_INT - || GET_CODE (op1) == SYMBOL_REF - || GET_CODE (op1) == LABEL_REF - || GET_CODE (op1) == CONST)) - ret = "ldi %0,%1"; - - else - fatal_insn ("emit_move_word:", insn); - - return ret; -} - - - -/* Emit the instructions to move 2 words. */ - -char * -emit_move_2words (op0, op1, insn) - rtx op0; - rtx op1; - rtx insn; -{ - char *ret = ""; - - if (REG_P (op0) && REG_P (op1)) - { - int reg0 = REGNO (op0); - int reg1 = REGNO (op1); - - if (GPR_P (reg0) && GPR_P (reg1)) - ret = "mv2w %0,%1"; - - else if (GPR_P (reg0) && ACCUM_P (reg1)) - ret = "mv2wfac %0,%1"; - - else if (ACCUM_P (reg0) && GPR_P (reg1)) - ret = "mv2wtac %1,%0"; - - else - fatal_insn ("emit_move_2words:", insn); - } - - else if (REG_P (op0) && GPR_P (REGNO (op0)) && GET_CODE (op1) == MEM) - ret = "ld2w %0,%M1"; - - else if (GET_CODE (op0) == MEM && REG_P (op1) && GPR_P (REGNO (op1))) - ret = "st2w %1,%M0"; - - else if (REG_P (op0) && GPR_P (REGNO (op0)) - && (GET_CODE (op1) == CONST_INT || GET_CODE (op1) == CONST_DOUBLE)) - ret = "#"; - - else if (REG_P (op0) && ACCUM_P (REGNO (op0)) && GET_CODE (op1) == CONST_INT && INTVAL (op1) == 0) - ret = "clrac %0"; - - else - fatal_insn ("emit_move_2words:", insn); - - return ret; -} - - - -/* Emit the instructions to move 4 words. */ - -char * -emit_move_4words (op0, op1, tmp_si, tmp_hi, insn) - rtx op0; - rtx op1; - rtx tmp_si; - rtx tmp_hi; - rtx insn; -{ - char *ret = ""; - int gpr0_p = (REG_P (op0) && GPR_P (REGNO (op0))); - int gpr1_p = (REG_P (op1) && GPR_P (REGNO (op1))); - int mem0_p = (GET_CODE (op0) == MEM); - int mem1_p = (GET_CODE (op1) == MEM); - int const1_p = (GET_CODE (op1) == CONST_INT || GET_CODE (op1) == CONST_DOUBLE); - - /* Check for overlap */ - if (gpr0_p && refers_to_regno_p (REGNO (op0), REGNO (op0)+2, op1, (rtx *)0)) - { - if (TARGET_DEBUG_MOVE4) - { - fprintf (stderr, "\n%s: overlap found in emit_move_4words\n", - IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); - debug_rtx (insn); - fprintf (stderr, "----------\n"); - } - - if (gpr1_p) - { - if (REGNO (op0) == REGNO (op1) + 2) - ret = "mv2w %C0,%C1\n\tmv2w %A0,%A1"; - else - ret = "mv2w %A0,%A1\n\tmv2w %C0,%C1"; - } - - else if (mem1_p) - ret = "ld2w %C0,%C1\n\tld2w %A0,%A1"; - - else - fatal_insn ("move 4 words overlap", insn); - } - - else if (gpr0_p && gpr1_p) - { - if (REGNO (op0) == REGNO (op1) + 2) - ret = "mv2w %C0,%C1\n\tmv2w %A0,%A1"; - else - ret = "mv2w %A0,%A1\n\tmv2w %C0,%C1"; - } - - else if (gpr0_p && mem1_p) - { - /* If we use post increment/post decrement, it allows the second instruction - to also be a 16-bit instruction */ - rtx addr = XEXP (op1, 0); - - if (GET_CODE (addr) == REG && REGNO (addr) != STACK_POINTER_REGNUM - && !IN_RANGE_P (REGNO (addr), REGNO (op0), REGNO (op0)+3)) - ret = "ld2w %A0,@%1+\n\tld2w %C0,@%1-"; - - else if (GET_CODE (addr) == REG && REGNO (addr) != STACK_POINTER_REGNUM - && IN_RANGE_P (REGNO (addr), REGNO (op0)+2, REGNO (op0)+3)) - ret = "ld2w %A0,@%1+\n\tld2w %C0,@%1"; - - else - ret = "ld2w %A0,%A1\n\tld2w %C0,%C1"; - } - - else if (mem0_p && gpr1_p) - { - /* If we use post increment/post decrement, it allows the second instruction - to also be a 16-bit instruction */ - rtx addr = XEXP (op0, 0); - - if (GET_CODE (addr) == REG && REGNO (addr) != STACK_POINTER_REGNUM - && !IN_RANGE_P (REGNO (addr), REGNO (op1), REGNO (op1)+3)) - ret = "st2w %A1,@%0+\n\tst2w %C1,@%0-"; - else - ret = "st2w %A1,%A0\n\tst2w %C1,%C0"; - } - - else if (mem0_p && mem1_p) - { - if (TARGET_DEBUG_MOVE4) - { - fprintf (stderr, "\n%s: memory to memory move in emit_move_4wordsn", - IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); - - debug_rtx (insn); - fprintf (stderr, "----------\n"); - } - - /* Check for the scratch space overlapping registers used for pointers. */ - if (GET_CODE (tmp_si) == REG && GET_MODE (tmp_si) == SImode) - { - int reg = REGNO (tmp_si); - - if (refers_to_regno_p (reg, reg+2, op0, (rtx *)0) - || refers_to_regno_p (reg, reg+2, op1, (rtx *)0)) - { - if (!refers_to_regno_p (reg, reg+1, op0, (rtx *)0) - && !refers_to_regno_p (reg, reg+1, op1, (rtx *)0)) - { - tmp_si = NULL_RTX; - tmp_hi = gen_rtx (REG, HImode, reg); - } - else if (!refers_to_regno_p (reg+1, reg+2, op0, (rtx *)0) - && !refers_to_regno_p (reg+1, reg+2, op1, (rtx *)0)) - { - tmp_si = NULL_RTX; - tmp_hi = gen_rtx (REG, HImode, reg+1); - } - else - fatal_insn ("emit_move_4words:", insn); - } - } - else if (GET_CODE (tmp_hi) == REG && GET_MODE (tmp_hi) == HImode) - { - if (refers_to_regno_p (REGNO (tmp_hi), REGNO (tmp_hi)+1, op0, (rtx *)0) - || refers_to_regno_p (REGNO (tmp_hi), REGNO (tmp_hi)+1, op1, (rtx *)0)) - fatal_insn ("emit_move_4words:", insn); - } - - if (tmp_si && GET_CODE (tmp_si) == REG && GET_MODE (tmp_si) == SImode) - ret = "ld2w %2,%A1\n\tst2w %2,%A0\n\tld2w %2,%C1\n\tst2w %2,%C0"; - - else if (tmp_hi && GET_CODE (tmp_hi) == REG && GET_MODE (tmp_hi) == HImode) - ret = "ld %3,%A1\nst %3,%A0\nld %3,%B1\nst %3,%B0\nld %3,%C1\nst %3,%C0\nld %3,%D1\nst %3,%D0\n"; - - else - fatal_insn ("emit_move_4words:", insn); - } - - else if (gpr0_p - && (GET_CODE (op1) == CONST_INT || GET_CODE (op1) == CONST_DOUBLE)) - ret = "ldi %A0,%A1\n\tldi %B0,%B1\n\tldi %C0,%C1\n\tldi %D0,%D1"; - - else if (mem0_p - && ((GET_CODE (op1) == CONST_INT && INTVAL (op1) == 0) - || (GET_CODE (op1) == CONST_DOUBLE - && CONST_DOUBLE_LOW (op1) == 0 - && CONST_DOUBLE_HIGH (op1) == 0))) - ret = "st %.,%A0\n\tst %.,%B0\n\tst %.,%C0\n\tst %.,%D0"; - - else if (mem0_p && const1_p && GET_CODE (tmp_si) == REG && GET_MODE (tmp_si) == SImode) - { - int part0, part1, part2, part3; - - if (GET_CODE (op1) == CONST_INT && INTVAL (op1) < 0) - { - HOST_WIDE_INT value = INTVAL (op1); - part0 = 0xffff; - part1 = 0xffff; - part2 = (value >> 16) & 0xffff; - part3 = value & 0xffff; - } - - else if (GET_CODE (op1) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (op1); - part0 = 0; - part1 = 0; - part2 = (value >> 16) & 0xffff; - part3 = value & 0xffff; - } - - else - { - part0 = (CONST_DOUBLE_HIGH (op1) >> 16) & 0xffff; - part1 = CONST_DOUBLE_HIGH (op1) & 0xffff; - part2 = (CONST_DOUBLE_LOW (op1) >> 16) & 0xffff; - part3 = CONST_DOUBLE_LOW (op1) & 0xffff; - } - - if (part0 == part2 && part1 == part3) - ret = "ldi %U2,%A1\n\tldi %L2,%B1\n\tst2w %2,%A0\n\tst2w %2,%C0"; - - else if (part0 == part2) - ret = "ldi %U2,%A1\n\tldi %L2,%B1\n\tst2w %2,%A0\n\tldi %L2,%D1\n\tst2w %2,%C0"; - - else if (part1 == part3) - ret = "ldi %U2,%A1\n\tldi %L2,%B1\n\tst2w %2,%A0\n\tldi %U2,%C1\n\tst2w %2,%C0"; - - else - ret = "ldi %U2,%A1\n\tldi %L2,%B1\n\tst2w %2,%A0\n\tldi %U2,%C1\n\tldi %L2,%D1\n\tst2w %2,%C0"; - } - - else - fatal_insn ("emit_move_4words:", insn); - - return ret; -} - - - -/* Emit code to do add of multiword values */ - -char * -emit_add (operands, insn) - rtx operands[], insn; -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - enum machine_mode mode = GET_MODE (op0); - int regno0 = (GET_CODE (op0) == REG) ? REGNO (op0) : -1; - int regno1 = (GET_CODE (op1) == REG) ? REGNO (op1) : -1; - int regno2 = (GET_CODE (op2) == REG) ? REGNO (op2) : -1; - HOST_WIDE_INT value; - - if (mode == SImode) - { - if (GET_CODE (op2) != CONST_INT) - { - if (GPR_P (regno0) && regno0 == regno1 && GPR_P (regno2)) - return "add2w %0,%2"; - - else if (ACCUM_P (regno0) && regno0 == regno1 && (GPR_P (regno2) || ACCUM_P (regno2))) - return "add %0,%2"; - - else if (GPR_P (regno0) && (GPR_P (regno1) || ACCUM_P (regno1)) && ACCUM_P (regno2) && TARGET_ADDAC3) - return "addac3 %0,%1,%2"; - } - - else if (regno0 != regno1) - return "ldi %U0,%U2\n\tldi %L0,%L2\n\tadd2w %0,%1"; - - else if (INTVAL (op2) < 0) - fatal_insn ("emit_add, negative constant", insn); - - else if (GPR_P (regno0) && GPR_P (regno1)) - { - value = INTVAL (op2); - if (IN_RANGE_P (value, 1, 16) && regno0 == regno1) - return "addi %L0,%2\n\tcpfg f0,c\n\texef0t || addi %U0,1"; - - else if (regno0 == regno1) - return "add3 %L0,%L0,%2\n\tcpfg f0,c\n\texef0t || addi %U0,1"; - - else - return "add3 %L0,%L1,%2\n\tcpfg f0,c || mv %U0,%U1\n\texef0t || addi %U0,1"; - } - } - - else if (mode == DImode && regno0 == regno1 && GPR_P (regno0)) - { - int num_carries = 0; - if (GPR_P (regno2)) - { - output_asm_insn ("add2w %A0,%A2", operands); - output_asm_insn ("add2w %C0,%C2", operands); - num_carries = 2; - } - - else if (GET_CODE (op2) == CONST_INT && INTVAL (op2) >= 0) - { - num_carries = 3; - value = INTVAL (op2); - if (IN_RANGE_P (value, 1, 16) && regno0 == regno1) - output_asm_insn ("addi %D0,%2", operands); - - else if (IN_RANGE_P (value, 1, 16) && TARGET_SMALL_INSNS && optimize) - output_asm_insn ("mv %D0,%D1\n\taddi %D0,%2", operands); - - else - output_asm_insn ("add3 %D0,%D1,%2", operands); - } - - else if (GET_CODE (op2) == CONST_DOUBLE - && CONST_DOUBLE_HIGH (op2) == 0 - && CONST_DOUBLE_LOW (op2) >= 0) - { - num_carries = 3; - value = CONST_DOUBLE_LOW (op2); - if (IN_RANGE_P (value, 1, 16) && regno0 == regno1) - output_asm_insn ("addi %D0,%2", operands); - - else if (IN_RANGE_P (value, 1, 16) && TARGET_SMALL_INSNS && optimize) - output_asm_insn ("mv %D0,%D1\n\taddi %D0,%2", operands); - - else - output_asm_insn ("add3 %D0,%D1,%2", operands); - } - - if (num_carries) - { - output_asm_insn ("cpfg f0,c", operands); - - if (num_carries == 3) - { - output_asm_insn ("exef0t || addi %C0,1", operands); - output_asm_insn ("cpfg f0,c || exef0t", operands); - } - - output_asm_insn ("exef0t || addi %B0,1", operands); - output_asm_insn ("cpfg f0,c || exef0t", operands); - output_asm_insn ("exef0t || addi %A0,1", operands); - return ""; - } - } - - fatal_insn ("emit_add:", insn); -} - - -/* Emit code to do subtract of multiword values */ - -char * -emit_subtract (operands, insn) - rtx operands[], insn; -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - enum machine_mode mode = GET_MODE (op0); - int regno0 = (GET_CODE (op0) == REG) ? REGNO (op0) : -1; - int regno1 = (GET_CODE (op1) == REG) ? REGNO (op1) : -1; - int regno2 = (GET_CODE (op2) == REG) ? REGNO (op2) : -1; - HOST_WIDE_INT value; - - if (mode == SImode) - { - if (GPR_P (regno0) && regno0 == regno1 && GPR_P (regno2)) - return "sub2w %0,%2"; - - else if (ACCUM_P (regno0) && regno0 == regno1 && (GPR_P (regno2) || ACCUM_P (regno2))) - return "sub %0,%2"; - - else if (GPR_P (regno0) && (GPR_P (regno1) || ACCUM_P (regno1)) && ACCUM_P (regno2) && TARGET_ADDAC3) - return "subac3 %0,%1,%2"; - } - - else if (mode == DImode && GPR_P (regno0) && regno0 == regno1 && GPR_P (regno2)) - return "sub2w %A0,%A2\n\tsub2w %C0,%C2\n\tcpfg f0,c\n\texef0f || subi %B0,1\n\tcpfg f0,c || exef0f\n\texef0f || subi %A0,1"; - - fatal_insn ("emit_subtract:", insn); -} - - -/* Output a conditional move instruction - operands[0] is the destination - operands[1] is the NE test - operands[2] is f0 - operands[3] is the value to move if the test was true - operands[4] is the value to move if the test was false */ - -char * -emit_cond_move (operands, insn) - rtx operands[]; - rtx insn; -{ - char *load = (char *)0; - char *store = (char *)0; - char *move_false = (char *)0; - char *move_true = (char *)0; - rtx dest = operands[0]; - rtx xop[10]; - rtx op_true; - rtx op_false; - enum machine_mode mode = GET_MODE (dest); - char buffer[80]; - - if (GET_MODE (operands[1]) == CC_REVmode) - { - op_true = operands[4]; - op_false = operands[3]; - } - else - { - op_true = operands[3]; - op_false = operands[4]; - } - - switch (mode) - { - case QImode: - load = "ldub"; - store = "stb"; - move_false = "mvf0f %0,%1"; - move_true = "mvf0t %0,%1"; - break; - - case HImode: - load = "ld"; - store = "st"; - move_false = "mvf0f %0,%1"; - move_true = "mvf0t %0,%1"; - break; - - case SImode: - case SFmode: - load = "ld2w"; - store = "st2w"; - move_false = "exef0f || mv2w %0,%1"; - move_true = "exef0t || mv2w %0,%1"; - break; - - default: - fatal_insn ("emit_cond_move", insn); - } - - xop[0] = dest; - if (GET_CODE (dest) == REG - && GET_CODE (op_false) == CONST_INT - && !refers_to_regno_p (REGNO (dest), REGNO (dest)+1, op_true, (rtx *)0)) - { - xop[1] = op_false; - output_asm_insn ("ldi %0,%1", xop); - - xop[1] = op_true; - switch (GET_CODE (op_true)) - { - case REG: - output_asm_insn (move_true, xop); - break; - - case MEM: - sprintf (buffer, "%s %%0,%%M1 || exef0t", load); - output_asm_insn (buffer, xop); - break; - - case CONST_INT: - output_asm_insn ("exef0t || ldi %0,%1", xop); - break; - - default: - fatal_insn ("emit_cond_move", insn); - } - } - - else if (GET_CODE (dest) == REG - && GET_CODE (op_true) == CONST_INT - && !refers_to_regno_p (REGNO (dest), REGNO (dest)+1, op_false, (rtx *)0)) - { - xop[1] = op_true; - output_asm_insn ("ldi %0,%1", xop); - - xop[1] = op_false; - switch (GET_CODE (op_false)) - { - case REG: - output_asm_insn (move_false, xop); - break; - - case MEM: - sprintf (buffer, "%s %%0,%%M1 || exef0f", load); - output_asm_insn (buffer, xop); - break; - - default: - fatal_insn ("emit_cond_move", insn); - } - } - - else if (GET_CODE (dest) == REG) - { - int dest_reg = REGNO (dest); - - /* Move value into register for false condition */ - xop[1] = op_false; - switch (GET_CODE (op_false)) - { - case REG: - if (REGNO (op_false) != dest_reg) - output_asm_insn (move_false, xop); - break; - - case MEM: - sprintf (buffer, "%s %%0,%%M1 || exef0f", load); - output_asm_insn (buffer, xop); - break; - - case CONST_INT: - output_asm_insn ("exef0f || ldi %0,%1", xop); - break; - - default: - fatal_insn ("emit_cond_move", insn); - } - - /* Move value into register for true condition */ - xop[1] = op_true; - switch (GET_CODE (op_true)) - { - case REG: - if (REGNO (op_true) != dest_reg) - output_asm_insn (move_true, xop); - break; - - case MEM: - sprintf (buffer, "%s %%0,%%M1 || exef0t", load); - output_asm_insn (buffer, xop); - break; - - case CONST_INT: - output_asm_insn ("exef0t || ldi %0,%1", xop); - break; - - default: - fatal_insn ("emit_cond_move", insn); - } - } - - else if (GET_CODE (dest) == MEM - && (GET_CODE (op_false) == REG - || (GET_CODE (op_false) == CONST_INT - && INTVAL (op_false) == 0 - && GET_MODE_SIZE (mode) <= 2)) - && (GET_CODE (op_true) == REG - || (GET_CODE (op_true) == CONST_INT - && INTVAL (op_true) == 0 - && GET_MODE_SIZE (mode) <= 2))) - { - xop[1] = op_false; - sprintf (buffer, "%s %s,%%M0 || exef0f", store, (GET_CODE (op_false) == CONST_INT ? "%." : "%1")); - output_asm_insn (buffer, xop); - - xop[1] = op_true; - sprintf (buffer, "%s %s,%%M0 || exef0t", store, (GET_CODE (op_true) == CONST_INT ? "%." : "%1")); - output_asm_insn (buffer, xop); - } - - else - fatal_insn ("emit_cond_move", insn); - - return ""; -} - - -/* Split a multiword logical operation into its component parts */ - -Rtx -d10v_split_logical_op (operands, code) - rtx operands[]; - enum rtx_code code; -{ - rtx ret; - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - rtx split_op0; - rtx split_op1; - rtx split_op2; - int split_values[4]; - int i, max_words; - int off0 = 0, off1 = 0, off2 = 0; - enum machine_mode mode = GET_MODE (op0); - rtx insn; - - if (GET_CODE (op0) == SUBREG) - { - off0 = SUBREG_WORD (op0); - op0 = SUBREG_REG (op0); - } - - if (GET_CODE (op0) != REG) - goto fail; - - if (GET_CODE (op1) == SUBREG) - { - off1 = SUBREG_WORD (op1); - op1 = SUBREG_REG (op1); - } - - if (GET_CODE (op1) != REG) - goto fail; - - if (code != NOT) - { - if (GET_CODE (op2) == SUBREG) - { - off2 = SUBREG_WORD (op2); - op2 = SUBREG_REG (op2); - } - - if (GET_CODE (op2) == CONST_INT || GET_CODE (op2) == CONST_DOUBLE) - { - if (mode == DImode) - d10v_split_constant64 (op2, split_values); - - else if (mode == SImode) - d10v_split_constant32 (op2, split_values); - - else - goto fail; - } - else if (GET_CODE (op2) != REG) - goto fail; - } - else - op2 = NULL_RTX; - - max_words = GET_MODE_SIZE (mode) / UNITS_PER_WORD; - start_sequence (); - - for (i = 0; i < max_words; i++) - { - if (!reload_completed) - { - split_op0 = gen_rtx (SUBREG, HImode, op0, i+off0); - split_op1 = gen_rtx (SUBREG, HImode, op1, i+off1); - } - else - { - split_op0 = gen_rtx (REG, HImode, REGNO (op0) + i+off0); - split_op1 = gen_rtx (REG, HImode, REGNO (op1) + i+off1); - } - - if (code == NOT) - { - emit_insn (gen_rtx (SET, VOIDmode, - split_op0, - gen_rtx (NOT, HImode, split_op1))); - continue; - } - - if (GET_CODE (op2) != REG) - { - /* Optimize = operations to skip NOPs */ - if ((REGNO (op0) + i + off0) == (REGNO (op1) + i + off1)) - { - if (split_values[i] == 0 && code == IOR) - continue; - - if ((split_values[i] & 0xffff) == 0xffff && code == AND) - continue; - } - - /* Optimize = that turn into moves */ - else if ((split_values[i] == 0 && code == IOR) - || ((split_values[i] & 0xffff) == 0xffff && code == AND)) - { - emit_insn (gen_rtx (SET, VOIDmode, split_op0, split_op1)); - continue; - } - - split_op2 = GEN_INT (split_values[i]); - } - else - split_op2 = gen_rtx (SUBREG, HImode, op2, i+off2); - - emit_insn (gen_rtx (SET, VOIDmode, - split_op0, - gen_rtx (code, HImode, split_op1, split_op2))); - } - - ret = gen_sequence (); - end_sequence (); - return ret; - -fail: - if (code != NOT) - insn = gen_rtx (SET, VOIDmode, - operands[0], - gen_rtx (code, mode, operands[1], operands[2])); - else - insn = gen_rtx (SET, VOIDmode, - operands[0], - gen_rtx (NOT, mode, operands[1])); - - fatal_insn ("bad insn to d10v_split_logical_op", insn); - return NULL_RTX; -} - - -/* Split a 32-bit constant into 2 16-bit values. */ - -static void -d10v_split_constant32 (x, values) - rtx x; - int values[]; -{ - enum rtx_code code = GET_CODE (x); - HOST_WIDE_INT v; - - if (code == CONST_INT) - { - v = INTVAL (x); - values[0] = SIGN_EXTEND_SHORT (v >> 16); - values[1] = SIGN_EXTEND_SHORT (v); - } - - else if (code == CONST_DOUBLE && GET_MODE (x) == SFmode) - { - REAL_VALUE_TYPE rv; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, v); - values[0] = SIGN_EXTEND_SHORT (v >> 16); - values[1] = SIGN_EXTEND_SHORT (v); - } - - else - fatal_insn ("Bad rtx passed to d10v_split_constant32:", x); -} - - -/* Split a 64-bit constant into 4 16-bit values. */ - -static void -d10v_split_constant64 (x, values) - rtx x; - int values[]; -{ - enum rtx_code code = GET_CODE (x); - HOST_WIDE_INT v; - - if (code == CONST_INT) - { - v = INTVAL (x); - if (v < 0) - values[0] = values[1] = -1; - else - values[0] = values[1] = 0; - - values[2] = SIGN_EXTEND_SHORT (v >> 16); - values[3] = SIGN_EXTEND_SHORT (v); - } - - else if (code == CONST_DOUBLE && GET_MODE (x) == DFmode) - { - long t[2]; - REAL_VALUE_TYPE rv; - - /* d10v is big endian, so the high word is first */ - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_DOUBLE (rv, t); - values[0] = SIGN_EXTEND_SHORT (t[0] >> 16); - values[1] = SIGN_EXTEND_SHORT (t[0]); - values[2] = SIGN_EXTEND_SHORT (t[1] >> 16); - values[3] = SIGN_EXTEND_SHORT (t[1]); - } - - else if (code == CONST_DOUBLE - && (GET_MODE (x) == DImode || GET_MODE (x) == VOIDmode)) - { - v = CONST_DOUBLE_HIGH (x); - values[0] = SIGN_EXTEND_SHORT (v >> 16); - values[1] = SIGN_EXTEND_SHORT (v); - - v = CONST_DOUBLE_LOW (x); - values[2] = SIGN_EXTEND_SHORT (v >> 16); - values[3] = SIGN_EXTEND_SHORT (v); - } - - else - fatal_insn ("Bad rtx passed to d10v_split_constant64:", x); -} - - -/* Print an integer constant expression in assembler syntax. - Note, for the d10v, we need to explicitly truncate integer - constants to 16 bits. */ - -void -d10v_output_addr_const (file, x) - FILE *file; - rtx x; -{ - char buf[256]; - - restart: - switch (GET_CODE (x)) - { - default: - output_addr_const (file, x); - break; - - case SYMBOL_REF: - /* We could use parentheses only for symbols whose names conflict - with the register names. But it would make the compiler - slower. */ - fputc ('(', file); - assemble_name (file, XSTR (x, 0)); - fputc (')', file); - break; - - case LABEL_REF: - ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); - assemble_name (file, buf); - break; - - case CODE_LABEL: - ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); - assemble_name (file, buf); - break; - - case CONST_INT: - fprintf (file, "%d", SIGN_EXTEND_SHORT (INTVAL (x))); - break; - - case CONST: - d10v_output_addr_const (file, XEXP (x, 0)); - break; - - case PLUS: - /* Some assemblers need integer constants to appear last (eg masm). */ - if (GET_CODE (XEXP (x, 0)) == CONST_INT) - { - d10v_output_addr_const (file, XEXP (x, 1)); - if (INTVAL (XEXP (x, 0)) >= 0) - fprintf (file, "+"); - d10v_output_addr_const (file, XEXP (x, 0)); - } - else - { - d10v_output_addr_const (file, XEXP (x, 0)); - if (INTVAL (XEXP (x, 1)) >= 0) - fprintf (file, "+"); - d10v_output_addr_const (file, XEXP (x, 1)); - } - break; - - case MINUS: - /* Avoid outputting things like x-x or x+5-x, - since some assemblers can't handle that. */ - x = simplify_subtraction (x); - if (GET_CODE (x) != MINUS) - goto restart; - - d10v_output_addr_const (file, XEXP (x, 0)); - fprintf (file, "-"); - if (GET_CODE (XEXP (x, 1)) == CONST_INT - && INTVAL (XEXP (x, 1)) < 0) - { - fprintf (file, ASM_OPEN_PAREN); - d10v_output_addr_const (file, XEXP (x, 1)); - fprintf (file, ASM_CLOSE_PAREN); - } - else - d10v_output_addr_const (file, XEXP (x, 1)); - break; - - case ZERO_EXTEND: - case SIGN_EXTEND: - d10v_output_addr_const (file, XEXP (x, 0)); - break; - } -} - - -/* A C compound statement to output to stdio stream STREAM the - assembler syntax for an instruction operand that is a memory - reference whose address is X. X is an RTL expression. - - On some machines, the syntax for a symbolic address depends on the - section that the address refers to. On these machines, define the - macro `ENCODE_SECTION_INFO' to store the information into the - `symbol_ref', and then check for it here. *Note Assembler - Format::. */ - -void -print_operand_address (stream, x) - FILE *stream; - rtx x; -{ - rtx x0, x1; - - if (GET_CODE (x) == MEM) - x = XEXP (x, 0); - - switch (GET_CODE (x)) - { - default: - break; - - case REG: - fputs (reg_names[ REGNO (x) ], stream); - return; - - case CONST_INT: - fprintf (stream, "%d", SIGN_EXTEND_SHORT (INTVAL (x))); - return; - - case SYMBOL_REF: - case CONST: - case LABEL_REF: - d10v_output_addr_const (stream, x); - return; - } - - fatal_insn ("Bad insn to print_operand_address:", x); -} - - -/* Print a memory reference suitable for the ld/st instructions. */ - -static void -print_operand_memory_reference (stream, x) - FILE *stream; - rtx x; -{ - rtx x0, x1; - int offset; - - switch (GET_CODE (x)) - { - default: - fatal_insn ("Bad insn to print_operand_memory_reference:", x); - break; - - case SUBREG: - offset = 0; - do { - offset += SUBREG_WORD (x); - x = SUBREG_REG (x); - } while (GET_CODE (x) == SUBREG); - fprintf (stream, "@%s", reg_names[ REGNO (x)+offset ]); - break; - - case REG: - fprintf (stream, "@%s", reg_names[ REGNO (x) ]); - break; - - case CONST_INT: - fprintf (stream, "@(%d,%s)", SIGN_EXTEND_SHORT (INTVAL (x)), reg_names[ GPR_ZERO_REGNUM ]); - break; - - case SYMBOL_REF: - case CONST: - case LABEL_REF: - fputs ("@(", stream); - d10v_output_addr_const (stream, x); - fprintf (stream, ",%s)", reg_names[ GPR_ZERO_REGNUM ]); - break; - - case PLUS: - x0 = XEXP (x, 0); - x1 = XEXP (x, 1); - offset = 0; - while (GET_CODE (x0) == SUBREG) - { - offset += SUBREG_WORD (x0); - x0 = SUBREG_REG (x0); - } - - if (CONSTANT_ADDRESS_P (x1) && GET_CODE (x0) == REG && GPR_P (REGNO (x0))) - { - if (GET_CODE (x1) == CONST_INT && INTVAL (x1) == 0) - fprintf (stream, "@%s", reg_names[ REGNO (x0)+offset ]); - else if (GET_CODE (x1) == CONST_INT) - fprintf (stream, "@(%d,%s)", SIGN_EXTEND_SHORT (INTVAL (x1)), - reg_names[ REGNO (x0)+offset ]); - else - { - fputs ("@(", stream); - d10v_output_addr_const (stream, x1); - fprintf (stream, ",%s)", reg_names[ REGNO (x0)+offset ]); - return; - } - } - else - fatal_insn ("Bad insn to print_operand_memory_reference:", x); - - break; - - case POST_INC: - x0 = XEXP (x, 0); - if (GET_CODE (x0) == REG && GPR_P (REGNO (x0))) - fprintf (stream, "@%s+", reg_names[ REGNO (x0) ]); - else - fatal_insn ("Bad insn to print_operand_memory_reference:", x); - - break; - - case POST_DEC: - x0 = XEXP (x, 0); - if (GET_CODE (x0) == REG && GPR_P (REGNO (x0)) - && REGNO (x0) != STACK_POINTER_REGNUM) - fprintf (stream, "@%s-", reg_names[ REGNO (x0) ]); - else - fatal_insn ("Bad insn to print_operand_memory_reference:", x); - - break; - - case PRE_DEC: - x0 = XEXP (x, 0); - if (GET_CODE (x0) == REG && REGNO (x0) == STACK_POINTER_REGNUM) - fprintf (stream, "@-%s", reg_names[ REGNO (x0) ]); - else - fatal_insn ("Bad insn to print_operand_memory_reference:", x); - - break; - - } -} - - -/* A C compound statement to output to stdio stream STREAM the - assembler syntax for an instruction operand X. X is an RTL - expression. - - LETTER is a value that can be used to specify one of several ways of - printing the operand. It is used when identical operands must be - printed differently depending on the context. LETTER comes from the - `%' specification that was used to request printing of the - operand. If the specification was just `%DIGIT' then LETTER is 0; - if the specification was `%LTR DIGIT' then LETTER is the ASCII code - for LTR. - - If X is a register, this macro should print the register's name. - The names can be found in an array `reg_names' whose type is `char - *[]'. `reg_names' is initialized from `REGISTER_NAMES'. - - When the machine description has a specification `%PUNCT' (a `%' - followed by a punctuation character), this macro is called with a - null pointer for X and the punctuation character for LETTER. */ - -void -print_operand (stream, x, letter) - FILE *stream; - rtx x; - int letter; -{ - enum rtx_code code = (x) ? GET_CODE (x) : NIL; - int regadd; - int split_values[4]; - int shift, log; - rtx x0; - - switch (letter) - { - case '|': /* Issue parallel instructions */ - fputs (" || ", stream); - break; - - case '.': /* Output r14 */ - fputs (reg_names[GPR_ZERO_REGNUM], stream); - break; - - case 'U': /* Extract the upper part (word 0) of a 32-bit value */ - regadd = 0; - goto common_32bit; - - case 'L': /* Extract the lower part (word 1) of a 32-bit value */ - regadd = 1; - /* fall through */ - - common_32bit: - if (code == CONST_INT || code == CONST_DOUBLE) - { - d10v_split_constant32 (x, split_values); - fprintf (stream, "%d", SIGN_EXTEND_SHORT (split_values[regadd])); - } - - else if (code == REG) - fprintf (stream, "%s", reg_names[ REGNO (x)+regadd ]); - - else if (code == MEM && offsettable_memref_p (x)) - print_operand_address (stream, plus_constant (XEXP (x, 0), regadd * UNITS_PER_WORD)); - - else - fatal_insn ("Bad insn for %U/%L:", x); - - break; - - case 'A': /* Extract word 0 of a 64-bit value */ - case 'B': /* Extract word 1 of a 64-bit value */ - case 'C': /* Extract word 2 of a 64-bit value */ - case 'D': /* Extract word 3 of a 64-bit value */ - regadd = letter - 'A'; - if (code == CONST_INT || code == CONST_DOUBLE) - { - d10v_split_constant64 (x, split_values); - fprintf (stream, "%d", split_values[regadd]); - } - - else if (code == REG) - fprintf (stream, "%s", reg_names[ REGNO (x)+regadd ]); - - else if (code == MEM && offsettable_memref_p (x)) - print_operand_memory_reference (stream, plus_constant (XEXP (x, 0), regadd * UNITS_PER_WORD)); - - else - fatal_insn ("Bad insn for %A/%B/%C/%D:", x); - - break; - - case 'M': /* Print a memory reference for ld/st instructions */ - if (GET_CODE (x) != MEM) - fatal_insn ("Bad insn to print_operand 'M' modifier:", x); - - print_operand_memory_reference (stream, XEXP (x, 0)); - break; - - case 'F': /* Print an appropriate 'f' or 't' for a false comparision instruction. */ - case 'T': /* Print an appropriate 'f' or 't' for a true comparision instruction. */ - if ((GET_CODE (x) == NE || GET_CODE (x) == EQ) - && (GET_MODE (x) == CCmode || GET_MODE (x) == CC_REVmode) - && GET_CODE (XEXP (x, 0)) == REG && REGNO (XEXP (x, 0)) == F0_REGNUM - && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 0) - { - int true_false = (GET_MODE (x) == CC_REVmode); - - if (letter == 'F') - true_false = !true_false; - - if (GET_CODE (x) == EQ) - true_false = !true_false; - - putc ((true_false) ? 't' : 'f', stream); - } - - else - fatal_insn ("Bad insn to print_operand 'F' or 'T' modifier:", x); - break; - - case 'b': /* emit offset single bit to change */ - if (GET_CODE (x) == CONST_INT && (log = exact_log2 (INTVAL (x))) >= 0) - fprintf (stream, "%d", 15 - log); - - else if (GET_CODE (x) == CONST_INT && (log = exact_log2 (~ INTVAL (x))) >= 0) - fprintf (stream, "%d", 15 - log); - - else - fatal_insn ("Bad insn to print_operand 'b' modifier:", x); - break; - - case 's': /* print ldi.s value for composing ldi.l out of ldi.s and slli */ - if (GET_CODE (x) == CONST_INT - && (shift = ldi_shift_operand (x, HImode)) > 0) - { - fprintf (stream, "%d", ((int) INTVAL (x)) >> shift); - } - - else - fatal_insn ("Bad insn to print_operand 'S' modifier:", x); - break; - - case 'S': /* print shift value for composing ldi.l out of ldi.s and slli */ - if (GET_CODE (x) == CONST_INT - && (shift = ldi_shift_operand (x, HImode)) > 0) - { - fprintf (stream, "%d", shift); - } - - else - fatal_insn ("Bad insn to print_operand 'S' modifier:", x); - break; - - case 'u': /* print a 'u' if the operator is ZERO_EXTEND */ - if (GET_CODE (x) == ZERO_EXTEND) - putc ('u', stream); - break; - - case 0: - if (code == REG) - fputs (reg_names[ REGNO (x) ], stream); - - else if (code == CONST_INT) - fprintf (stream, "%d", (int)INTVAL (x)); - - else if (code == MEM) - print_operand_address (stream, XEXP (x, 0)); - - else if (CONSTANT_ADDRESS_P (x)) - print_operand_address (stream, x); - - else - fatal_insn ("Bad insn in print_operand, 0 case", x); - - return; - - default: - { - char buf[80]; - - sprintf (buf, "Invalid asm template character '%%%c'", letter); - fatal_insn (buf, x); - } - } -} - - -/* A C statement (sans semicolon) for initializing the variable CUM - for the state at the beginning of the argument list. The variable - has type `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node - for the data type of the function which will receive the args, or 0 - if the args are to a compiler support library function. The value - of INDIRECT is nonzero when processing an indirect call, for - example a call through a function pointer. The value of INDIRECT - is zero for a call to an explicitly named function, a library - function call, or when `INIT_CUMULATIVE_ARGS' is used to find - arguments for the function being compiled. - - When processing a call to a compiler support library function, - LIBNAME identifies which one. It is a `symbol_ref' rtx which - contains the name of the function, as a string. LIBNAME is 0 when - an ordinary C function call is being processed. Thus, each time - this macro is called, either LIBNAME or FNTYPE is nonzero, but - never both of them at once. */ - -void -init_cumulative_args (cum, fntype, libname, indirect, incoming) - CUMULATIVE_ARGS *cum; - tree fntype; - rtx libname; - int indirect; - int incoming; -{ - cum->reg = 0; - cum->stack = 4; - - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "\ninit_cumulative_args:"); - if (indirect) - fputs (" indirect", stderr); - - if (incoming) - fputs (" incoming", stderr); - - if (fntype) - { - tree ret_type = TREE_TYPE (fntype); - fprintf (stderr, " return=%s,", - tree_code_name[ (int)TREE_CODE (ret_type) ]); - } - - if (libname && GET_CODE (libname) == SYMBOL_REF) - fprintf (stderr, " libname=%s", XSTR (libname, 0)); - - putc ('\n', stderr); - } -} - - -/* If defined, a C expression that gives the alignment boundary, in - bits, of an argument with the specified mode and type. If it is - not defined, `PARM_BOUNDARY' is used for all arguments. */ - -int -function_arg_boundary (mode, type) - enum machine_mode mode; - tree type; -{ - int size = ((mode == BLKmode && type) - ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)); - - return ((size >= 2 * UNITS_PER_WORD) ? 2*BITS_PER_WORD : BITS_PER_WORD); -} - - -/* A C expression that controls whether a function argument is passed - in a register, and which register. - - The arguments are CUM, which summarizes all the previous - arguments; MODE, the machine mode of the argument; TYPE, the data - type of the argument as a tree node or 0 if that is not known - (which happens for C support library functions); and NAMED, which - is 1 for an ordinary argument and 0 for nameless arguments that - correspond to `...' in the called function's prototype. - - The value of the expression should either be a `reg' RTX for the - hard register in which to pass the argument, or zero to pass the - argument on the stack. - - For machines like the Vax and 68000, where normally all arguments - are pushed, zero suffices as a definition. - - The usual way to make the ANSI library `stdarg.h' work on a machine - where some arguments are usually passed in registers, is to cause - nameless arguments to be passed on the stack instead. This is done - by making `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the - definition of this macro to determine if this argument is of a - type that must be passed in the stack. If `REG_PARM_STACK_SPACE' - is not defined and `FUNCTION_ARG' returns non-zero for such an - argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is - defined, the argument will be computed in the stack and then - loaded into a register. */ - -struct rtx_def * -function_arg (cum, mode, type, named) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int named; -{ - int align = ((cum->reg & 1) != 0 - && function_arg_boundary (mode, type) >= (2*BITS_PER_WORD)); - int size = ((mode == BLKmode && type) - ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)); - - rtx ret; - - if ((cum->reg + align) * 2 + size > (ARG_LAST - ARG_FIRST + 1) * 2) - ret = NULL_RTX; - - else - ret = gen_rtx (REG, mode, ARG_FIRST + cum->reg + align); - - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "function_arg: words = %2d %2d, mode = %4s, named = %d, align = %d, size = %3d, arg = %s\n", - cum->reg, cum->stack, GET_MODE_NAME (mode), named, align, size, - (ret) ? reg_names[ REGNO (ret) ] : "memory"); - - return ret; -} - - - -/* If defined, a C expression that indicates when it is the called - function's responsibility to make a copy of arguments passed by - invisible reference. Normally, the caller makes a copy and passes - the address of the copy to the routine being called. When - FUNCTION_ARG_CALLEE_COPIES is defined and is nonzero, the caller - does not make a copy. Instead, it passes a pointer to the "live" - value. The called function must not modify this value. If it can - be determined that the value won't be modified, it need not make a - copy; otherwise a copy must be made. */ - -int -function_arg_callee_copies (cum, mode, type, named) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int named; -{ - return TARGET_CALLEE_COPIES != 0; -} - - -/* A C statement (sans semicolon) to update the summarizer variable - CUM to advance past an argument in the argument list. The values - MODE, TYPE and NAMED describe that argument. Once this is done, - the variable CUM is suitable for analyzing the *following* - argument with `FUNCTION_ARG', etc. - - This macro need not do anything if the argument in question was - passed on the stack. The compiler knows how to track the amount - of stack space used for arguments without any special help. */ - -void -function_arg_advance (cum, mode, type, named) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int named; -{ - int align = ((cum->reg & 1) != 0 - && function_arg_boundary (mode, type) >= (2*BITS_PER_WORD)); - - int size = ((mode == BLKmode && type) - ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)); - - int words = (size + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; - - if (cum->reg + align + words <= (ARG_LAST - ARG_FIRST + 1)) - cum->reg += align + words; - else -#if 0 /* ??? there should be no such alignment here, but there appears to be. - This is probably a backend bug. */ - cum->stack += words; -#else - cum->stack += align + words; -#endif - - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "function_adv: words = %2d %2d, mode = %4s, named = %d, align = %d, size = %3d\n", - cum->reg, cum->stack, GET_MODE_NAME (mode), named, align, size); -} - - -/* Perform any needed actions needed for a function that is receiving a - variable number of arguments. - - CUM is as above. - - MODE and TYPE are the mode and type of the current parameter. - - PRETEND_SIZE is a variable that should be set to the amount of stack - that must be pushed by the prolog to pretend that our caller pushed - it. - - Normally, this macro will push all remaining incoming registers on the - stack and set PRETEND_SIZE to the length of the registers pushed. */ - -void -setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int *pretend_size; - int no_rtl; - -{ - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "setup_vararg: words = %2d %2d, mode = %4s, no_rtl= %d\n", - cum->reg, cum->stack, GET_MODE_NAME (mode), no_rtl); -} - - -/* If defined, is a C expression that produces the machine-specific - code for a call to `__builtin_saveregs'. This code will be moved - to the very beginning of the function, before any parameter access - are made. The return value of this function should be an RTX that - contains the value to use as the return of `__builtin_saveregs'. - - The argument ARGS is a `tree_list' containing the arguments that - were passed to `__builtin_saveregs'. - - If this macro is not defined, the compiler will output an ordinary - call to the library function `__builtin_saveregs'. - - On the D10V return the start address of the area on the stack - used to hold arguments (including the 4 words pushed at the start - of the function for the arguments passed in registers. */ - -struct rtx_def * -expand_builtin_saveregs (args) - tree args; -{ - return gen_rtx (PLUS, Pmode, - virtual_incoming_args_rtx, - GEN_INT (- UNITS_PER_WORD * (ARG_LAST + 1 - ARG_FIRST))); -} - - -/* A C compound statement with a conditional `goto LABEL;' executed - if X (an RTX) is a legitimate memory address on the target machine - for a memory operand of mode MODE. - - It usually pays to define several simpler macros to serve as - subroutines for this one. Otherwise it may be too complicated to - understand. - - This macro must exist in two variants: a strict variant and a - non-strict one. The strict variant is used in the reload pass. It - must be defined so that any pseudo-register that has not been - allocated a hard register is considered a memory reference. In - contexts where some kind of register is required, a pseudo-register - with no hard register must be rejected. - - The non-strict variant is used in other passes. It must be - defined to accept all pseudo-registers in every context where some - kind of register is required. - - Compiler source files that want to use the strict variant of this - macro define the macro `REG_OK_STRICT'. You should use an `#ifdef - REG_OK_STRICT' conditional to define the strict variant in that - case and the non-strict variant otherwise. - - Subroutines to check for acceptable registers for various purposes - (one for base registers, one for index registers, and so on) are - typically among the subroutines used to define - `GO_IF_LEGITIMATE_ADDRESS'. Then only these subroutine macros - need have two variants; the higher levels of macros may be the - same whether strict or not. */ - -#define XREGNO_OK_FOR_BASE_P(REGNO, STRICT_P) \ - (GPR_P (REGNO) || \ - (!STRICT_P && ((REGNO) == ARG_POINTER_REGNUM \ - || (REGNO) >= FIRST_PSEUDO_REGISTER))) - -int -d10v_legitimate_address_p (mode, x, strict_p) - enum machine_mode mode; - rtx x; - int strict_p; -{ - rtx x0, x1; - int ret = 0; - - switch (GET_CODE (x)) - { - default: - break; - - case PLUS: - x0 = XEXP (x, 0); - x1 = XEXP (x, 1); - - while (GET_CODE (x0) == SUBREG) - x0 = SUBREG_REG (x0); - - while (GET_CODE (x1) == SUBREG) - x1 = SUBREG_REG (x1); - - if (GET_CODE (x0) == REG - && XREGNO_OK_FOR_BASE_P (REGNO (x0), strict_p) - && CONSTANT_P (x1) - && LEGITIMATE_CONSTANT_P (x1)) - ret = 1; - - break; - - case SUBREG: - do - { - x = SUBREG_REG (x); - } - while (GET_CODE (x) == SUBREG); /* fall through */ - - case REG: - ret = XREGNO_OK_FOR_BASE_P (REGNO (x), strict_p); - break; - - case CONST_INT: - ret = IN_RANGE_P (INTVAL (x), -32768, 32767); - break; - - case CONST: - case SYMBOL_REF: - case LABEL_REF: - ret = 1; - break; - - case POST_INC: - x0 = XEXP (x, 0); - if ((mode == HImode || mode == SImode || mode == SFmode) - && GET_CODE (x0) == REG && XREGNO_OK_FOR_BASE_P (REGNO (x0), strict_p)) - ret = 1; - break; - - case POST_DEC: - x0 = XEXP (x, 0); - if ((mode == HImode || mode == SImode || mode == SFmode) - && GET_CODE (x0) == REG && XREGNO_OK_FOR_BASE_P (REGNO (x0), strict_p) - && REGNO (x0) != STACK_POINTER_REGNUM) - ret = 1; - break; - - case PRE_DEC: - x0 = XEXP (x, 0); - if ((mode == HImode || mode == SImode || mode == SFmode) - && GET_CODE (x0) == REG && REGNO (x0) == STACK_POINTER_REGNUM) - ret = 1; - break; - } - - if (TARGET_DEBUG_ADDR) - { - fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, mode = %s, result = %d, addresses are %sstrict\n", - GET_MODE_NAME (mode), ret, (strict_p) ? "" : "not "); - debug_rtx (x); - } - - return ret; -} - - - -/* A C compound statement that attempts to replace X with a valid - memory address for an operand of mode MODE. WIN will be a C - statement label elsewhere in the code; the macro definition may use - - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); - - to avoid further processing if the address has become legitimate. - - X will always be the result of a call to `break_out_memory_refs', - and OLDX will be the operand that was given to that function to - produce X. - - The code generated by this macro should not alter the substructure - of X. If it transforms X into a more legitimate form, it should - assign X (which will always be a C variable) a new value. - - It is not necessary for this macro to come up with a legitimate - address. The compiler has standard ways of doing so in all cases. - In fact, it is safe for this macro to do nothing. But often a - machine-dependent strategy can generate better code. */ - -struct rtx_def * -d10v_legitimize_address (x, oldx, mode, strict_p) - rtx x; - rtx oldx; - enum machine_mode mode; - int strict_p; -{ - rtx ret = NULL_RTX; - - if (TARGET_DEBUG_ADDR) - { - if (ret) - { - fprintf (stderr, "\n========== LEGITIMIZE_ADDRESS, transformed:\n"); - debug_rtx (x); - fprintf (stderr, "\ninto:\n"); - debug_rtx (ret); - } - else - { - fprintf (stderr, "\n========== LEGITIMIZE_ADDRESS, did nothing with:\n"); - debug_rtx (x); - } - } - - return ret; -} - - -/* A C statement or compound statement with a conditional `goto - LABEL;' executed if memory address X (an RTX) can have different - meanings depending on the machine mode of the memory reference it - is used for or if the address is valid for some modes but not - others. - - Autoincrement and autodecrement addresses typically have - mode-dependent effects because the amount of the increment or - decrement is the size of the operand being addressed. Some - machines have other mode-dependent addresses. Many RISC machines - have no mode-dependent addresses. - - You may assume that ADDR is a valid address for the machine. */ - -int -d10v_mode_dependent_address_p (addr) - rtx addr; -{ - switch (GET_CODE (addr)) - { - default: - break; - - case POST_INC: - case POST_DEC: - case PRE_DEC: - return 1; - } - return 0; -} - - -/* Return an RTX that refers to the nth subword of a multiword - expression. This is similar to operand_subword, but that - has a bias that SImode is a word. */ - -struct rtx_def * -d10v_subword (op, word_num, target_mode, source_mode) - rtx op; - int word_num; - enum machine_mode target_mode; - enum machine_mode source_mode; -{ - enum rtx_code code = GET_CODE (op); - enum machine_mode mode = GET_MODE (op); - int split_values[4]; - - if (!IN_RANGE_P (word_num, 0, 3)) - error ("div10_subword_mode: Internal error -- word_num (%d) should be >= 0 && <= 3", word_num); - - if (target_mode == SImode && word_num != 0 && word_num != 2) - error ("div10_subword_mode: Internal error -- word_num (%d) should be 0 or 2 for SImode", word_num); - - if (target_mode != HImode && target_mode != SImode) - error ("d10v_subword_mode: Internal error -- target_mode (%s) must be HImode or SImode", GET_MODE_NAME (target_mode)); - - if (code == REG) - { - if ((UNITS_PER_WORD * word_num) >= GET_MODE_SIZE (mode)) - error ("div10_subword: Internal error -- word_num (%d) is too large for mode %s", - word_num, GET_MODE_NAME (mode)); - - if (!reload_completed) - return gen_rtx (SUBREG, target_mode, op, word_num); - - return gen_rtx (REG, target_mode, REGNO (op) + word_num); - } - - else if (code == SUBREG) - { - if ((UNITS_PER_WORD * word_num) >= GET_MODE_SIZE (mode)) - error ("div10_subword: Internal error -- word_num (%d) is too large for mode %s", - word_num, GET_MODE_NAME (mode)); - - if (!reload_completed) - return gen_rtx (SUBREG, target_mode, op, word_num); - - do - { - word_num += SUBREG_WORD (op); - op = SUBREG_REG (op); - } - while (GET_CODE (op) == SUBREG); - - return gen_rtx (REG, target_mode, REGNO (op) + word_num); - } - - else if ((code == CONST_INT || code == CONST_DOUBLE) && GET_MODE_SIZE (source_mode) == 2) - { - if (word_num > 1) - error ("div10_subword: Internal error -- word_num (%d) is too large for 32-bit constants", word_num); - - d10v_split_constant32 (op, split_values); - return GEN_INT (SIGN_EXTEND_SHORT (split_values[word_num])); - } - - else if ((code == CONST_INT || code == CONST_DOUBLE) && GET_MODE_SIZE (source_mode) == 4) - { - d10v_split_constant32 (op, split_values); - return GEN_INT (SIGN_EXTEND_SHORT (split_values[word_num])); - } - - else if ((code == CONST_INT || code == CONST_DOUBLE) && GET_MODE_SIZE (source_mode) == 8) - { - HOST_WIDE_INT value; - - d10v_split_constant64 (op, split_values); - value = SIGN_EXTEND_SHORT (split_values[word_num]); - if (GET_MODE_SIZE (target_mode) == 4) - value = (value << 16) & (split_values[word_num+1] & 0xffff); - - return GEN_INT (value); - } - - else if (code == MEM && word_num == 0) - return op; - - else if (code == MEM) - return change_address (op, target_mode, plus_constant (XEXP (op, 0), word_num * 16)); - - else - fatal_insn ("Cannot get subword of:", op); - - return NULL_RTX; -} - - -/* Calculate the stack information for the current function. - - D10V stack frames look like: - - high | .... | - +-------------------------------+ - | Argument word #8 | - +-------------------------------+ - | Argument word #7 | - +-------------------------------+ - | Argument word #6 | - +-------------------------------+ - | Argument word #5 | - Prev sp +-------------------------------+ - | | - | Save for arguments 1..4 if | - | the func. uses stdarg/varargs | - | | - +-------------------------------+ - | | - | Save area for preserved regs | - | | - +-------------------------------+ - | | - | Local variables | - | | - +-------------------------------+ - | | - | alloca space if used | - | | - +-------------------------------+ - | | - | Space for outgoing arguments | - | | - +-------------------------------+ - | Return address if -mnew-stack | - +-------------------------------+ - | Previous sp if -mnew-stack | - low SP----> +-------------------------------+ -*/ - -d10v_stack_t * -d10v_stack_info () -{ - static d10v_stack_t info, zero_info; - d10v_stack_t *info_ptr = &info; - tree fndecl = current_function_decl; - tree fntype = TREE_TYPE (fndecl); - int varargs_p = 0; - tree cur_arg; - tree next_arg; - int saved_gprs; - int saved_accs; - int i; - - /* If we've already calculated the values and reload is complete, just return now */ - if (d10v_stack_cache) - return d10v_stack_cache; - - /* Zero all fields portably */ - info = zero_info; - - if (profile_flag) - regs_ever_live[RETURN_ADDRESS_REGNUM] = 1; - - /* Determine if this is a stdarg function */ - if (TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node)) - varargs_p = 1; - else - { - /* Find the last argument, and see if it is __builtin_va_alist. */ - for (cur_arg = DECL_ARGUMENTS (fndecl); cur_arg != (tree)0; cur_arg = next_arg) - { - next_arg = TREE_CHAIN (cur_arg); - if (next_arg == (tree)0) - { - if (DECL_NAME (cur_arg) - && !strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)), "__builtin_va_alist")) - varargs_p = 1; - - break; - } - } - } - - /* Calculate which registers need to be saved & save area size */ - saved_accs = 0; - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) - { - if (regs_ever_live[i] && !call_used_regs[i]) - { - info_ptr->save_p[i] = 1; - saved_accs++; - } - } - - /* If any accumulators are to be saved, we need a one two word register - pair to save the main portion of the accs and another register to - save the guard digits. */ - if (saved_accs) - { - regs_ever_live[SAVE_GUARD_REGNUM] = 1; - regs_ever_live[SAVE_ACC_REGNUM] = 1; - regs_ever_live[SAVE_ACC_REGNUM+1] = 1; - } - - saved_gprs = 0; - for (i = GPR_FIRST; i <= GPR_LAST; i++) - { - if (regs_ever_live[i] && (!call_used_regs[i] || i == RETURN_ADDRESS_REGNUM)) - { - info_ptr->save_p[i] = 1; - saved_gprs++; - } - } - - /* Determine various sizes */ - info_ptr->varargs_p = varargs_p; - info_ptr->varargs_size = D10V_ALIGN (((varargs_p) - ? (ARG_LAST + 1 - ARG_FIRST) * UNITS_PER_WORD - : 0), UNITS_PER_WORD); - - info_ptr->gpr_size = D10V_ALIGN (UNITS_PER_WORD * saved_gprs, UNITS_PER_WORD); - info_ptr->accum_size = D10V_ALIGN (3 * UNITS_PER_WORD * saved_accs, UNITS_PER_WORD); - info_ptr->vars_size = D10V_ALIGN (get_frame_size (), UNITS_PER_WORD); - info_ptr->parm_size = D10V_ALIGN (current_function_outgoing_args_size, UNITS_PER_WORD); - info_ptr->total_size = D10V_ALIGN (info_ptr->gpr_size - + info_ptr->accum_size - + info_ptr->vars_size - + info_ptr->parm_size - + info_ptr->varargs_size, (STACK_BOUNDARY / BITS_PER_UNIT)); - - if (reload_completed) - d10v_stack_cache = info_ptr; - - return info_ptr; -} - - -/* Internal function to print all of the information about the stack */ - -void -debug_stack_info (info) - d10v_stack_t *info; -{ - int i; - - if (!info) - info = d10v_stack_info (); - - fprintf (stderr, "\nStack information for function %s:\n", - ((current_function_decl && DECL_NAME (current_function_decl)) - ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl)) - : "")); - - fprintf (stderr, "\tvarargs_p = %d\n", info->varargs_p); - fprintf (stderr, "\tvarargs_size = %d\n", info->varargs_size); - fprintf (stderr, "\tvars_size = %d\n", info->vars_size); - fprintf (stderr, "\tparm_size = %d\n", info->parm_size); - fprintf (stderr, "\tgpr_size = %d\n", info->gpr_size); - fprintf (stderr, "\taccum_size = %d\n", info->accum_size); - fprintf (stderr, "\ttotal_size = %d\n", info->total_size); - fprintf (stderr, "\tsaved registers ="); - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (info->save_p[i]) - fprintf (stderr, " %s", reg_names[i]); - - putc ('\n', stderr); - fflush (stderr); -} - - -/* Return non-zero if this function is known to have a null or 1 instruction epilogue. */ - -int -direct_return () -{ - if (reload_completed) - { - d10v_stack_t *info = d10v_stack_info (); - - /* If no epilogue code is needed, can use just a simple jump */ - if (info->total_size == 0) - return 1; - - /* Also allow the common case where r13 is reloaded before the return, - since we take the same space as a forward branch for the two. */ - if (info->total_size == UNITS_PER_WORD && info->save_p[RETURN_ADDRESS_REGNUM]) - return 1; - - /* Using similar logic, if just a small amount of local stack was allocated - and no registers saved, skip forward branch */ - if (info->total_size == info->vars_size - && IN_RANGE_P (info->total_size, 1, 16)) - return 1; - } - - return 0; -} - - -/* Internal function to print a memory reference. */ - -static void -print_memory_ref (stream, instruction, reg, offset, index_reg) - FILE *stream; - char *instruction; - int reg; - int offset; - int index_reg; -{ - if (offset == 0) - fprintf (stream, "\t%s %s,@%s\n", instruction, reg_names[reg], - reg_names[index_reg]); - else - fprintf (stream, "\t%s %s,@(%d,%s)\n", instruction, reg_names[reg], offset, - reg_names[index_reg]); -} - - -/* A C compound statement that outputs the assembler code for entry - to a function. The prologue is responsible for setting up the - stack frame, initializing the frame pointer register, saving - registers that must be saved, and allocating SIZE additional bytes - of storage for the local variables. SIZE is an integer. FILE is - a stdio stream to which the assembler code should be output. */ - -void -function_prologue (stream, size) - FILE *stream; - int size; -{ - int i, offset; - d10v_stack_t *info = d10v_stack_info (); - char *sp_name = reg_names[STACK_POINTER_REGNUM]; - int total_size = info->total_size; - int gpr_size = info->gpr_size; - int accum_size = info->accum_size; - - if (TARGET_DEBUG_STACK) - debug_stack_info (info); - - /* Save any variable arguments */ - if (info->varargs_p) - { - offset = 0; - for (i = ARG_LAST-1; i >= ARG_FIRST; i -= 2) - { - fprintf (stream, "\tst2w %s,@-%s\n", reg_names[i], sp_name); - offset -= 2 * UNITS_PER_WORD; - total_size -= 2 * UNITS_PER_WORD; - } - } - - /* Save the GPRs by pushing */ - for (i = GPR_FIRST; i <= GPR_LAST; i++) - { - if (info->save_p[i]) - { - if (GPR_EVEN_P (i) && info->save_p[i+1]) - { - total_size -= 2 * UNITS_PER_WORD; - fprintf (stream, "\tst2w %s,@-%s\n", reg_names[i++], sp_name); - } - else - { - total_size -= UNITS_PER_WORD; - fprintf (stream, "\tst %s,@-%s\n", reg_names[i], sp_name); - } - } - } - - /* Now save the ACs (both guard digits and 32-bit value) by moving into r12/r13 and pushing */ - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) - { - if (info->save_p[i]) - { - total_size -= 3 * UNITS_PER_WORD; - fprintf (stream, "\tmvfacg %s,%s\n", reg_names[SAVE_GUARD_REGNUM], - reg_names[i]); - - fprintf (stream, "\tmv2wfac %s,%s\n", reg_names[SAVE_ACC_REGNUM], - reg_names[i]); - - fprintf (stream, "\tst %s,@-%s\n", reg_names[SAVE_GUARD_REGNUM], - sp_name); - - fprintf (stream, "\tst2w %s,@-%s\n", reg_names[SAVE_ACC_REGNUM], - sp_name); - } - } - - if (total_size > 0) - { - if (total_size <= 16) - fprintf (stream, "\tsubi %s,%d\n", sp_name, total_size); - - else - fprintf (stream, "\tadd3 %s,%s,%d\n", sp_name, sp_name, -total_size); - } - - /* Update frame pointer if needed */ - if (frame_pointer_needed) - fprintf (stream, "\tmv %s,%s\n", reg_names[FRAME_POINTER_REGNUM], sp_name); -} - - -/* A C compound statement that outputs the assembler code for exit - from a function. The epilogue is responsible for restoring the - saved registers and stack pointer to their values when the - function was called, and returning control to the caller. This - macro takes the same arguments as the macro `FUNCTION_PROLOGUE', - and the registers to restore are determined from `regs_ever_live' - and `CALL_USED_REGISTERS' in the same way. */ - -void -function_epilogue (stream, size) - FILE *stream; - int size; -{ - int i; - rtx insn = get_last_insn (); - char *sp_name = reg_names[STACK_POINTER_REGNUM]; - - /* If the last insn was a BARRIER, we don't have to write anything except - the trace table. */ - if (GET_CODE (insn) == NOTE) - insn = prev_nonnote_insn (insn); - - if (insn == 0 || GET_CODE (insn) != BARRIER) - { - d10v_stack_t *info = d10v_stack_info (); - int varargs_size = info->varargs_size; - int stack_size = info->total_size - varargs_size; - int gpr_size = info->gpr_size; - int accum_size = info->accum_size; - - /* If we have a varargs area, but no saved registers (ie, this is a stub) - fold the varargs area back into stack size */ - if (varargs_size && !gpr_size) - { - stack_size += varargs_size; - varargs_size = 0; - } - - /* Restore stack pointer if needed */ - if (frame_pointer_needed) - { - char *fp_name = reg_names[FRAME_POINTER_REGNUM]; - - /* We can combine restoring the stack pointer with the adjustment directly. */ - if (stack_size > 0) - { - fprintf (stream, "\tadd3 %s,%s,%d\n", sp_name, fp_name, stack_size - gpr_size - accum_size); - stack_size = gpr_size + accum_size; - } - else - fprintf (stream, "\tmv %s,%s\n", sp_name, fp_name); - } - - /* Restore stack pointer, other than the space needed to load registers w/postdecrement */ - stack_size -= gpr_size + accum_size; - if (stack_size > 0) - { - if (stack_size <= 16) - fprintf (stream, "\taddi %s,%d\n", sp_name, stack_size); - else - fprintf (stream, "\tadd3 %s,%s,%d\n", sp_name, sp_name, stack_size); - } - - /* Restore any saved accumulators. We must restore both the accumulator and the guard digits */ - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) - { - if (info->save_p[i]) - { - fprintf (stream, "\tld2w %s,@%s+\n", reg_names[SAVE_ACC_REGNUM], - sp_name); - - fprintf (stream, "\tld %s,@%s+\n", reg_names[SAVE_GUARD_REGNUM], - sp_name); - - fprintf (stream, "\tmv2wtac %s,%s\n", reg_names[SAVE_ACC_REGNUM], - reg_names[i]); - - fprintf (stream, "\tmvtacg %s,%s\n", reg_names[SAVE_GUARD_REGNUM], - reg_names[i]); - } - } - - /* Restore the gprs by poping the registers. */ - for (i = GPR_LAST; i >= GPR_FIRST; i--) - { - if (info->save_p[i]) - { - if (GPR_ODD_P (i) && info->save_p[i-1]) - fprintf (stream, "\tld2w %s,@%s+\n", reg_names[--i], sp_name); - else - fprintf (stream, "\tld %s,@%s+\n", reg_names[i], sp_name); - } - } - - /* Finally remove varargs area */ - if (varargs_size) - fprintf (stream, "\taddi %s,%d\n", sp_name, varargs_size); - - /* Return to the user */ - fprintf (stream, "\tjmp %s\n", reg_names[RETURN_ADDRESS_REGNUM]); - } - - /* Clear out stack cache */ - d10v_stack_cache = (d10v_stack_t *)0; -} -/* END CYGNUS LOCAL -- meissner/d10v abi change */ diff --git a/gcc/config/d10v/d10v.h b/gcc/config/d10v/d10v.h deleted file mode 100755 index bd77ba9..0000000 --- a/gcc/config/d10v/d10v.h +++ /dev/null @@ -1,5065 +0,0 @@ -/* CYGNUS LOCAL -- meissner/d10v abi change */ -/* Definitions of target machine for Mitsubishi D10V. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. - Contributed by Cygnus Support. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Include generic ELF definitions */ - -#include "svr4.h" - -/* D10v specific macros */ - -/* Align an address */ -#define D10V_ALIGN(addr,align) (((addr) + (align) - 1) & ~((align) - 1)) - -/* Truncate and sign extend a value to 16 bits. */ -#define SIGN_EXTEND_SHORT(VALUE) ((int)((((VALUE) & 0xffff) ^ 0x8000) - 0x8000)) - - -/* Driver configuration */ - -/* A C string constant that tells the GNU CC driver program options to - pass to CPP. It can also specify how to translate options you - give to GNU CC into options for GNU CC to pass to the CPP. - - Do not define this macro if it does not need to do anything. */ -#define CPP_SPEC "\ -%{mint32: -D__INT__=32 -D__INT_MAX__=2147483647} \ -%{!mint32: -D__INT__=16 -D__INT_MAX__=32767} \ -%{mdouble64: -D__DOUBLE__=64} \ -%{!mdouble64: -D__DOUBLE__=32}" - -/* A C string constant that tells the GNU CC driver program options to - pass to `cc1'. It can also specify how to translate options you - give to GNU CC into options for GNU CC to pass to the `cc1'. - - Do not define this macro if it does not need to do anything. */ -/* #define CC1_SPEC */ - -/* A C string constant that tells the GNU CC driver program options to - pass to `cc1plus'. It can also specify how to translate options - you give to GNU CC into options for GNU CC to pass to the - `cc1plus'. - - Do not define this macro if it does not need to do anything. */ -/* #define CC1PLUS_SPEC */ - -/* A C string constant that tells the GNU CC driver program options to - pass to the assembler. It can also specify how to translate - options you give to GNU CC into options for GNU CC to pass to the - assembler. See the file `sun3.h' for an example of this. - - Do not define this macro if it does not need to do anything. */ -#undef ASM_SPEC -#if 1 -#define ASM_SPEC "%{!mno-asm-optimize: %{O*: %{!O0: -O} %{O0: %{masm-optimize: -O}}}}" - -#else -#define ASM_SPEC "%{masm-optimize: %{O*: %{!O0: -O}}} %{mno-asm-optimize: }" -#endif - -/* A C string constant that tells the GNU CC driver program how to - run any programs which cleanup after the normal assembler. - Normally, this is not needed. See the file `mips.h' for an - example of this. - - Do not define this macro if it does not need to do anything. */ -/* #define ASM_FINAL_SPEC */ - -/* A C string constant that tells the GNU CC driver program options to - pass to the linker. It can also specify how to translate options - you give to GNU CC into options for GNU CC to pass to the linker. - - Do not define this macro if it does not need to do anything. */ -/* #define LINK_SPEC */ - -/* Another C string constant used much like `LINK_SPEC'. The - difference between the two is that `LIB_SPEC' is used at the end - of the command given to the linker. - - If this macro is not defined, a default is provided that loads the - standard C library from the usual place. See `gcc.c'. */ -#undef LIB_SPEC -#define LIB_SPEC "%{msim: %e-msim is no longer supported} -lc -lnosys" - -/* Another C string constant that tells the GNU CC driver program how - and when to place a reference to `libgcc.a' into the linker - command line. This constant is placed both before and after the - value of `LIB_SPEC'. - - If this macro is not defined, the GNU CC driver provides a default - that passes the string `-lgcc' to the linker unless the `-shared' - option is specified. */ -/* #define LIBGCC_SPEC */ - -/* Another C string constant used much like `LINK_SPEC'. The - difference between the two is that `STARTFILE_SPEC' is used at the - very beginning of the command given to the linker. - - If this macro is not defined, a default is provided that loads the - standard C startup file from the usual place. See `gcc.c'. */ -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "crt0%O%s" - - -/* Another C string constant used much like `LINK_SPEC'. The - difference between the two is that `ENDFILE_SPEC' is used at the - very end of the command given to the linker. - - Do not define this macro if it does not need to do anything. */ -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "" - -/* Define this macro to provide additional specifications to put in - the `specs' file that can be used in various specifications like - `CC1_SPEC'. - - The definition should be an initializer for an array of structures, - containing a string constant, that defines the specification name, - and a string constant that provides the specification. - - Do not define this macro if it does not need to do anything. */ -/* #define EXTRA_SPECS */ - -/* Define this macro as a C expression for the initializer of an - array of string to tell the driver program which options are - defaults for this target and thus do not need to be handled - specially when using `MULTILIB_OPTIONS'. - - Do not define this macro if `MULTILIB_OPTIONS' is not defined in - the target makefile fragment or if none of the options listed in - `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */ -#define MULTILIB_DEFAULTS { "mint16", "mdouble32" } - - -/* Run-time target specifications */ - -/* Define this to be a string constant containing `-D' options to - define the predefined macros that identify this machine and system. - These macros will be predefined unless the `-ansi' option is - specified. - - In addition, a parallel set of macros are predefined, whose names - are made by appending `__' at the beginning and at the end. These - `__' macros are permitted by the ANSI standard, so they are - predefined regardless of whether `-ansi' is specified. */ -#define CPP_PREDEFINES "-D__D10V__ -Amachine(d10v)" - -/* Variable to hold flag bits. */ -extern int target_flags; - -/* Machine dependent switche bits */ -#define MASK_INT32 0x00000001 /* ints are 32 bits */ -#define MASK_DOUBLE64 0x00000002 /* double is 64 bits */ -#define MASK_ADDAC3 0x00000004 /* enable ADDAC3/SUBAC3 instructions */ -#define MASK_ACCUM 0x00000008 /* allow use of the accumulators */ -#define MASK_NO_CALLEE_COPIES 0x00000010 /* disable callee copies */ -#define MASK_NO_SMALL_INSNS 0x00000020 /* disable replacing 1 long insn with 2 short ones */ -#define MASK_NO_COND_MOVE 0x00000040 /* disable conditional moves */ -#define MASK_NO_LONGLONG_ALU 0x00000080 /* disable long long plus/minus */ - -#define MASK_DEBUG_MOVE4 0x04000000 /* debug emit_move4_words */ -#define MASK_DEBUG_STACK 0x08000000 /* debug stack offsets */ -#define MASK_DEBUG_ARG 0x10000000 /* debug FUNCTION_ARG */ -#define MASK_DEBUG_ADDR 0x20000000 /* debug GO_IF_LEGITIMATE_ADDRESS */ -#define MASK_DEBUG 0x40000000 /* general debug flag */ - -#ifndef TARGET_DEFAULT -/* XXX: The normal scheduler seems to have a bug regarding no callee copies, so for - now, just set the default appropriately. */ -#ifndef HAIFA -#define TARGET_DEFAULT MASK_NO_CALLEE_COPIES -#else -#define TARGET_DEFAULT 0 -#endif -#endif - -/* Machine dependent switches */ -#define TARGET_INT32 (target_flags & MASK_INT32) -#define TARGET_DOUBLE64 (target_flags & MASK_DOUBLE64) -#define TARGET_ADDAC3 (target_flags & MASK_ADDAC3) -#define TARGET_ACCUM (target_flags & MASK_ACCUM) -#define TARGET_NO_CALLEE_COPIES (target_flags & MASK_NO_CALLEE_COPIES) -#define TARGET_NO_SMALL_INSNS (target_flags & MASK_NO_SMALL_INSNS) -#define TARGET_NO_COND_MOVE (target_flags & MASK_NO_COND_MOVE) -#define TARGET_NO_LONGLONG_ALU (target_flags & MASK_NO_LONGLONG_ALU) -#define TARGET_DEBUG_MOVE4 (target_flags & MASK_DEBUG_MOVE4) -#define TARGET_DEBUG_STACK (target_flags & MASK_DEBUG_STACK) -#define TARGET_DEBUG_ARG (target_flags & MASK_DEBUG_ARG) -#define TARGET_DEBUG_ADDR (target_flags & MASK_DEBUG_ADDR) -#define TARGET_DEBUG (target_flags & MASK_DEBUG) - -#define TARGET_INT16 (! TARGET_INT32) -#define TARGET_DOUBLE32 (! TARGET_DOUBLE64) -#define TARGET_CALLEE_COPIES (! TARGET_NO_CALLEE_COPIES) -#define TARGET_SMALL_INSNS (! TARGET_NO_SMALL_INSNS) -#define TARGET_COND_MOVE (! TARGET_NO_COND_MOVE) -#define TARGET_LONGLONG_ALU (! TARGET_NO_LONGLONG_ALU) - -/* 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. - - Each subgrouping contains a string constant, that defines the - option name, and a number, which contains the bits to set in - `target_flags'. A negative number says to clear bits instead; the - negative of the number is which bits to clear. The actual option - name is made by appending `-m' to the specified name. - - One of the subgroupings should have a null string. The number in - this grouping is the default value for `target_flags'. Any target - options act starting with that value. */ -#define TARGET_SWITCHES \ -{ \ - { "int16", -MASK_INT32 }, \ - { "int32", MASK_INT32 }, \ - { "double64", MASK_DOUBLE64 }, \ - { "double32", -MASK_DOUBLE64 }, \ - { "addac3", MASK_ADDAC3 | MASK_ACCUM }, \ - { "no-addac3", -MASK_ADDAC3 }, \ - { "accum", MASK_ACCUM }, \ - { "no-accum", -MASK_ACCUM }, \ - { "callee-copies", -MASK_NO_CALLEE_COPIES }, \ - { "no-callee-copies", MASK_NO_CALLEE_COPIES }, \ - { "small-insns", -MASK_NO_SMALL_INSNS }, \ - { "no-small-insns", MASK_NO_SMALL_INSNS }, \ - { "cond-move", -MASK_NO_COND_MOVE }, \ - { "no-cond-move", MASK_NO_COND_MOVE }, \ - { "longlong-alu", -MASK_NO_LONGLONG_ALU }, \ - { "no-longlong-alu", MASK_NO_LONGLONG_ALU }, \ - { "debug", MASK_DEBUG }, \ - { "debug-arg", MASK_DEBUG_ARG }, \ - { "debug-addr", MASK_DEBUG_ADDR }, \ - { "debug-stack", MASK_DEBUG_STACK }, \ - { "debug-move4", MASK_DEBUG_MOVE4 }, \ - { "asm-optimize", 0 }, \ - { "no-asm-optimize", 0 }, \ - { "", TARGET_DEFAULT } \ -} - -/* 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. - - Each subgrouping contains a string constant, that defines the - fixed part of the option name, and the address of a variable. The - variable, type `char *', is set to the variable part of the given - option if the fixed part matches. The actual option name is made - by appending `-m' to the specified name. */ - -#define TARGET_OPTIONS \ -{ \ - {"branch-cost=", &d10v_branch_cost_string}, \ - {"cond-exec=", &d10v_cond_exec_string}, \ -} - -/* This macro is a C statement to print on `stderr' a string - describing the particular machine description choice. Every - machine description should define `TARGET_VERSION'. */ -#define TARGET_VERSION fprintf (stderr, " (D10V)") - -/* Sometimes certain combinations of command options do not make - sense on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. - - Don't use this macro to turn on various extra optimizations for - `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ -#define OVERRIDE_OPTIONS override_options () - -/* Some machines may desire to change what optimizations are - performed for various optimization levels. This macro, if - defined, is executed once just after the optimization level is - determined and before the remainder of the command options have - been parsed. Values set in this macro are used as the default - values for the other command line options. - - LEVEL is the optimization level specified; 2 if `-O2' is - specified, 1 if `-O' is specified, and 0 if neither is specified. - - SIZE is non-zero if `-Os' is specified, 0 otherwise. - - On the d10v, turn off scheduling before register allocation, since - it makes for more spills and increases the register pressure. There - is also a bug between passing 64 bit values by reference that the - scheduler tweaks. */ - -#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ -do { \ - if ((LEVEL) > 1) \ - flag_schedule_insns = 0; \ -} while (0) - -/* Define this macro if debugging can be performed even without a - frame pointer. If this macro is defined, GNU CC will turn on the - `-fomit-frame-pointer' option whenever `-O' is specified. */ -#define CAN_DEBUG_WITHOUT_FP 1 - - -/* Storage layout */ - -/* Define this macro to have the value 1 if the most significant bit - in a byte has the lowest number; otherwise define it to have the - value zero. This means that bit-field instructions count from the - most significant bit. If the machine has no bit-field - instructions, then this must still be defined, but it doesn't - matter which value it is defined to. This macro need not be a - constant. - - This macro does not affect the way structure fields are packed into - bytes or words; that is controlled by `BYTES_BIG_ENDIAN'. */ -#define BITS_BIG_ENDIAN 1 - -/* Define this macro to have the value 1 if the most significant byte - in a word has the lowest number. This macro need not be a - constant. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this macro to have the value 1 if, in a multiword object, - the most significant word has the lowest number. This applies to - both memory locations and registers; GNU CC fundamentally assumes - that the order of words in memory is the same as the order in - registers. This macro need not be a constant. */ -#define WORDS_BIG_ENDIAN 1 - -/* Define this macro if WORDS_BIG_ENDIAN is not constant. This must - be a constant value with the same meaning as WORDS_BIG_ENDIAN, - which will be used only when compiling libgcc2.c. Typically the - value will be set based on preprocessor defines. */ -/* #define LIBGCC2_WORDS_BIG_ENDIAN 1 */ - -/* Define this macro to have the value 1 if `DFmode', `XFmode' or - `TFmode' floating point numbers are stored in memory with the word - containing the sign bit at the lowest address; otherwise define it - to have the value 0. This macro need not be a constant. - - You need not define this macro if the ordering is the same as for - multi-word integers. */ -/* #define FLOAT_WORDS_BIG_ENDIAN 1 */ - -/* Define this macro to be the number of bits in an addressable - storage unit (byte); normally 8. */ -#define BITS_PER_UNIT 8 - -/* Number of bits in a word; normally 32. */ -#define BITS_PER_WORD 16 - -/* Maximum number of bits in a word. If this is undefined, the - default is `BITS_PER_WORD'. Otherwise, it is the constant value - that is the largest value that `BITS_PER_WORD' can have at - run-time. */ -#define MAX_BITS_PER_WORD 16 - -/* Number of storage units in a word; normally 4. */ -#define UNITS_PER_WORD 2 - -/* Minimum number of units in a word. If this is undefined, the - default is `UNITS_PER_WORD'. Otherwise, it is the constant value - that is the smallest value that `UNITS_PER_WORD' can have at - run-time. */ -#define MIN_UNITS_PER_WORD 2 - -/* Normal alignment required for function parameters on the stack, in - bits. All stack parameters receive at least this much alignment - regardless of data type. On most machines, this is the same as the - size of an integer. */ -#define PARM_BOUNDARY 16 - -/* Define this macro if you wish to preserve a certain alignment for - the stack pointer. The definition is a C expression for the - desired alignment (measured in bits). - - If `PUSH_ROUNDING' is not defined, the stack will always be aligned - to the specified boundary. If `PUSH_ROUNDING' is defined and - specifies a less strict alignment than `STACK_BOUNDARY', the stack - may be momentarily unaligned while pushing arguments. */ -#define STACK_BOUNDARY 16 - -/* Alignment required for a function entry point, in bits. */ -#define FUNCTION_BOUNDARY 32 - -/* Biggest alignment that any data type can require on this machine, - in bits. */ -#define BIGGEST_ALIGNMENT 16 - -/* Biggest alignment that any structure field can require on this - machine, in bits. If defined, this overrides `BIGGEST_ALIGNMENT' - for structure fields only. */ -/* #define BIGGEST_FIELD_ALIGNMENT */ - -/* An expression for the alignment of a structure field FIELD if the - alignment computed in the usual way is COMPUTED. GNU CC 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) */ - -/* 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'. */ -/* #define MAX_OFILE_ALIGNMENT */ - -/* If defined, a C expression to compute the alignment for a static - variable. 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. - - 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. */ -/* #define DATA_ALIGNMENT(TYPE, BASIC-ALIGN) */ - -/* If defined, a C expression to compute the alignment given to a - constant that is being placed in memory. CONSTANT is the constant - 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. - - 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(CONSTANT, BASIC-ALIGN) */ - -/* Alignment in bits to be given to a structure bit field that - follows an empty field such as `int : 0;'. - - Note that `PCC_BITFIELD_TYPE_MATTERS' also affects the alignment - that results from an empty field. */ -/* #define EMPTY_FIELD_BOUNDARY */ - -/* Number of bits which any structure or union's size must be a - multiple of. Each structure or union's size is rounded up to a - multiple of this. - - If you do not define this macro, the default is the same as - `BITS_PER_UNIT'. */ -/* #define STRUCTURE_SIZE_BOUNDARY */ - -/* Define this macro to be the value 1 if instructions will fail to - work if given data not on the nominal alignment. If instructions - will merely go slower in that case, define this macro as 0. */ -#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 bitfield (`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 bitfield 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 bitfield 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. - - Note that if this macro is not defined, or its value is zero, some - bitfields may cross more than one alignment boundary. The - compiler can support such references if there are `insv', `extv', - and `extzv' insns that can directly reference memory. - - The other known way of making bitfields work is to define - `STRUCTURE_SIZE_BOUNDARY' as large as `BIGGEST_ALIGNMENT'. Then - every structure can be accessed with fullwords. - - Unless the machine has bitfield instructions or you define - `STRUCTURE_SIZE_BOUNDARY' that way, you must define - `PCC_BITFIELD_TYPE_MATTERS' to have a nonzero value. */ -/* #define PCC_BITFIELD_TYPE_MATTERS */ - -/* Like PCC_BITFIELD_TYPE_MATTERS except that its effect is limited to - aligning a bitfield within the structure. */ -/* #define BITFIELD_NBYTES_LIMITED */ - -/* Define this macro as an expression for the overall size of a - structure (given by STRUCT as a tree node) when the size computed - from the fields is SIZE and the alignment is ALIGN. - - The default is to round SIZE up to a multiple of ALIGN. */ -/* #define ROUND_TYPE_SIZE(STRUCT, SIZE, ALIGN) */ - -/* Define this macro as an expression for the alignment of a structure - (given by STRUCT as a tree node) if the alignment computed in the - usual way is COMPUTED and the alignment explicitly specified was - SPECIFIED. - - The default is to use SPECIFIED if it is larger; otherwise, use - the smaller of COMPUTED and `BIGGEST_ALIGNMENT' */ -/* #define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) */ - -/* An integer expression for the size in bits of the largest integer - machine mode that should actually be used. All integer machine - modes of this size or smaller can be used for structures and - unions with the appropriate sizes. If this macro is undefined, - `GET_MODE_BITSIZE (DImode)' is assumed. */ -/* #define MAX_FIXED_MODE_SIZE */ - -/* A C statement to validate the value VALUE (of type `double') for - mode MODE. This means that you check whether VALUE fits within - the possible range of values for mode MODE on this target machine. - The mode MODE is always a mode of class `MODE_FLOAT'. OVERFLOW - is nonzero if the value is already known to be out of range. - - If VALUE is not valid or if OVERFLOW is nonzero, you should set - OVERFLOW to 1 and then assign some valid value to VALUE. Allowing - an invalid value to go through the compiler can produce incorrect - assembler code which may even cause Unix assemblers to crash. - - This macro need not be defined if there is no work for it to do. */ -/* #define CHECK_FLOAT_VALUE(MODE, VALUE, OVERFLOW) */ - -/* A code distinguishing the floating point format of the target - machine. There are three defined values: - - `IEEE_FLOAT_FORMAT' - This code indicates IEEE floating point. It is the default; - there is no need to define this macro when the format is IEEE. - - `VAX_FLOAT_FORMAT' - This code indicates the peculiar format used on the Vax. - - `UNKNOWN_FLOAT_FORMAT' - This code indicates any other format. - - The value of this macro is compared with `HOST_FLOAT_FORMAT' - (*note Config::.) to determine whether the target machine has the - same format as the host machine. If any other formats are - actually in use on supported machines, new codes should be defined - for them. - - The ordering of the component words of floating point values - stored in memory is controlled by `FLOAT_WORDS_BIG_ENDIAN' for the - target machine and `HOST_FLOAT_WORDS_BIG_ENDIAN' for the host. */ -#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT - - -/* Layout of Source Language Data Types */ - -/* Width of a pointer, in bits. You must specify a value no wider - than the width of `Pmode'. If it is not equal to the width of - `Pmode', you must define `POINTERS_EXTEND_UNSIGNED'. */ -#define POINTER_SIZE 16 - -/* A C expression whose value is nonzero if pointers that need to be - extended from being `POINTER_SIZE' bits wide to `Pmode' are - sign-extended and zero if they are zero-extended. - - You need not define this macro if the `POINTER_SIZE' is equal to - the width of `Pmode'. */ -#define POINTERS_EXTEND_UNSIGNED 1 - -/* A C expression for the size in bits of the type `int' on the - target machine. If you don't define this, the default is one word. */ -#define INT_TYPE_SIZE (TARGET_INT32 ? 32 : 16) - -/* Maximum number for the size in bits of the type `int' on the target - machine. If this is undefined, the default is `INT_TYPE_SIZE'. - Otherwise, it is the constant value that is the largest value that - `INT_TYPE_SIZE' can have at run-time. This is used in `cpp'. */ -#define MAX_INT_TYPE_SIZE 32 - -/* A C expression for the size in bits of the type `short' on the - target machine. If you don't define this, the default is half a - word. (If this would be less than one storage unit, it is rounded - up to one unit.) */ -#define SHORT_TYPE_SIZE 16 - -/* A C expression for the size in bits of the type `long' on the - target machine. If you don't define this, the default is one word. */ -#define LONG_TYPE_SIZE 32 - -/* Maximum number for the size in bits of the type `long' on the - target machine. If this is undefined, the default is - `LONG_TYPE_SIZE'. Otherwise, it is the constant value that is the - largest value that `LONG_TYPE_SIZE' can have at run-time. This is - used in `cpp'. */ -#define MAX_LONG_TYPE_SIZE 32 - -/* A C expression for the size in bits of the type `long long' on the - target machine. If you don't define this, the default is two - words. If you want to support GNU Ada on your machine, the value - of macro must be at least 64. */ -#define LONG_LONG_TYPE_SIZE 64 - -/* A C expression for the size in bits of the type `char' on the - target machine. If you don't define this, the default is one - quarter of a word. (If this would be less than one storage unit, - it is rounded up to one unit.) */ -#define CHAR_TYPE_SIZE 8 - -/* Maximum number for the size in bits of the type `char' on the - target machine. If this is undefined, the default is - `CHAR_TYPE_SIZE'. Otherwise, it is the constant value that is the - largest value that `CHAR_TYPE_SIZE' can have at run-time. This is - used in `cpp'. */ -#define MAX_CHAR_TYPE_SIZE 8 - -/* A C expression for the size in bits of the type `float' on the - target machine. If you don't define this, the default is one word. */ -#define FLOAT_TYPE_SIZE 32 - -/* A C expression for the size in bits of the type `double' on the - target machine. If you don't define this, the default is two - words. */ -#define DOUBLE_TYPE_SIZE ((TARGET_DOUBLE64) ? 64 : 32) - -/* A C expression for the size in bits of the type `long double' on - the target machine. If you don't define this, the default is two - words. */ -#define LONG_DOUBLE_TYPE_SIZE 64 - -/* An expression whose value is 1 or 0, according to whether the type - `char' should be signed or unsigned by default. The user can - always override this default with the options `-fsigned-char' and - `-funsigned-char'. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* A C expression to determine whether to give an `enum' type only as - many bytes as it takes to represent the range of possible values - of that type. A nonzero value means to do that; a zero value - means all `enum' types should be allocated like `int'. - - If you don't define the macro, the default is 0. */ -#define DEFAULT_SHORT_ENUMS 0 - -/* A C expression for a string describing the name of the data type - to use for size values. The typedef name `size_t' is defined - using the contents of the string. - - The string can contain more than one keyword. If so, separate - them with spaces, and write first any length keyword, then - `unsigned' if appropriate, and finally `int'. The string must - exactly match one of the data type names defined in the function - `init_decl_processing' in the file `c-decl.c'. You may not omit - `int' or change the order--that would cause the compiler to crash - on startup. - - If you don't define this macro, the default is `"long unsigned - int"'. - - On the D10V, ints can be either 16 or 32 bits, so we need to adjust - size_t appropriately. */ -#undef SIZE_TYPE -#define SIZE_TYPE "short unsigned int" - -/* A C expression for a string describing the name of the data type - to use for the result of subtracting two pointers. The typedef - name `ptrdiff_t' is defined using the contents of the string. See - `SIZE_TYPE' above for more information. - - If you don't define this macro, the default is `"long int"'. */ -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "short int" - -/* A C expression for a string describing the name of the data type - to use for wide characters. The typedef name `wchar_t' is defined - using the contents of the string. See `SIZE_TYPE' above for more - information. - - If you don't define this macro, the default is `"int"'. */ -#undef WCHAR_TYPE -#define WCHAR_TYPE "short unsigned int" - -/* A C expression for the size in bits of the data type for wide - characters. This is used in `cpp', which cannot make use of - `WCHAR_TYPE'. */ -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 - -/* Maximum number for the size in bits of the data type for wide - characters. If this is undefined, the default is - `WCHAR_TYPE_SIZE'. Otherwise, it is the constant value that is the - largest value that `WCHAR_TYPE_SIZE' can have at run-time. This is - used in `cpp'. */ -#define MAX_WCHAR_TYPE_SIZE 16 - -/* Define results of standard character escape sequences. */ -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - - -/* Basic Characteristics of Registers */ - -/* Return true if a value is inside a range */ -#define IN_RANGE_P(VALUE, LOW, HIGH) \ - (((unsigned)((VALUE) - (LOW))) <= ((unsigned)((HIGH) - (LOW)))) - -/* First/last general purpose registers */ -#define GPR_FIRST 0 -#define GPR_LAST 15 -#define GPR_ZERO_REGNUM (GPR_FIRST + 14) /* register that holds 0 */ -#define GPR_P(REGNO) IN_RANGE_P (REGNO, GPR_FIRST, GPR_LAST) -#define GPR_OR_PSEUDO_P(REGNO) (GPR_P (REGNO) || REGNO >= FIRST_PSEUDO_REGISTER) - -/* Registers arguments are passed in */ -#define ARG_FIRST (GPR_FIRST + 0) -#define ARG_LAST (GPR_FIRST + 3) -#define RETURN_REGNUM ARG_FIRST - -/* Register pair to save accumulators in */ -#define SAVE_ACC_REGNUM (GPR_FIRST + 12) - -/* Register to save accumulator guard digits in */ -#define SAVE_GUARD_REGNUM (GPR_FIRST + 5) - -/* Even/odd registers for multiword items */ -#define GPR_EVEN_P(REGNO) (GPR_P(REGNO) && ((((REGNO) - GPR_FIRST) & 1) == 0)) -#define GPR_ODD_P(REGNO) (GPR_P(REGNO) && ((((REGNO) - GPR_FIRST) & 1) != 0)) - -/* First/last control registers */ -#define CR_FIRST 16 -#define CR_LAST 31 -#define CR_P(REGNO) IN_RANGE_P (REGNO, CR_FIRST, CR_LAST) - -#define REPEAT_REGNUM (CR_FIRST + 7) - -/* First/last accumulator registers */ -#define ACCUM_FIRST 32 -#define ACCUM_LAST 33 -#define ACCUM_P(REGNO) IN_RANGE_P (REGNO, ACCUM_FIRST, ACCUM_LAST) - -/* Argument pointer pseudo register */ -#define AP_FIRST 34 - -/* Condition/carry code 'registers'. We ignore the fact that these - are actually stored in CR0. */ -#define CC_FIRST 35 -#define CC_LAST 37 -#define CC_P(REGNO) IN_RANGE_P (REGNO, CC_FIRST, CC_LAST) - -#define F0_REGNUM (CC_FIRST + 0) -#define F1_REGNUM (CC_FIRST + 1) -#define CARRY_REGNUM (CC_FIRST + 2) - -/* Number of hardware registers known to the compiler. They receive - numbers 0 through `FIRST_PSEUDO_REGISTER-1'; thus, the first - pseudo register's number really is assigned the number - `FIRST_PSEUDO_REGISTER'. */ -#define FIRST_PSEUDO_REGISTER 38 - -/* An initializer that says which registers are used for fixed - purposes all throughout the compiled code and are therefore not - available for general allocation. These would include the stack - pointer, the frame pointer (except on machines where that can be - used as a general register when no frame pointer is needed), the - program counter on machines where that is considered one of the - addressable registers, and any other numbered register with a - standard use. - - This information is expressed as a sequence of numbers, separated - by commas and surrounded by braces. The Nth number is 1 if - register N is fixed, 0 otherwise. - - The table initialized from this macro, and the table initialized by - the following one, may be overridden at run time either - automatically, by the actions of the macro - `CONDITIONAL_REGISTER_USAGE', or by the user with the command - options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'. */ -#define FIXED_REGISTERS \ -{ \ - 0, /* r0 */ 0, /* r1 */ 0, /* r2 */ 0, /* r3 */ \ - 0, /* r4 */ 0, /* r5 */ 0, /* r6 */ 0, /* r7 */ \ - 0, /* r8 */ 0, /* r9 */ 0, /* r10 */ 0, /* r11 */ \ - 0, /* r12 */ 0, /* r13 */ 1, /* r14 */ 1, /* r15 */ \ - 1, /* cr0 */ 1, /* cr1 */ 1, /* cr2 */ 1, /* cr3 */ \ - 1, /* cr4 */ 1, /* cr5 */ 1, /* cr6 */ 1, /* cr7 */ \ - 1, /* cr8 */ 1, /* cr9 */ 1, /* cr10 */ 1, /* cr11 */ \ - 1, /* cr12 */ 1, /* cr13 */ 1, /* cr14 */ 1, /* cr15 */ \ - 1, /* a0 */ 1, /* a1 */ \ - 1, /* ap */ \ - 1, /* f0 */ 1, /* f1 */ 1, /* c */ \ -} - -/* Like `FIXED_REGISTERS' but has 1 for each register that is - clobbered (in general) by function calls as well as for fixed - registers. This macro therefore identifies the registers that are - not available for general allocation of values that must live - across function calls. - - If a register has 0 in `CALL_USED_REGISTERS', the compiler - automatically saves it on function entry and restores it on - function exit, if the register is used within the function. */ -#define CALL_USED_REGISTERS \ -{ \ - 1, /* r0 */ 1, /* r1 */ 1, /* r2 */ 1, /* r3 */ \ - 1, /* r4 */ 1, /* r5 */ 0, /* r6 */ 0, /* r7 */ \ - 0, /* r8 */ 0, /* r9 */ 0, /* r10 */ 0, /* r11 */ \ - 1, /* r12 */ 1, /* r13 */ 1, /* r14 */ 1, /* r15 */ \ - 1, /* cr0 */ 1, /* cr1 */ 1, /* cr2 */ 1, /* cr3 */ \ - 1, /* cr4 */ 1, /* cr5 */ 1, /* cr6 */ 1, /* cr7 */ \ - 1, /* cr8 */ 1, /* cr9 */ 1, /* cr10 */ 1, /* cr11 */ \ - 1, /* cr12 */ 1, /* cr13 */ 1, /* cr14 */ 1, /* cr15 */ \ - 1, /* a0 */ 1, /* a1 */ \ - 1, /* ap */ \ - 1, /* f0 */ 1, /* f1 */ 1, /* c */ \ -} - -/* Zero or more C statements that may conditionally modify two - variables `fixed_regs' and `call_used_regs' (both of type `char - []') after they have been initialized from the two preceding - macros. - - This is necessary in case the fixed or call-clobbered registers - depend on target flags. */ -#define CONDITIONAL_REGISTER_USAGE \ -do \ - { \ - if (TARGET_ACCUM) \ - { \ - int i; \ - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) \ - fixed_regs[i] = call_used_regs[i] = 0; \ - } \ - } \ -while (0) - -/* If this macro is defined and has a nonzero value, it means that - `setjmp' and related functions fail to save the registers, or that - `longjmp' fails to restore them. To compensate, the compiler - avoids putting variables in registers in functions that use - `setjmp'. */ -/* #define NON_SAVING_SETJMP */ - - -/* Order of allocating registers */ - -/* If defined, an initializer for a vector of integers, containing the - numbers of hard registers in the order in which GNU CC should - prefer to use them (from most preferred to least). - - If this macro is not defined, registers are used lowest numbered - first (all else being equal). - - One use of this macro is on machines where the highest numbered - registers must always be saved and the save-multiple-registers - instruction supports only sequences of consecutive registers. On - such machines, define `REG_ALLOC_ORDER' to be an initializer that - lists the highest numbered allocatable register first. - - On the d10v, we save some time by putting the fixed registers at - the end of the list. Also, we put the odd registers whose even - register is fixed before the even/odd register pairs. */ -#define REG_ALLOC_ORDER \ -{ \ - /* Volatile GPR registers */ \ - GPR_FIRST+0, \ - GPR_FIRST+1, \ - GPR_FIRST+2, \ - GPR_FIRST+3, \ - GPR_FIRST+4, \ - GPR_FIRST+5, \ - GPR_FIRST+12, \ - GPR_FIRST+13, \ - \ - /* Callee preserved GPR registers */ \ - GPR_FIRST+6, \ - GPR_FIRST+7, \ - GPR_FIRST+8, \ - GPR_FIRST+9, \ - GPR_FIRST+10, \ - GPR_FIRST+11, \ - \ - /* Accumulators */ \ - ACCUM_FIRST+0, \ - ACCUM_FIRST+1, \ - \ - /* Repeat count register */ \ - REPEAT_REGNUM, \ - \ - /* Condition code, carry registers */ \ - F0_REGNUM, \ - F1_REGNUM, \ - CARRY_REGNUM, \ - \ - /* Fixed registers */ \ - GPR_FIRST+14, /* zero register */ \ - GPR_FIRST+15, /* stack pointer */ \ - CR_FIRST+0, \ - CR_FIRST+1, \ - CR_FIRST+2, \ - CR_FIRST+3, \ - CR_FIRST+4, \ - CR_FIRST+5, \ - CR_FIRST+6, \ - CR_FIRST+8, \ - CR_FIRST+9, \ - CR_FIRST+10, \ - CR_FIRST+11, \ - CR_FIRST+12, \ - CR_FIRST+13, \ - CR_FIRST+14, \ - CR_FIRST+15, \ - ARG_POINTER_REGNUM, \ -} - -/* A C statement (sans semicolon) to choose the order in which to - allocate hard registers for pseudo-registers local to a basic - block. - - Store the desired register order in the array `reg_alloc_order'. - Element 0 should be the register to allocate first; element 1, the - next register; and so on. - - The macro body should not assume anything about the contents of - `reg_alloc_order' before execution of the macro. - - On most machines, it is not necessary to define this macro. */ -/* #define ORDER_REGS_FOR_LOCAL_ALLOC */ - - -/* How values fit in registers */ - -/* A C expression for the number of consecutive hard registers, - starting at register number REGNO, required to hold a value of mode - MODE. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((ACCUM_P (REGNO)) \ - ? ((GET_MODE_SIZE (MODE) + 4 - 1) / 4) \ - : ((GET_MODE_SIZE (MODE) + 2 - 1) / 2)) - -/* A C expression that is nonzero if it is permissible to store a - value of mode MODE in hard register number REGNO (or in several - registers starting with that one). */ - -extern unsigned char hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; -#define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok[ (int)MODE ][ REGNO ] - -/* A C expression that is nonzero if it is desirable to choose - register allocation so as to avoid move instructions between a - value of mode MODE1 and a value of mode MODE2. - - If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, - MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1, - MODE2)' must be zero. */ - -extern unsigned char modes_tieable_p[]; -#define MODES_TIEABLE_P(MODE1, MODE2) \ - modes_tieable_p[ (((int)(MODE1)) * (NUM_MACHINE_MODES)) + (int)(MODE2) ] - - -/* Register classes */ - -/* An enumeral type that must be defined with all the register class - names as enumeral values. `NO_REGS' must be first. `ALL_REGS' - must be the last register class, followed by one more enumeral - value, `LIM_REG_CLASSES', which is not a register class but rather - tells how many classes there are. - - Each register class has a number, which is the value of casting - the class name to type `int'. The number serves as an index in - many of the tables described below. - - All things being equal, the register allocator prefers the higher - register class, so put all of the general registers higher than - the accumulators and CRs. */ - -enum reg_class -{ - NO_REGS, - REPEAT_REGS, - CR_REGS, - ACCUM_REGS, - F0_REGS, - F1_REGS, - F_REGS, - CARRY_REGS, - CC_REGS, - ARG0_REGS, - ARG1_REGS, - ARG2_REGS, - ARG3_REGS, - RETURN_REGS, - EVEN_REGS, - GENERAL_REGS, - ALL_REGS, - LIM_REG_CLASSES -}; - - -/* The number of distinct register classes */ -#define N_REG_CLASSES ((int) LIM_REG_CLASSES) - -/* An initializer containing the names of the register classes as C - string constants. These names are used in writing some of the - debugging dumps. */ -#define REG_CLASS_NAMES \ -{ \ - "NO_REGS", \ - "REPEAT_REGS", \ - "CR_REGS", \ - "ACCUM_REGS", \ - "F0_REGS", \ - "F1_REGS", \ - "F_REGS", \ - "CARRY_REGS", \ - "CC_REGS", \ - "ARG0_REGS", \ - "ARG1_REGS", \ - "ARG2_REGS", \ - "ARG3_REGS", \ - "RETURN_REGS", \ - "EVEN_REGS", \ - "GENERAL_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 }, /* NO_REGS */ \ - { 0x00800000, 0x00000000 }, /* REPEAT_REGS */ \ - { 0xffff0000, 0x00000000 }, /* CR_REGS */ \ - { 0x00000000, 0x00000003 }, /* ACCUM_REGS */ \ - { 0x00000000, 0x00000008 }, /* F0_REGS */ \ - { 0x00000000, 0x00000010 }, /* F1_REGS */ \ - { 0x00000000, 0x00000018 }, /* F_REGS */ \ - { 0x00000000, 0x00000020 }, /* CARRY_REGS */ \ - { 0x00000000, 0x00000038 }, /* CC_REGS */ \ - { 0x00000001, 0x00000000 }, /* ARG0_REGS */ \ - { 0x00000002, 0x00000000 }, /* ARG1_REGS */ \ - { 0x00000004, 0x00000000 }, /* ARG2_REGS */ \ - { 0x00000008, 0x00000000 }, /* ARG3_REGS */ \ - { 0x00002000, 0x00000000 }, /* R13_REGS */ \ - { 0x0000ffff, 0x00000000 }, /* EVEN_REGS */ \ - { 0x0000ffff, 0x00000004 }, /* GENERAL_REGS */ \ - { 0xffffffff, 0x0000001f }, /* ALL_REGS */ \ -} - -/* A C expression whose value is a register class containing hard - register REGNO. In general there is more than one such class; - choose a class which is "minimal", meaning that no smaller class - also contains the register. */ - -extern enum reg_class regno_reg_class[]; -#define REGNO_REG_CLASS(REGNO) regno_reg_class[ (REGNO) ] - -/* A macro whose definition is the name of the class to which a valid - base register must belong. A base register is one used in an - address which is the register value plus a displacement. */ -#define BASE_REG_CLASS GENERAL_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 GENERAL_REGS - -/* A C expression which defines the machine-dependent operand - constraint letters for register classes. If CHAR is such a - letter, the value should be the register class corresponding to - it. Otherwise, the value should be `NO_REGS'. The register - letter `r', corresponding to class `GENERAL_REGS', will not be - passed to this macro; you do not need to handle it. */ - -extern enum reg_class reg_class_from_letter[]; -#define REG_CLASS_FROM_LETTER(CHAR) reg_class_from_letter[ CHAR ] - -/* A C expression which is nonzero if register number NUM is suitable - for use as a base register in operand addresses. It may be either - a suitable hard register or a pseudo register that has been - allocated such a hard register. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_BASE_P(REGNO) \ -((REGNO) < FIRST_PSEUDO_REGISTER \ - ? GPR_P (REGNO) || (REGNO) == ARG_POINTER_REGNUM \ - : (reg_renumber[REGNO] >= 0 && GPR_P (reg_renumber[REGNO]))) - -/* A C expression which is nonzero if register number NUM is suitable - for use as an index register in operand addresses. It may be - either a suitable hard register or a pseudo register that has been - allocated such a hard register. - - The difference between an index register and a base register is - that the index register may be scaled. If an address involves the - sum of two registers, neither one of them scaled, then either one - may be labeled the "base" and the other the "index"; but whichever - labeling is used must fit the machine's constraints of which - registers may serve in each capacity. The compiler will try both - labelings, looking for one that is valid, and will reload one or - both registers only if neither labeling works. */ -#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P (REGNO) - -/* A C expression that places additional restrictions on the register - class to use when it is necessary to copy value X into a register - in class CLASS. The value is a register class; perhaps CLASS, or - perhaps another, smaller class. On many machines, the following - definition is safe: - - #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS - - Sometimes returning a more restrictive class makes better code. - For example, on the 68000, when X is an integer constant that is - in range for a `moveq' instruction, the value of this macro is - always `DATA_REGS' as long as CLASS includes the data registers. - Requiring a data register guarantees that a `moveq' will be used. - - If X is a `const_double', by returning `NO_REGS' you can force X - into a memory constant. This is useful on certain machines where - immediate floating values cannot be loaded into certain kinds of - registers. */ -#define PREFERRED_RELOAD_CLASS(X, CLASS) \ - ((CLASS == EVEN_REGS || CLASS == ACCUM_REGS) ? EVEN_REGS : GENERAL_REGS) - -/* Like `PREFERRED_RELOAD_CLASS', but for output reloads instead of - input reloads. If you don't define this macro, the default is to - use CLASS, unchanged. */ -/* #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) */ - -/* A C expression that places additional restrictions on the register - class to use when it is necessary to be able to hold a value of - mode MODE in a reload register for which class CLASS would - ordinarily be used. - - Unlike `PREFERRED_RELOAD_CLASS', this macro should be used when - there are certain modes that simply can't go in certain reload - classes. - - The value is a register class; perhaps CLASS, or perhaps another, - smaller class. - - Don't define this macro unless the target machine has limitations - which require the macro to do something nontrivial. */ -/* #define LIMIT_RELOAD_CLASS (MODE, CLASS) */ - -/* Many machines have some registers that cannot be copied directly - to or from memory or even from other types of registers. An - example is the `MQ' register, which on most machines, can only be - copied to or from general registers, but not memory. Some - machines allow copying all registers to and from memory, but - require a scratch register for stores to some memory locations - (e.g., those with symbolic address on the RT, and those with - certain symbolic address on the Sparc when compiling PIC). In - some cases, both an intermediate and a scratch register are - required. - - You should define these macros to indicate to the reload phase - that it may need to allocate at least one register for a reload in - addition to the register to contain the data. Specifically, if - copying X to a register CLASS in MODE requires an intermediate - register, you should define `SECONDARY_INPUT_RELOAD_CLASS' to - return the largest register class all of whose registers can be - used as intermediate registers or scratch registers. - - If copying a register CLASS in MODE to X requires an intermediate - or scratch register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be - defined to return the largest register class required. If the - requirements for input and output reloads are the same, the macro - `SECONDARY_RELOAD_CLASS' should be used instead of defining both - macros identically. - - The values returned by these macros are often `GENERAL_REGS'. - Return `NO_REGS' if no spare register is needed; i.e., if X can be - directly copied to or from a register of CLASS in MODE without - requiring a scratch register. Do not define this macro if it - would always return `NO_REGS'. - - If a scratch register is required (either with or without an - intermediate register), you should define patterns for - `reload_inM' or `reload_outM', as required (*note Standard - Names::.. These patterns, which will normally be implemented with - a `define_expand', should be similar to the `movM' patterns, - except that operand 2 is the scratch register. - - Define constraints for the reload register and scratch register - that contain a single register class. If the original reload - register (whose class is CLASS) can meet the constraint given in - the pattern, the value returned by these macros is used for the - class of the scratch register. Otherwise, two additional reload - registers are required. Their classes are obtained from the - constraints in the insn pattern. - - X might be a pseudo-register or a `subreg' of a pseudo-register, - which could either be in a hard register or in memory. Use - `true_regnum' to find out; it will return -1 if the pseudo is in - memory and the hard register number if it is in a register. - - These macros should not be used in the case where a particular - class of registers can only be copied to memory and not to another - class of registers. In that case, secondary reload registers are - not needed and would not be helpful. Instead, a stack location - must be used to perform the copy and the `movM' pattern should use - memory as a intermediate storage. This case often occurs between - floating-point and general registers. */ -#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \ - ((CLASS) == ACCUM_REGS ? EVEN_REGS \ - : ((CLASS) == GENERAL_REGS || (CLASS) == EVEN_REGS) ? NO_REGS \ - : GENERAL_REGS) - -/* #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) */ -/* #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) */ - -/* 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 non-zero if - objects of mode M 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. */ -/* #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, M) */ - -/* Normally when `SECONDARY_MEMORY_NEEDED' is defined, the compiler - allocates a stack slot for a memory location needed for register - copies. If this macro is defined, the compiler instead uses the - memory location defined by this macro. - - Do not define this macro if you do not define - `SECONDARY_MEMORY_NEEDED'. */ -/* #define SECONDARY_MEMORY_NEEDED_RTX(MODE) */ - -/* When the compiler needs a secondary memory location to copy - between two registers of mode MODE, it normally allocates - sufficient memory to hold a quantity of `BITS_PER_WORD' bits and - performs the store and load operations in a mode that many bits - wide and whose class is the same as that of MODE. - - This is right thing to do on most machines because it ensures that - all bits of the register are copied and prevents accesses to the - registers in a narrower mode, which some machines prohibit for - floating-point registers. - - However, this default behavior is not correct on some machines, - such as the DEC Alpha, that store short integers in floating-point - registers differently than in integer registers. On those - machines, the default widening will not work correctly and you - must define this macro to suppress that widening in some cases. - See the file `alpha.h' for details. - - Do not define this macro if you do not define - `SECONDARY_MEMORY_NEEDED' or if widening MODE to a mode that is - `BITS_PER_WORD' bits wide is correct for your machine. */ -/* #define SECONDARY_MEMORY_NEEDED_MODE(MODE) */ - -/* Normally the compiler avoids choosing registers that have been - explicitly mentioned in the rtl as spill registers (these - registers are normally those used to pass parameters and return - values). However, some machines have so few registers of certain - classes that there would not be enough registers to use as spill - registers if this were done. - - Define `SMALL_REGISTER_CLASSES' on these machines. When it is - defined, the compiler allows registers explicitly used in the rtl - to be used as spill registers but avoids extending the lifetime of - these registers. - - It is always safe to define this macro, but if you unnecessarily - define it, you will reduce the amount of optimizations that can be - performed in some cases. If you do not define this macro when it - is required, the compiler will run out of spill registers and - print a fatal error message. For most machines, you should not - define this macro. */ -#define SMALL_REGISTER_CLASSES 1 - -/* A C expression whose value is nonzero if pseudos that have been - assigned to registers of class CLASS would likely be spilled - because registers of CLASS are needed for spill registers. - - The default value of this macro returns 1 if CLASS has exactly one - register and zero otherwise. On most machines, this default - should be used. Only define this macro to some other expression - if pseudo allocated by `local-alloc.c' end up in memory because - their hard registers were needed for spill registers. If this - macro returns nonzero for those classes, those pseudos will only - be allocated by `global.c', which knows how to reallocate the - pseudo to another register. If there would not be another - register available for reallocation, you should not change the - definition of this macro since the only effect of such a - definition would be to slow down register allocation. */ -/* #define CLASS_LIKELY_SPILLED_P(CLASS) */ - -/* A C expression for the maximum number of consecutive registers of - class CLASS needed to hold a value of mode MODE. - - This is closely related to the macro `HARD_REGNO_NREGS'. In fact, - the value of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be - the maximum value of `HARD_REGNO_NREGS (REGNO, MODE)' for all - REGNO values in the class CLASS. - - This macro helps control the handling of multiple-word values in - the reload pass. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ -(((CLASS) == ACCUM_REGS) \ - ? ((GET_MODE_SIZE (MODE) + 4 - 1) / 4) \ - : ((GET_MODE_SIZE (MODE) + 2 - 1) / 2)) - -/* If defined, a C expression for a class that contains registers - which the compiler must always access in a mode that is the same - size as the mode in which it loaded the register. - - For the example, loading 32-bit integer or floating-point objects - into floating-point registers on the Alpha extends them to 64-bits. - Therefore loading a 64-bit object and then storing it as a 32-bit - object does not store the low-order 32-bits, as would be the case - for a normal register. Therefore, `alpha.h' defines this macro as - `FLOAT_REGS'. */ -/* #define CLASS_CANNOT_CHANGE_SIZE */ - -/* A C expression that defines the machine-dependent operand - constraint letters that specify particular ranges of integer - values. If C is one of those letters, the expression should check - that VALUE, an integer, is in the appropriate range and return 1 - if so, 0 otherwise. If C is not one of those letters, the value - should be 0 regardless of VALUE. - - 'I' is for 4-bit unsigned constants (imm4), note bit pattern 0 == 16. - 'J' is for ~ (1 << n), for n <= 15 - 'K' is for 32-bit constants with the lower 8 bits in the range -8..7. - 'L' is for 4-bit signed constants (imm4). - 'M' is for 16-bit non-negative constants. - 'N' is for 4-bit negative unsigned constants (imm4), note bit pattern 0 == 16. - 'O' is zero. - 'P' is for (1 << n), where n <= 15. */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'I' ? IN_RANGE_P (VALUE, 1, 16) \ - : (C) == 'J' ? IN_RANGE_P (exact_log2 (~ (VALUE)), 0, 15) \ - : (C) == 'K' ? IN_RANGE_P (SIGN_EXTEND_SHORT (VALUE), -8, 7) \ - : (C) == 'L' ? IN_RANGE_P (VALUE, -8, 7) \ - : (C) == 'M' ? IN_RANGE_P (VALUE, 0, 32767) \ - : (C) == 'N' ? IN_RANGE_P (VALUE, -16, -1) \ - : (C) == 'O' ? ((VALUE) == 0) \ - : (C) == 'P' ? IN_RANGE_P (exact_log2 (VALUE), 0, 15) \ - : 0) - -/* A C expression that defines the machine-dependent operand - constraint letters that specify particular ranges of - `const_double' values. - - If C is one of those letters, the expression should check that - VALUE, an RTX of code `const_double', is in the appropriate range - and return 1 if so, 0 otherwise. If C is not one of those - letters, the value should be 0 regardless of VALUE. - - `const_double' is used for all floating-point constants and for - `DImode' fixed-point constants. A given letter can accept either - or both kinds of values. It can use `GET_MODE' to distinguish - between these kinds. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'G' ? (CONST_DOUBLE_LOW (VALUE) == 0 && CONST_DOUBLE_HIGH (VALUE) == 0) \ - : 0) - -/* A C expression that defines the optional machine-dependent - constraint letters that can be used to segregate specific types of - operands, usually memory references, for the target machine. - Normally this macro will not be defined. If it is required for a - particular target machine, it should return 1 if VALUE corresponds - to the operand type represented by the constraint letter C. If C - is not defined as an extra constraint, the value returned should - be 0 regardless of VALUE. - - 'Q' is for memory references that are short. */ - -#define EXTRA_CONSTRAINT(VALUE, C) \ - ((C) == 'Q' ? short_memory_operand (VALUE, GET_MODE (VALUE)) \ - : 0) - - -/* Stack layout */ - -/* Structure used to define the d10v stack */ -typedef struct d10v_stack { - int varargs_p; /* whether this is a varargs function */ - int varargs_size; /* size to hold varargs args passed in regs */ - int vars_size; /* variable save area size */ - int parm_size; /* outgoing parameter size */ - int gpr_size; /* size of saved GPR registers */ - int accum_size; /* size of saved ACCUM registers */ - int total_size; /* total bytes allocated for stack */ - /* which registers are to be saved */ - unsigned char save_p[FIRST_PSEUDO_REGISTER]; -} d10v_stack_t; - -/* Define this macro if pushing a word onto the stack moves the stack - pointer to a smaller address. - - When we say, "define this macro if ...," it means that the - compiler checks this macro only with `#ifdef' so the precise - definition used does not matter. */ - -#define STACK_GROWS_DOWNWARD 1 - -/* Define this macro if the addresses of local variable slots are at - negative offsets from the frame pointer. - - On the D10v, we grow upwards, from the area before the outgoing - arguments. */ -/* #define FRAME_GROWS_DOWNWARD */ - -/* Define this macro if successive arguments to a function occupy - decreasing addresses on the stack. */ -/* #define ARGS_GROW_DOWNWARD */ - -/* Offset from the frame pointer to the first local variable slot to - be allocated. - - If `FRAME_GROWS_DOWNWARD', find the next slot's offset by - subtracting the first slot's length from `STARTING_FRAME_OFFSET'. - Otherwise, it is found by adding the length of the first slot to - the value `STARTING_FRAME_OFFSET'. - - On the D10V, the frame pointer is the same as the stack pointer, - except for dynamic allocations. So we start after the outgoing - parameter area. */ - -#define STARTING_FRAME_OFFSET \ - (D10V_ALIGN (current_function_outgoing_args_size, 2)) - -/* Offset from the stack pointer register to the first location at - which outgoing arguments are placed. If not specified, the - default value of zero is used. This is the proper value for most - machines. - - If `ARGS_GROW_DOWNWARD', this is the offset to the location above - the first location at which outgoing arguments are placed. */ -/* #define STACK_POINTER_OFFSET */ - -/* Offset from the argument pointer register to the first argument's - address. On some machines it may depend on the data type of the - function. - - If `ARGS_GROW_DOWNWARD', this is the offset to the location above - the first argument's address. */ -#define FIRST_PARM_OFFSET(FUNDECL) 0 - -/* Offset from the stack pointer register to an item dynamically - allocated on the stack, e.g., by `alloca'. - - The default value for this macro is `STACK_POINTER_OFFSET' plus the - length of the outgoing arguments. The default is correct for most - machines. See `function.c' for details. */ -/* #define STACK_DYNAMIC_OFFSET (FUNDECL) */ - -/* A C expression whose value is RTL representing the address in a - stack frame where the pointer to the caller's frame is stored. - Assume that FRAMEADDR is an RTL expression for the address of the - stack frame itself. - - If you don't define this macro, the default is to return the value - of FRAMEADDR--that is, the stack frame address is also the address - of the stack word that points to the previous frame. */ -/* #define DYNAMIC_CHAIN_ADDRESS (FRAMEADDR) */ - -/* If defined, a C expression that produces the machine-specific code - to setup the stack so that arbitrary frames can be accessed. For - example, on the Sparc, we must flush all of the register windows - to the stack before we can access arbitrary stack frames. This - macro will seldom need to be defined. */ -/* #define SETUP_FRAME_ADDRESSES() */ - -/* A C expression whose value is RTL representing the value of the - return address for the frame COUNT steps up from the current frame. - FRAMEADDR is the frame pointer of the COUNT frame, or the frame - pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' - is defined. */ -/* #define RETURN_ADDR_RTX (COUNT, FRAMEADDR) */ - -/* Define this if the return address of a particular stack frame is - accessed from the frame pointer of the previous stack frame. */ -/* #define RETURN_ADDR_IN_PREVIOUS_FRAME */ - - -/* Stack based registers */ - -/* The register number of the stack pointer register, which must also - be a fixed register according to `FIXED_REGISTERS'. On most - machines, the hardware determines which register this is. */ -#define STACK_POINTER_REGNUM (GPR_FIRST + 15) - -/* The register number of the frame pointer register, which is used to - access automatic variables in the stack frame. On some machines, - the hardware determines which register this is. On other - machines, you can choose any register you wish for this purpose. */ -#define FRAME_POINTER_REGNUM (GPR_FIRST + 11) - -/* On some machines the offset between the frame pointer and starting - offset of the automatic variables is not known until after register - allocation has been done (for example, because the saved registers - are between these two locations). On those machines, define - `FRAME_POINTER_REGNUM' the number of a special, fixed register to - be used internally until the offset is known, and define - `HARD_FRAME_POINTER_REGNUM' to be actual the hard register number - used for the frame pointer. - - You should define this macro only in the very rare circumstances - when it is not possible to calculate the offset between the frame - pointer and the automatic variables until after register - allocation has been completed. When this macro is defined, you - must also indicate in your definition of `ELIMINABLE_REGS' how to - eliminate `FRAME_POINTER_REGNUM' into either - `HARD_FRAME_POINTER_REGNUM' or `STACK_POINTER_REGNUM'. - - Do not define this macro if it would be the same as - `FRAME_POINTER_REGNUM'. */ -/* #define HARD_FRAME_POINTER_REGNUM */ - -/* The register number of the arg pointer register, which is used to - access the function's argument list. On some machines, this is - the same as the frame pointer register. On some machines, the - hardware determines which register this is. On other machines, - you can choose any register you wish for this purpose. If this is - not the same register as the frame pointer register, then you must - mark it as a fixed register according to `FIXED_REGISTERS', or - arrange to be able to eliminate it (*note Elimination::.). */ -#define ARG_POINTER_REGNUM AP_FIRST - -/* The register number of the return address pointer register, which - is used to access the current function's return address from the - stack. On some machines, the return address is not at a fixed - offset from the frame pointer or stack pointer or argument - pointer. This register can be defined to point to the return - address on the stack, and then be converted by `ELIMINABLE_REGS' - into either the frame pointer or stack pointer. - - Do not define this macro unless there is no other way to get the - return address from the stack. */ -/* #define RETURN_ADDRESS_POINTER_REGNUM */ - -/* Register numbers used for passing a function's static chain - pointer. - - The static chain register need not be a fixed register. - - If the static chain is passed in memory, these macros should not be - defined; instead, the next two macros should be defined. */ -#define STATIC_CHAIN_REGNUM (GPR_FIRST + 4) - -/* If the static chain is passed in memory, these macros provide rtx - giving `mem' expressions that denote where they are stored. - `STATIC_CHAIN' and `STATIC_CHAIN_INCOMING' give the locations as - seen by the calling and called functions, respectively. Often the - former will be at an offset from the stack pointer and the latter - at an offset from the frame pointer. - - The variables `stack_pointer_rtx', `frame_pointer_rtx', and - `arg_pointer_rtx' will have been initialized prior to the use of - these macros and should be used to refer to those items. - - If the static chain is passed in a register, the two previous - macros should be defined instead. */ -/* #define STATIC_CHAIN_INCOMING */ -/* #define STATIC_CHAIN */ - -/* Local d10v return link register number */ -#define RETURN_ADDRESS_REGNUM (GPR_FIRST + 13) - - -/* Eliminating the frame and arg pointers */ - -/* A C expression which is nonzero if a function must have and use a - frame pointer. This expression is evaluated in the reload pass. - If its value is nonzero the function will have a frame pointer. - - The expression can in principle examine the current function and - decide according to the facts, but on most machines the constant 0 - or the constant 1 suffices. Use 0 when the machine allows code to - be generated with no frame pointer, and doing so saves some time - or space. Use 1 when there is no possible advantage to avoiding a - frame pointer. - - In certain cases, the compiler does not know how to produce valid - code without a frame pointer. The compiler recognizes those cases - and automatically gives the function a frame pointer regardless of - what `FRAME_POINTER_REQUIRED' says. You don't need to worry about - them. - - In a function that does not require a frame pointer, the frame - pointer register can be allocated for ordinary usage, unless you - mark it as a fixed register. See `FIXED_REGISTERS' for more - information. */ -#define FRAME_POINTER_REQUIRED 0 - -/* A C statement to store in the variable DEPTH-VAR the difference - between the frame pointer and the stack pointer values immediately - after the function prologue. The value would be computed from - information such as the result of `get_frame_size ()' and the - tables of registers `regs_ever_live' and `call_used_regs'. - - If `ELIMINABLE_REGS' is defined, this macro will be not be used and - need not be defined. Otherwise, it must be defined even if - `FRAME_POINTER_REQUIRED' is defined to always be true; in that - case, you may set DEPTH-VAR to anything. */ -/* #define INITIAL_FRAME_POINTER_OFFSET(DEPTH) */ - -/* If defined, this macro specifies a table of register pairs used to - eliminate unneeded registers that point into the stack frame. If - it is not defined, the only elimination attempted by the compiler - is to replace references to the frame pointer with references to - the stack pointer. - - The definition of this macro is a list of structure - initializations, each of which specifies an original and - replacement register. - - On some machines, the position of the argument pointer is not - known until the compilation is completed. In such a case, a - separate hard register must be used for the argument pointer. - This register can be eliminated by replacing it with either the - frame pointer or the argument pointer, depending on whether or not - the frame pointer has been eliminated. - - In this case, you might specify: - #define ELIMINABLE_REGS \ - {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} - - Note that the elimination of the argument pointer with the stack - pointer is specified first since that is the preferred elimination. */ - -#define ELIMINABLE_REGS \ -{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ - { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }} \ - -/* A C expression that returns non-zero if the compiler is allowed to - try to replace register number FROM-REG with register number - TO-REG. This macro need only be defined if `ELIMINABLE_REGS' is - defined, and will usually be the constant 1, since most of the - cases preventing register elimination are things that the compiler - already knows about. */ - -#define CAN_ELIMINATE(FROM, TO) \ - ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \ - ? ! frame_pointer_needed \ - : 1) - -/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It - specifies the initial difference between the specified pair of - registers. This macro must be defined if `ELIMINABLE_REGS' is - defined. */ - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ \ - d10v_stack_t *info = d10v_stack_info (); \ - \ - if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = 0; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \ - (OFFSET) = info->total_size; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = info->total_size; \ - else \ - abort (); \ -} - - -/* Define this macro if the `longjmp' function restores registers from - the stack frames, rather than from those saved specifically by - `setjmp'. Certain quantities must not be kept in registers across - a call to `setjmp' on such machines. */ -/* #define LONGJMP_RESTORE_FROM_STACK */ - - -/* Passing arguments */ - -/* 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. */ -/* #define PROMOTE_PROTOTYPES */ - -/* A C expression that is the number of bytes actually pushed onto the - stack when an instruction attempts to push NPUSHED bytes. - - If the target machine does not have a push instruction, do not - define this macro. That directs GNU CC to use an alternate - strategy: to allocate the entire argument block and then store the - arguments into it. - - On some machines, the definition - - #define PUSH_ROUNDING(BYTES) (BYTES) - - will suffice. But on other machines, instructions that appear to - push one byte actually push two bytes in an attempt to maintain - alignment. Then the definition should be - - #define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1) */ -/* #define PUSH_ROUNDING(NPUSHED) */ - -/* If defined, the maximum amount of space required for outgoing - arguments will be computed and placed into the variable - `current_function_outgoing_args_size'. No space will be pushed - onto the stack for each call; instead, the function prologue should - increase the stack frame size by this amount. - - Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is - not proper. */ -#define ACCUMULATE_OUTGOING_ARGS 1 - -/* Define this macro if functions should assume that stack space has - been allocated for arguments even when their values are passed in - registers. - - The value of this macro is the size, in bytes, of the area - reserved for arguments passed in registers for the function - represented by FNDECL. - - This space can be allocated by the caller, or be a part of the - machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says - which. */ -/* Currently, emit_library_call(,_value} always think that a definition of - REG_PARM_STACK_SPACE means that all register values need stack space, - so defining it to always 0 doesn't work; e.g. ashldi3 is affected. */ -/* #define REG_PARM_STACK_SPACE(FNDECL) 0 */ - -/* Define these macros in addition to the one above if functions might - allocate stack space for arguments even when their values are - passed in registers. These should be used when the stack space - allocated for arguments in registers is not a simple constant - independent of the function declaration. - - The value of the first macro is the size, in bytes, of the area - that we should initially assume would be reserved for arguments - passed in registers. - - The value of the second macro is the actual size, in bytes, of the - area that will be reserved for arguments passed in registers. - This takes two arguments: an integer representing the number of - bytes of fixed sized arguments on the stack, and a tree - representing the number of bytes of variable sized arguments on - the stack. - - When these macros are defined, `REG_PARM_STACK_SPACE' will only be - called for libcall functions, the current function, or for a - function being called when it is known that such stack space must - be allocated. In each case this value can be easily computed. - - When deciding whether a called function needs such stack space, - and how much space to reserve, GNU CC uses these two macros - instead of `REG_PARM_STACK_SPACE'. */ -/* #define MAYBE_REG_PARM_STACK_SPACE */ -/* #define FINAL_REG_PARM_STACK_SPACE(CONST_SIZE, VAR_SIZE) */ - -/* 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 defined, this macro controls - whether the space for these arguments counts in the value of - `current_function_outgoing_args_size'. */ -#define OUTGOING_REG_PARM_STACK_SPACE 1 - -/* Define this macro if `REG_PARM_STACK_SPACE' is defined, but the - stack parameters don't skip the area specified by it. - - Normally, when a parameter is not passed in registers, it is - placed on the stack beyond the `REG_PARM_STACK_SPACE' area. - Defining this macro suppresses this behavior and causes the - parameter to be passed on the stack in its natural location. */ -/* #define STACK_PARMS_IN_REG_PARM_AREA */ - -/* A C expression that should indicate the number of bytes of its own - arguments that a function pops on returning, or 0 if the function - pops no arguments and the caller must therefore pop them all after - the function returns. - - FUNDECL is a C variable whose value is a tree node that describes - the function in question. Normally it is a node of type - `FUNCTION_DECL' that describes the declaration of the function. - From this it is possible to obtain the DECL_MACHINE_ATTRIBUTES of - the function. - - FUNTYPE is a C variable whose value is a tree node that describes - the function in question. Normally it is a node of type - `FUNCTION_TYPE' that describes the data type of the function. - From this it is possible to obtain the data types of the value and - arguments (if known). - - When a call to a library function is being considered, FUNTYPE - will contain an identifier node for the library function. Thus, if - you need to distinguish among various library functions, you can - do so by their names. Note that "library function" in this - context means a function used to perform arithmetic, whose name is - known specially in the compiler and was not mentioned in the C - code being compiled. - - STACK-SIZE is the number of bytes of arguments passed on the - stack. If a variable number of bytes is passed, it is zero, and - argument popping will always be the responsibility of the calling - function. - - On the Vax, all functions always pop their arguments, so the - definition of this macro is STACK-SIZE. On the 68000, using the - standard calling convention, no functions pop their arguments, so - the value of the macro is always 0 in this case. But an - alternative calling convention is available in which functions - that take a fixed number of arguments pop them but other functions - (such as `printf') pop nothing (the caller pops all). When this - convention is in use, FUNTYPE is examined to determine whether a - function takes a fixed number of arguments. */ -#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACKSIZE) 0 - - -/* Function arguments */ - -/* Nonzero if we do not know how to pass TYPE solely in registers. - Values that come in registers with inconvenient padding are stored - to memory at the function start. */ - -#define MUST_PASS_IN_STACK(MODE,TYPE) \ - ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_ADDRESSABLE (TYPE))) - -/* A C expression that controls whether a function argument is passed - in a register, and which register. - - The arguments are CUM, which summarizes all the previous - arguments; MODE, the machine mode of the argument; TYPE, the data - type of the argument as a tree node or 0 if that is not known - (which happens for C support library functions); and NAMED, which - is 1 for an ordinary argument and 0 for nameless arguments that - correspond to `...' in the called function's prototype. - - The value of the expression should either be a `reg' RTX for the - hard register in which to pass the argument, or zero to pass the - argument on the stack. - - For machines like the Vax and 68000, where normally all arguments - are pushed, zero suffices as a definition. - - The usual way to make the ANSI library `stdarg.h' work on a machine - where some arguments are usually passed in registers, is to cause - nameless arguments to be passed on the stack instead. This is done - by making `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the - definition of this macro to determine if this argument is of a - type that must be passed in the stack. If `REG_PARM_STACK_SPACE' - is not defined and `FUNCTION_ARG' returns non-zero for such an - argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is - defined, the argument will be computed in the stack and then - loaded into a register. */ -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - function_arg(&CUM, MODE, TYPE, NAMED) - -/* Define this macro if the target machine has "register windows", so - that the register in which a function sees an arguments is not - necessarily the same as the one in which the caller passed the - argument. - - For such machines, `FUNCTION_ARG' computes the register in which - the caller passes the value, and `FUNCTION_INCOMING_ARG' should be - defined in a similar fashion to tell the function being called - where the arguments will arrive. - - If `FUNCTION_INCOMING_ARG' is not defined, `FUNCTION_ARG' serves - both purposes. */ -/* #define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) */ - -/* A C expression for the number of words, at the beginning of an - argument, must be put in registers. The value must be zero for - arguments that are passed entirely in registers or that are - entirely pushed on the stack. - - On some machines, certain arguments must be passed partially in - registers and partially in memory. On these machines, typically - the first N words of arguments are passed in registers, and the - rest on the stack. If a multi-word argument (a `double' or a - structure) crosses that boundary, its first few words must be - passed in registers and the rest must be pushed. This macro tells - the compiler when this occurs, and how many of the words should go - in registers. - - `FUNCTION_ARG' for these arguments should return the first - register to be used by the caller for this argument; likewise - `FUNCTION_INCOMING_ARG', for the called function. */ -/* #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) */ - -/* If defined, a C expression that indicates when it is the called - function's responsibility to make a copy of arguments passed by - invisible reference. Normally, the caller makes a copy and passes - the address of the copy to the routine being called. When - FUNCTION_ARG_CALLEE_COPIES is defined and is nonzero, the caller - does not make a copy. Instead, it passes a pointer to the "live" - value. The called function must not modify this value. If it can - be determined that the value won't be modified, it need not make a - copy; otherwise a copy must be made. */ -#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \ - function_arg_callee_copies(&CUM, MODE, TYPE, NAMED) - -/* If defined, a C expression that indicates whether items passed by - reference should be kept as a reference, or should be allocated to - a pseudo register. */ -#define FUNCTION_ARG_KEEP_AS_REFERENCE(CUM, MODE, TYPE, NAMED) 1 - -/* A C type for declaring a variable that is used as the first - argument of `FUNCTION_ARG' and other related values. For some - target machines, the type `int' suffices and can hold the number - of bytes of argument so far. - - There is no need to record in `CUMULATIVE_ARGS' anything about the - arguments that have been passed on the stack. The compiler has - other variables to keep track of that. For target machines on - which all arguments are passed on the stack, there is no need to - store anything in `CUMULATIVE_ARGS'; however, the data structure - must exist and should not be empty, so use `int'. */ -typedef struct { int reg, stack; } d10v_cumulative_args; -#define CUMULATIVE_ARGS d10v_cumulative_args - -/* A C statement (sans semicolon) for initializing the variable CUM - for the state at the beginning of the argument list. The variable - has type `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node - for the data type of the function which will receive the args, or 0 - if the args are to a compiler support library function. The value - of INDIRECT is nonzero when processing an indirect call, for - example a call through a function pointer. The value of INDIRECT - is zero for a call to an explicitly named function, a library - function call, or when `INIT_CUMULATIVE_ARGS' is used to find - arguments for the function being compiled. - - When processing a call to a compiler support library function, - LIBNAME identifies which one. It is a `symbol_ref' rtx which - contains the name of the function, as a string. LIBNAME is 0 when - an ordinary C function call is being processed. Thus, each time - this macro is called, either LIBNAME or FNTYPE is nonzero, but - never both of them at once. */ -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ - init_cumulative_args (&CUM, FNTYPE, LIBNAME, INDIRECT, FALSE) - -/* Like `INIT_CUMULATIVE_ARGS' but overrides it for the purposes of - finding the arguments for the function being compiled. If this - macro is undefined, `INIT_CUMULATIVE_ARGS' is used instead. - - The value passed for LIBNAME is always 0, since library routines - with special calling conventions are never compiled with GNU CC. - The argument LIBNAME exists for symmetry with - `INIT_CUMULATIVE_ARGS'. */ -#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \ - init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE, TRUE) - -/* A C statement (sans semicolon) to update the summarizer variable - CUM to advance past an argument in the argument list. The values - MODE, TYPE and NAMED describe that argument. Once this is done, - the variable CUM is suitable for analyzing the *following* - argument with `FUNCTION_ARG', etc. - - This macro need not do anything if the argument in question was - passed on the stack. The compiler knows how to track the amount - of stack space used for arguments without any special help. */ -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - function_arg_advance (&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, `downward' to pad below, or `none' to inhibit - padding. - - The *amount* of padding is always just enough to reach the next - multiple of `FUNCTION_ARG_BOUNDARY'; this macro does not control - it. - - This macro has a default definition which is right for most - systems. For little-endian machines, the default is to pad - upward. For big-endian machines, the default is to pad downward - for an argument of constant size shorter than an `int', and upward - otherwise. */ -/* #define FUNCTION_ARG_PADDING(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) \ - 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 implicit arguments such as the static chain and - the structure-value address. On many machines, no registers can be - used for this purpose since all function arguments are pushed on - the stack. */ -#define FUNCTION_ARG_REGNO_P(REGNO) IN_RANGE_P (REGNO, ARG_FIRST, ARG_LAST) - - -/* How values are returned */ - -/* Define this macro if `-traditional' should not cause functions - declared to return `float' to convert the value to `double'. */ -/* #define TRADITIONAL_RETURN_FLOAT */ - -/* A C expression to create an RTX representing the place where a - function returns a value of data type VALTYPE. VALTYPE is a tree - node representing a data type. Write `TYPE_MODE (VALTYPE)' to get - the machine mode used to represent that type. On many machines, - only the mode is relevant. (Actually, on most machines, scalar - values are returned in the same place regardless of mode). - - If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same - promotion rules specified in `PROMOTE_MODE' if VALTYPE is a scalar - type. - - If the precise function being called is known, FUNC is a tree node - (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This - makes it possible to use a different value-returning convention - for specific functions when all their calls are known. - - `FUNCTION_VALUE' is not used for return vales with aggregate data - types, because these are returned in another way. See - `STRUCT_VALUE_REGNUM' and related macros, below. */ -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), RETURN_REGNUM) - -/* Define this macro if the target machine has "register windows" so - that the register in which a function returns its value is not the - same as the one in which the caller sees the value. - - For such machines, `FUNCTION_VALUE' computes the register in which - the caller will see the value. `FUNCTION_OUTGOING_VALUE' should be - defined in a similar fashion to tell the function where to put the - value. - - If `FUNCTION_OUTGOING_VALUE' is not defined, `FUNCTION_VALUE' - serves both purposes. - - `FUNCTION_OUTGOING_VALUE' is not used for return vales with - aggregate data types, because these are returned in another way. - See `STRUCT_VALUE_REGNUM' and related macros, below. */ -/* #define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) */ - -/* A C expression to create an RTX representing the place where a - library function returns a value of mode MODE. If the precise - function being called is known, FUNC is a tree node - (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This - makes it possible to use a different value-returning convention - for specific functions when all their calls are known. - - Note that "library function" in this context means a compiler - support routine, used to perform arithmetic, whose name is known - specially by the compiler and was not mentioned in the C code being - compiled. - - The definition of `LIBRARY_VALUE' need not be concerned aggregate - data types, because none of the library functions returns such - types. */ - -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, RETURN_REGNUM) - -/* A C expression that is nonzero if REGNO is the number of a hard - register in which the values of called function may come back. - - A register whose use for returning values is limited to serving as - the second of a pair (for a value of type `double', say) need not - be recognized by this macro. So for most machines, this definition - suffices: - - #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) - - If the machine has register windows, so that the caller and the - called function use different registers for the return value, this - macro should recognize only the caller's register numbers. */ -#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == RETURN_REGNUM) - -/* Define this macro if `untyped_call' and `untyped_return' need more - space than is implied by `FUNCTION_VALUE_REGNO_P' for saving and - restoring an arbitrary return value. */ -/* #define APPLY_RESULT_SIZE */ - -/* A C expression which can inhibit the returning of certain function - values in registers, based on the type of value. A nonzero value - says to return the function value in memory, just as large - structures are always returned. Here TYPE will be a C expression - of type `tree', representing the data type of the value. - - Note that values of mode `BLKmode' must be explicitly handled by - this macro. Also, the option `-fpcc-struct-return' takes effect - regardless of this macro. On most systems, it is possible to - leave the macro undefined; this causes a default definition to be - used, whose value is the constant 1 for `BLKmode' values, and 0 - otherwise. - - Do not use this macro to indicate that structures and unions - should always be returned in memory. You should instead use - `DEFAULT_PCC_STRUCT_RETURN' to indicate this. */ -/* #define RETURN_IN_MEMORY(TYPE) */ - -/* Define this macro to be 1 if all structure and union return values - must be in memory. Since this results in slower code, this should - be defined only if needed for compatibility with other compilers - or with an ABI. 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. - - If not defined, this defaults to the value 1. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* If the structure value address is passed in a register, then - `STRUCT_VALUE_REGNUM' should be the number of that register. */ -#define STRUCT_VALUE_REGNUM (GPR_FIRST + 2) - -/* If the structure value address is not passed in a register, define - `STRUCT_VALUE' as an expression returning an RTX for the place - where the address is passed. If it returns 0, the address is - passed as an "invisible" first argument. */ -#define STRUCT_VALUE 0 - -/* On some architectures the place where the structure value address - is found by the called function is not the same place that the - caller put it. This can be due to register windows, or it could - be because the function prologue moves it to a different place. - - If the incoming location of the structure value address is in a - register, define this macro as the register number. */ -/* #define STRUCT_VALUE_INCOMING_REGNUM */ - -/* If the incoming location is not a register, then you should define - `STRUCT_VALUE_INCOMING' as an expression for an RTX for where the - called function should find the value. If it should find the - value on the stack, define this to create a `mem' which refers to - the frame pointer. A definition of 0 means that the address is - passed as an "invisible" first argument. */ -/* #define STRUCT_VALUE_INCOMING */ - -/* Define this macro if the usual system convention on the target - machine for returning structures and unions is for the called - function to return the address of a static variable containing the - value. - - Do not define this if the usual system convention is for the - caller to pass an address to the subroutine. - - This macro has effect in `-fpcc-struct-return' mode, but it does - nothing when you use `-freg-struct-return' mode. */ -/* #define PCC_STATIC_STRUCT_RETURN */ - - -/* Caller saves */ - -/* Define this macro if function calls on the target machine do not - preserve any registers; in other words, if `CALL_USED_REGISTERS' - has 1 for all registers. This macro enables `-fcaller-saves' by - default. Eventually that option will be enabled by default on all - machines and both the option and this macro will be eliminated. */ -/* #define DEFAULT_CALLER_SAVES */ - -/* A C expression to determine whether it is worthwhile to consider - placing a pseudo-register in a call-clobbered hard register and - saving and restoring it around each function call. The expression - should be 1 when this is worth doing, and 0 otherwise. - - If you don't define this macro, a default is used which is good on - most machines: `4 * CALLS < REFS'. */ -/* #define CALLER_SAVE_PROFITABLE (REFS, CALLS) */ - - -/* Prologues and epilogues */ - -/* A C compound statement that outputs the assembler code for entry - to a function. The prologue is responsible for setting up the - stack frame, initializing the frame pointer register, saving - registers that must be saved, and allocating SIZE additional bytes - of storage for the local variables. SIZE is an integer. FILE is - a stdio stream to which the assembler code should be output. */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) function_prologue (FILE, SIZE) - -/* Define this macro as a C expression that is nonzero if the return - instruction or the function epilogue ignores the value of the stack - pointer; in other words, if it is safe to delete an instruction to - adjust the stack pointer before a return from the function. - - Note that this macro's value is relevant only for functions for - which frame pointers are maintained. It is never safe to delete a - final stack adjustment in a function that has no frame pointer, - and the compiler knows this regardless of `EXIT_IGNORE_STACK'. */ -/* #define EXIT_IGNORE_STACK */ - -/* A C compound statement that outputs the assembler code for exit - from a function. The epilogue is responsible for restoring the - saved registers and stack pointer to their values when the - function was called, and returning control to the caller. This - macro takes the same arguments as the macro `FUNCTION_PROLOGUE', - and the registers to restore are determined from `regs_ever_live' - and `CALL_USED_REGISTERS' in the same way. */ - -#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue (FILE, SIZE) - -/* Define this macro if the function epilogue contains delay slots to - which instructions from the rest of the function can be "moved". - The definition should be a C expression whose value is an integer - representing the number of delay slots there. */ -/* #define DELAY_SLOTS_FOR_EPILOGUE */ - -/* A C expression that returns 1 if INSN can be placed in delay slot - number N of the epilogue. - - The argument N is an integer which identifies the delay slot now - being considered (since different slots may have different rules of - eligibility). It is never negative and is always less than the - number of epilogue delay slots (what `DELAY_SLOTS_FOR_EPILOGUE' - returns). If you reject a particular insn for a given delay slot, - in principle, it may be reconsidered for a subsequent delay slot. - Also, other insns may (at least in principle) be considered for - the so far unfilled delay slot. - - The insns accepted to fill the epilogue delay slots are put in an - RTL list made with `insn_list' objects, stored in the variable - `current_function_epilogue_delay_list'. The insn for the first - delay slot comes first in the list. Your definition of the macro - `FUNCTION_EPILOGUE' should fill the delay slots by outputting the - insns in this list, usually by calling `final_scan_insn'. - - You need not define this macro if you did not define - `DELAY_SLOTS_FOR_EPILOGUE'. */ -/* #define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN, N) */ - -/* A C compound statement that outputs the assembler code for a thunk - function, used to implement C++ virtual function calls with - multiple inheritance. The thunk acts as a wrapper around a - virtual function, adjusting the implicit object parameter before - handing control off to the real function. - - First, emit code to add the integer DELTA to the location that - contains the incoming first argument. Assume that this argument - contains a pointer, and is the one used to pass the `this' pointer - in C++. This is the incoming argument *before* the function - prologue, e.g. `%o0' on a sparc. The addition must preserve the - values of all other incoming arguments. - - After the addition, emit code to jump to FUNCTION, which is a - `FUNCTION_DECL'. This is a direct pure jump, not a call, and does - not touch the return address. Hence returning from FUNCTION will - return to whoever called the current `thunk'. - - The effect must be as if FUNCTION had been called directly with - the adjusted first argument. This macro is responsible for - emitting all of the code for a thunk function; `FUNCTION_PROLOGUE' - and `FUNCTION_EPILOGUE' are not invoked. - - The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already - been extracted from it.) It might possibly be useful on some - targets, but probably not. - - For many targets, the target-independent code in the C++ frontend - will be sufficient and you can leave this macro undefined. You - need to define this macro if the code generated by default would - clobber any of the incoming arguments; this is only likely if - parameters can be passed in registers. You should also define - this macro if the default code is sub-optimal. */ -/* #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) */ - - -/* Profiling */ - -/* A C statement or compound statement to output to FILE some - assembler code to call the profiling subroutine `mcount'. Before - calling, the assembler code must load the address of a counter - variable into a register where `mcount' expects to find the - address. The name of this variable is `LP' followed by the number - LABELNO, so you would generate the name using `LP%d' in a - `fprintf'. - - The details of how the address should be passed to `mcount' are - determined by your operating system environment, not by GNU CC. To - figure them out, compile a small program for profiling using the - system's installed C compiler and look at the assembler code that - results. */ -#define FUNCTION_PROFILER(FILE, LABELNO) abort () - -/* 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 */ - -/* A C statement or compound statement to output to FILE some - assembler code to initialize basic-block profiling for the current - object module. The global compile flag `profile_block_flag' - distingishes two profile modes. - - `profile_block_flag != 2' - Output code to call the subroutine `__bb_init_func' once per - object module, passing it as its sole argument the address of - a block allocated in the object module. - - The name of the block is a local symbol made with this - statement: - - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); - - Of course, since you are writing the definition of - `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, - you can take a short cut in the definition of this macro and - use the name that you know will result. - - The first word of this block is a flag which will be nonzero - if the object module has already been initialized. So test - this word first, and do not call `__bb_init_func' if the flag - is nonzero. BLOCK_OR_LABEL contains a unique number which - may be used to generate a label as a branch destination when - `__bb_init_func' will not be called. - - Described in assembler language, the code to be output looks - like: - - cmp (LPBX0),0 - bne local_label - parameter1 <- LPBX0 - call __bb_init_func - local_label: - - `profile_block_flag == 2' - Output code to call the subroutine `__bb_init_trace_func' and - pass two parameters to it. The first parameter is the same as - for `__bb_init_func'. The second parameter is the number of - the first basic block of the function as given by - BLOCK_OR_LABEL. Note that `__bb_init_trace_func' has to be - called, even if the object module has been initialized - already. - - Described in assembler language, the code to be output looks - like: - parameter1 <- LPBX0 - parameter2 <- BLOCK_OR_LABEL - call __bb_init_trace_func */ -/* #define FUNCTION_BLOCK_PROFILER (FILE, LABELNO) */ - -/* A C statement or compound statement to output to FILE some - assembler code to increment the count associated with the basic - block number BLOCKNO. */ -/* #define BLOCK_PROFILER(FILE, BLOCKNO) */ - -/* A C statement or compound statement to output to FILE assembler - code to call function `__bb_trace_ret'. The assembler code should - only be output if the global compile flag `profile_block_flag' == - 2. This macro has to be used at every place where code for - returning from a function is generated (e.g. `FUNCTION_EPILOGUE'). - Although you have to write the definition of `FUNCTION_EPILOGUE' - as well, you have to define this macro to tell the compiler, that - the proper call to `__bb_trace_ret' is produced. */ -/* #define FUNCTION_BLOCK_PROFILER_EXIT(FILE) */ - -/* A C statement or compound statement to save all registers, which - may be clobbered by a function call, including condition codes. - The `asm' statement will be mostly likely needed to handle this - task. Local labels in the assembler code can be concatenated with - the string ID, to obtain a unique lable name. - - Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or - `FUNCTION_EPILOGUE' must be saved in the macros - `FUNCTION_BLOCK_PROFILER', `FUNCTION_BLOCK_PROFILER_EXIT' and - `BLOCK_PROFILER' prior calling `__bb_init_trace_func', - `__bb_trace_ret' and `__bb_trace_func' respectively. */ -/* #define MACHINE_STATE_SAVE(ID) */ - -/* A C statement or compound statement to restore all registers, - including condition codes, saved by `MACHINE_STATE_SAVE'. - - Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or - `FUNCTION_EPILOGUE' must be restored in the macros - `FUNCTION_BLOCK_PROFILER', `FUNCTION_BLOCK_PROFILER_EXIT' and - `BLOCK_PROFILER' after calling `__bb_init_trace_func', - `__bb_trace_ret' and `__bb_trace_func' respectively. */ -/* #define MACHINE_STATE_RESTORE(ID) */ - -/* A C function or functions which are needed in the library to - support block profiling. */ -/* #define BLOCK_PROFILER_CODE */ - - -/* Variable arguments */ - -/* If defined, is a C expression that produces the machine-specific - code for a call to `__builtin_saveregs'. This code will be moved - to the very beginning of the function, before any parameter access - are made. The return value of this function should be an RTX that - contains the value to use as the return of `__builtin_saveregs'. - - The argument ARGS is a `tree_list' containing the arguments that - were passed to `__builtin_saveregs'. - - If this macro is not defined, the compiler will output an ordinary - call to the library function `__builtin_saveregs'. */ -#define EXPAND_BUILTIN_SAVEREGS(ARGS) expand_builtin_saveregs (ARGS) - - -/* This macro offers an alternative to using `__builtin_saveregs' and - defining the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the - anonymous register arguments into the stack so that all the arguments - appear to have been passed consecutively on the stack. Once this is done, - you can use the standard implementation of varargs that works for machines - that pass all their arguments on the stack. */ -#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_ARGS_SIZE, SECOND_TIME) \ - 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. - - 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. */ -/* #define STRICT_ARGUMENT_NAMING */ - - -/* Trampolines */ - -/* 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. - - If you do not define this macro, it means no template is needed - for the target. Do not define this macro on systems where the - block move code to copy the trampoline into place would be larger - than the code to generate it on the spot. */ -/* #define TRAMPOLINE_TEMPLATE(FILE) */ - -/* The name of a subroutine to switch to the section in which the - trampoline template is to be placed (*note Sections::.). The - default is a value of `readonly_data_section', which places the - trampoline in the section containing read-only data. */ -/* #define TRAMPOLINE_SECTION */ - -/* A C expression for the size in bytes of the trampoline, as an - integer. */ -#define TRAMPOLINE_SIZE 8 - -/* Alignment required for trampolines, in bits. - - If you don't define this macro, the value of `BIGGEST_ALIGNMENT' - is used for aligning trampolines. */ -#define TRAMPOLINE_ALIGNMENT 32 - -/* A C statement to initialize the variable parts of a trampoline. - ADDR is an RTX for the address of the trampoline; FNADDR is an RTX - for the address of the nested function; STATIC_CHAIN is an RTX for - the static chain value that should be passed to the function when - it is called. */ - -#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \ - initialize_trampoline (ADDR, FNADDR, STATIC_CHAIN) - -/* A C expression to allocate run-time space for a trampoline. The - expression value should be an RTX representing a memory reference - to the space for the trampoline. - - If this macro is not defined, by default the trampoline is - allocated as a stack slot. This default is right for most - machines. The exceptions are machines where it is impossible to - execute instructions in the stack area. On such machines, you may - have to implement a separate stack, using this macro in - conjunction with `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE'. - - FP points to a data structure, a `struct function', which - describes the compilation status of the immediate containing - function of the function which the trampoline is for. Normally - (when `ALLOCATE_TRAMPOLINE' is not defined), the stack slot for the - trampoline is in the stack frame of this containing function. - Other allocation strategies probably must do something analogous - with this information. - - Implementing trampolines is difficult on many machines because they - have separate instruction and data caches. Writing into a stack - location fails to clear the memory in the instruction cache, so when - the program jumps to that location, it executes the old contents. - - Here are two possible solutions. One is to clear the relevant parts - of the instruction cache whenever a trampoline is set up. The other is - to make all trampolines identical, by having them jump to a standard - subroutine. The former technique makes trampoline execution faster; the - latter makes initialization faster. - - To clear the instruction cache when a trampoline is initialized, - define the following macros which describe the shape of the cache. */ -/* #define ALLOCATE_TRAMPOLINE(FP) allocate_trampoline(FP) */ - -/* The total size in bytes of the cache. */ -/* #define INSN_CACHE_SIZE */ - -/* The length in bytes of each cache line. The cache is divided into - cache lines which are disjoint slots, each holding a contiguous - chunk of data fetched from memory. Each time data is brought into - the cache, an entire line is read at once. The data loaded into a - cache line is always aligned on a boundary equal to the line size. */ -/* #define INSN_CACHE_LINE_WIDTH */ - -/* The number of alternative cache lines that can hold any particular - memory location. - - Alternatively, if the machine has system calls or instructions to - clear the instruction cache directly, you can define the following - macro. */ -/* #define INSN_CACHE_DEPTH */ - -/* If defined, expands to a C expression clearing the *instruction - cache* in the specified interval. If it is not defined, and the - macro INSN_CACHE_SIZE is defined, some generic code is generated - to clear the cache. The definition of this macro would typically - be a series of `asm' statements. Both BEG and END are both pointer - expressions. - - To use a standard subroutine, define the following macro. In - addition, you must make sure that the instructions in a trampoline fill - an entire cache line with identical instructions, or else ensure that - the beginning of the trampoline code is always aligned at the same - point in its cache line. Look in `m68k.h' as a guide. -/* #define CLEAR_INSN_CACHE (BEG, END) */ - -/* Define this macro if trampolines need a special subroutine to do - their work. The macro should expand to a series of `asm' - statements which will be compiled with GNU CC. They go in a - library function named `__transfer_from_trampoline'. - - If you need to avoid executing the ordinary prologue code of a - compiled C function when you jump to the subroutine, you can do so - by placing a special label of your own in the assembler code. Use - one `asm' statement to generate an assembler label, and another to - make the label global. Then trampolines can use that label to - jump directly to your special assembler code. */ -/* #define TRANSFER_FROM_TRAMPOLINE */ - - -/* Address modes */ - -/* Define this macro if the machine supports post-increment, - pre-increment, post-decrement, and/or pre-decrement - addressing. */ -#define HAVE_POST_INCREMENT 1 -#define HAVE_POST_DECREMENT 1 -#define HAVE_PRE_DECREMENT 1 -/* #define HAVE_PRE_INCREMENT 0 */ - -/** A C expression that is 1 if the RTX X is a constant which is a - valid address. On most machines, this can be defined as - `CONSTANT_P (X)', but a few machines are more restrictive in which - constant addresses are supported. - - `CONSTANT_P' accepts integer-values expressions whose values are - not explicitly known, such as `symbol_ref', `label_ref', and - `high' expressions and `const' arithmetic expressions, in addition - to `const_int' and `const_double' expressions. */ -#define CONSTANT_ADDRESS_P(X) CONSTANT_P(X) - -/* A number, the maximum number of registers that can appear in a - valid memory address. Note that it is up to you to specify a - value equal to the maximum number that `GO_IF_LEGITIMATE_ADDRESS' - would ever accept. */ -#define MAX_REGS_PER_ADDRESS 1 - -/* A C compound statement with a conditional `goto LABEL;' executed - if X (an RTX) is a legitimate memory address on the target machine - for a memory operand of mode MODE. - - It usually pays to define several simpler macros to serve as - subroutines for this one. Otherwise it may be too complicated to - understand. - - This macro must exist in two variants: a strict variant and a - non-strict one. The strict variant is used in the reload pass. It - must be defined so that any pseudo-register that has not been - allocated a hard register is considered a memory reference. In - contexts where some kind of register is required, a pseudo-register - with no hard register must be rejected. - - The non-strict variant is used in other passes. It must be - defined to accept all pseudo-registers in every context where some - kind of register is required. - - Compiler source files that want to use the strict variant of this - macro define the macro `REG_OK_STRICT'. You should use an `#ifdef - REG_OK_STRICT' conditional to define the strict variant in that - case and the non-strict variant otherwise. - - Subroutines to check for acceptable registers for various purposes - (one for base registers, one for index registers, and so on) are - typically among the subroutines used to define - `GO_IF_LEGITIMATE_ADDRESS'. Then only these subroutine macros - need have two variants; the higher levels of macros may be the - same whether strict or not. */ - -#ifdef REG_OK_STRICT -#define REG_OK_STRICT_P 1 -#else -#define REG_OK_STRICT_P 0 -#endif - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -do { \ - if (d10v_legitimate_address_p (MODE, X, REG_OK_STRICT_P)) \ - goto ADDR; \ -} while (0) - -/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is - valid for use as a base register. For hard registers, it should - always accept those which the hardware permits and reject the - others. Whether the macro accepts or rejects pseudo registers - must be controlled by `REG_OK_STRICT' as described above. This - usually requires two variant definitions, of which `REG_OK_STRICT' - controls the one actually used. */ - -#ifdef REG_OK_STRICT -#define REG_OK_FOR_BASE_P(X) GPR_P (REGNO (X)) -#else -#define REG_OK_FOR_BASE_P(X) \ - (GPR_P (REGNO (X)) \ - || REGNO (X) == ARG_POINTER_REGNUM \ - || REGNO (X) >= FIRST_PSEUDO_REGISTER) -#endif - -/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is - valid for use as an index register. - - The difference between an index register and a base register is - that the index register may be scaled. If an address involves the - sum of two registers, neither one of them scaled, then either one - may be labeled the "base" and the other the "index"; but whichever - labeling is used must fit the machine's constraints of which - registers may serve in each capacity. The compiler will try both - labelings, looking for one that is valid, and will reload one or - both registers only if neither labeling works. */ -#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P(X) - -/* A C compound statement that attempts to replace X with a valid - memory address for an operand of mode MODE. WIN will be a C - statement label elsewhere in the code; the macro definition may use - - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); - - to avoid further processing if the address has become legitimate. - - X will always be the result of a call to `break_out_memory_refs', - and OLDX will be the operand that was given to that function to - produce X. - - The code generated by this macro should not alter the substructure - of X. If it transforms X into a more legitimate form, it should - assign X (which will always be a C variable) a new value. - - It is not necessary for this macro to come up with a legitimate - address. The compiler has standard ways of doing so in all cases. - In fact, it is safe for this macro to do nothing. But often a - machine-dependent strategy can generate better code. */ -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -do { \ - rtx y = d10v_legitimize_address (X, OLDX, MODE, REG_OK_STRICT_P); \ - if (y) \ - { \ - X = y; \ - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); \ - } \ -} while (0) - -/* A C statement or compound statement with a conditional `goto - LABEL;' executed if memory address X (an RTX) can have different - meanings depending on the machine mode of the memory reference it - is used for or if the address is valid for some modes but not - others. - - Autoincrement and autodecrement addresses typically have - mode-dependent effects because the amount of the increment or - decrement is the size of the operand being addressed. Some - machines have other mode-dependent addresses. Many RISC machines - have no mode-dependent addresses. - - You may assume that ADDR is a valid address for the machine. */ -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ -do { \ - if (d10v_mode_dependent_address_p (ADDR)) \ - goto LABEL; \ -} while (0) \ - -/* A C expression that is nonzero if X is a legitimate constant for - an immediate operand on the target machine. You can assume that X - satisfies `CONSTANT_P', so you need not check this. In fact, `1' - is a suitable definition for this macro on machines where anything - `CONSTANT_P' is valid. */ -#define LEGITIMATE_CONSTANT_P(X) 1 - - -/* Condition codes */ - -/* C code for a data type which is used for declaring the `mdep' - component of `cc_status'. It defaults to `int'. - - This macro is not used on machines that do not use `cc0'. */ -/* #define CC_STATUS_MDEP */ - -/* A C expression to initialize the `mdep' field to "empty". The - default definition does nothing, since most machines don't use the - field anyway. If you want to use the field, you should probably - define this macro to initialize it. - - This macro is not used on machines that do not use `cc0'. */ -/* #define CC_STATUS_MDEP_INIT */ - -/* A C compound statement to set the components of `cc_status' - appropriately for an insn INSN whose body is EXP. It is this - macro's responsibility to recognize insns that set the condition - code as a byproduct of other activity as well as those that - explicitly set `(cc0)'. - - This macro is not used on machines that do not use `cc0'. - - If there are insns that do not set the condition code but do alter - other machine registers, this macro must check to see whether they - invalidate the expressions that the condition code is recorded as - reflecting. For example, on the 68000, insns that store in address - registers do not set the condition code, which means that usually - `NOTICE_UPDATE_CC' can leave `cc_status' unaltered for such insns. - But suppose that the previous insn set the condition code based - on location `a4@(102)' and the current insn stores a new value in - `a4'. Although the condition code is not changed by this, it will - no longer be true that it reflects the contents of `a4@(102)'. - Therefore, `NOTICE_UPDATE_CC' must alter `cc_status' in this case - to say that nothing is known about the condition code value. - - The definition of `NOTICE_UPDATE_CC' must be prepared to deal with - the results of peephole optimization: insns whose patterns are - `parallel' RTXs containing various `reg', `mem' or constants which - are just the operands. The RTL structure of these insns is not - sufficient to indicate what the insns actually do. What - `NOTICE_UPDATE_CC' should do when it sees one is just to run - `CC_STATUS_INIT'. - - A possible definition of `NOTICE_UPDATE_CC' is to call a function - that looks at an attribute (*note Insn Attributes::.) named, for - example, `cc'. This avoids having detailed information about - patterns in two places, the `md' file and in `NOTICE_UPDATE_CC'. */ -/* #define NOTICE_UPDATE_CC (EXP, INSN) */ - -/* A list of names to be used for additional modes for condition code - values in registers (*note Jump Patterns::.). These names are - added to `enum machine_mode' and all have class `MODE_CC'. By - convention, they should start with `CC' and end with `mode'. - - You should only define this macro if your machine does not use - `cc0' and only if additional modes are required. */ -#define EXTRA_CC_MODES CC_REVmode - -/* A list of C strings giving the names for the modes listed in - `EXTRA_CC_MODES'. For example, the Sparc defines this macro and - `EXTRA_CC_MODES' as - - #define EXTRA_CC_MODES CC_NOOVmode, CCFPmode, CCFPEmode - #define EXTRA_CC_NAMES "CC_NOOV", "CCFP", "CCFPE" - - This macro is not required if `EXTRA_CC_MODES' is not defined. */ -#define EXTRA_CC_NAMES "CC_REV" - -/* Returns a mode from class `MODE_CC' to be used when comparison - operation code OP is applied to rtx X and Y. For example, on the - Sparc, `SELECT_CC_MODE' is defined as (see *note Jump Patterns::. - for a description of the reason for this definition) - - #define SELECT_CC_MODE(OP,X,Y) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ - : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ - || GET_CODE (X) == NEG) \ - ? CC_NOOVmode : CCmode)) - - You need not define this macro if `EXTRA_CC_MODES' is not defined. */ -#define SELECT_CC_MODE(OP, X, Y) ((enum machine_mode) select_cc_mode (OP, X, Y)) - -/* One some machines not all possible comparisons are defined, but - you can convert an invalid comparison into a valid one. For - example, the Alpha does not have a `GT' comparison, but you can - use an `LT' comparison instead and swap the order of the operands. - - On such machines, define this macro to be a C statement to do any - required conversions. CODE is the initial comparison code and OP0 - and OP1 are the left and right operands of the comparison, - respectively. You should modify CODE, OP0, and OP1 as required. - - GNU CC will not assume that the comparison resulting from this - macro is valid but will see if the resulting insn matches a - pattern in the `md' file. - - You need not define this macro if it would never change the - comparison code or operands. */ - -#if 0 -#define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \ - do { \ - if (((CODE) == GE || (CODE) == GT || (CODE) == GEU || (CODE) == GTU) \ - && (GET_CODE (OP1) == REG || (OP1) == const0_rtx)) \ - { \ - rtx tem = (OP0); \ - (OP0) = (OP1); \ - (OP1) = tem; \ - (CODE) = swap_condition (CODE); \ - } \ - if (((CODE) == LT || (CODE) == LTU) \ - && GET_CODE (OP1) == CONST_INT && INTVAL (OP1) == 256) \ - { \ - (CODE) = (CODE) == LT ? LE : LEU; \ - (OP1) = GEN_INT (255); \ - } \ - } while (0) -#endif - - -/* A C expression whose value is one if it is always safe to reverse a - comparison whose mode is MODE. If `SELECT_CC_MODE' can ever - return MODE for a floating-point inequality comparison, then - `REVERSIBLE_CC_MODE (MODE)' must be zero. - - You need not define this macro if it would always returns zero or - if the floating-point format is anything other than - `IEEE_FLOAT_FORMAT'. For example, here is the definition used on - the Sparc, where floating-point inequality comparisons are always - given `CCFPEmode': - - #define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode) */ -/* #define REVERSIBLE_CC_MODE (MODE) */ - - -/* Describing Relative Costs of Operations */ - -/* A part of a C `switch' statement that describes the relative costs - of constant RTL expressions. It must contain `case' labels for - expression codes `const_int', `const', `symbol_ref', `label_ref' - and `const_double'. Each case must ultimately reach a `return' - statement to return the relative cost of the use of that kind of - constant value in an expression. The cost may depend on the - precise value of the constant, which is available for examination - in X, and the rtx code of the expression in which it is contained, - found in OUTER_CODE. */ -#define CONST_COSTS(X, CODE, OUTER_CODE) \ - return COSTS_N_INSNS (1); - -/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. - This can be used, for example, to indicate how costly a multiply - instruction is. In writing this macro, you can use the construct - `COSTS_N_INSNS (N)' to specify a cost equal to N fast - instructions. OUTER_CODE is the code of the expression in which X - is contained. - - This macro is optional; do not define it if the default cost - assumptions are adequate for the target machine. */ -#define RTX_COSTS(X, CODE, OUTER_CODE) \ - case MULT: \ - return COSTS_N_INSNS (2); \ - case DIV: \ - case MOD: \ - case UDIV: \ - case UMOD: \ - return COSTS_N_INSNS (TARGET_DEBUG ? 2 : 16); - -/* An expression giving the cost of an addressing mode that contains - ADDRESS. If not defined, the cost is computed from the ADDRESS - expression and the `CONST_COSTS' values. - - For most CISC machines, the default cost is a good approximation - of the true cost of the addressing mode. However, on RISC - machines, all instructions normally have the same length and - execution time. Hence all addresses will have equal costs. - - In cases where more than one form of an address is known, the form - with the lowest cost will be used. If multiple forms have the - same, lowest, cost, the one that is the most complex will be used. - - This macro will normally either not be defined or be defined as a - constant. */ -/* #define ADDRESS_COST (ADDRESS) */ - -/* 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 (FROM, TO) */ - -/* A C expression for the cost of moving data of mode M between a - register and memory. A value of 4 is the default; this cost is - relative to those in `REGISTER_MOVE_COST'. - - If moving between registers and memory is more expensive than - between two registers, you should define this macro to express the - relative cost. */ -/* #define MEMORY_MOVE_COST (M,C,I) */ - -/* 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 d10v_branch_cost - -/* Values of the -mbranch-cost=n string. */ -extern int d10v_branch_cost; -extern char *d10v_branch_cost_string; - -/* A C expression for the maximum number of instructions to execute via - conditional execution instructions instead of a branch. A value of - BRANCH_COST+1 is the default if the machine does not use cc0, and 1 if it - does use cc0. */ -#define MAX_CONDITIONAL_EXECUTE d10v_cond_exec - -/* Values of the -mcond-exec=n string. */ -extern int d10v_cond_exec; -extern char *d10v_cond_exec_string; - - -/* Define this macro as a C expression which is nonzero if accessing - less than a word of memory (i.e. a `char' or a `short') is no - faster than accessing a word of memory, i.e., if such access - require more than one instruction or if there is no difference in - cost between byte and (aligned) word loads. - - When this macro is not defined, the compiler will access a field by - finding the smallest containing object; when it is defined, a - fullword load will be used if alignment permits. Unless bytes - accesses are faster than word accesses, using word accesses is - preferable since it may eliminate subsequent memory access if - subsequent accesses occur to other fields in the same word of the - structure, but to different bytes. */ -#define SLOW_BYTE_ACCESS 0 - -/* Define this macro if zero-extension (of a `char' or `short' to an - `int') can be done faster if the destination is a register that is - known to be zero. - - If you define this macro, you must have instruction patterns that - recognize RTL structures like this: - - (set (strict_low_part (subreg:QI (reg:SI ...) 0)) ...) - - and likewise for `HImode'. */ -/* #define SLOW_ZERO_EXTEND */ - -/* Define this macro to be the value 1 if unaligned accesses have a - cost many times greater than aligned accesses, for example if they - are emulated in a trap handler. - - When this macro is non-zero, the compiler will act as if - `STRICT_ALIGNMENT' were non-zero when generating code for block - moves. This can cause significantly more instructions to be - produced. Therefore, do not set this macro non-zero if unaligned - accesses only add a cycle or two to the time for a memory access. - - If the value of this macro is always zero, it need not be defined. */ -/* #define SLOW_UNALIGNED_ACCESS */ - -/* Define this macro to inhibit strength reduction of memory - addresses. (On some machines, such strength reduction seems to do - harm rather than good.) */ -/* #define DONT_REDUCE_ADDR */ - -/* The number of scalar move insns which should be generated instead - of a string move insn or a library call. Increasing the value - will always make code faster, but eventually incurs high cost in - increased code size. - - If you don't define this, a reasonable default is used. */ -#define MOVE_RATIO 4 - -/* 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 - -/* Define this macro if it is as good or better for a function to call - itself with an explicit address than to call an address kept in a - register. */ -#define NO_RECURSIVE_FUNCTION_CSE - -/* A C statement (sans semicolon) to update the integer variable COST - based on the relationship between INSN that is dependent on - DEP_INSN through the dependence LINK. The default is to make no - adjustment to COST. This can be used for example to specify to - the scheduler that an output- or anti-dependence does not incur - the same cost as a data-dependence. */ -/* #define ADJUST_COST (INSN, LINK, DEP_INSN, COST) */ - -/* A C statement (sans semicolon) to update the integer scheduling - priority `INSN_PRIORITY(INSN)'. Reduce the priority to execute - the INSN earlier, increase the priority to execute INSN later. - Do not define this macro if you do not need to adjust the - scheduling priorities of insns. */ -/* #define ADJUST_PRIORITY (INSN) */ - - -/* Dividing the Output into Sections (Texts, Data, ...) */ - -/* A C expression whose value is a string containing the assembler - operation that should precede instructions and read-only data. - Normally `".text"' is right. */ -#define TEXT_SECTION_ASM_OP "\t.text" - - -/* A C expression whose value is a string containing the assembler - operation to identify the following data as writable initialized - data. Normally `".data"' is right. */ -#define DATA_SECTION_ASM_OP "\t.data" - - -/* If defined, a C expression whose value is a string containing the - assembler operation to identify the following data as shared data. - If not defined, `DATA_SECTION_ASM_OP' will be used. */ -/* #define SHARED_SECTION_ASM_OP */ - -/* 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. */ -#ifndef BSS_SECTION_ASM_OP -#define BSS_SECTION_ASM_OP ".section\t.bss" -#endif - -/* If defined, a C expression whose value is a string containing the - assembler operation to identify the following data as - uninitialized global shared data. If not defined, and - `BSS_SECTION_ASM_OP' is, the latter will be used. */ -/* #define SHARED_BSS_SECTION_ASM_OP */ - -/* If defined, a C expression whose value is a string containing the - assembler operation to identify the following data as - initialization code. If not defined, GNU CC will assume such a - section does not exist. */ -/* #define INIT_SECTION_ASM_OP */ - -/* A list of names for sections other than the standard two, which are - `in_text' and `in_data'. You need not define this macro on a - system with no other sections (that GCC needs to use). */ -/* #define EXTRA_SECTIONS */ - -/* One or more functions to be defined in `varasm.c'. These - functions should do jobs analogous to those of `text_section' and - `data_section', for your additional sections. Do not define this - macro if you do not define `EXTRA_SECTIONS'. */ -/* #define EXTRA_SECTION_FUNCTIONS */ - -/* On most machines, read-only variables, constants, and jump tables - are placed in the text section. If this is not the case on your - machine, this macro should be defined to be the name of a function - (either `data_section' or a function defined in `EXTRA_SECTIONS') - that switches to the section to be used for read-only items. - - If these items should be placed in the text section, this macro - should not be defined. */ -/* #define READONLY_DATA_SECTION */ - -/* A C statement or statements to switch to the appropriate section - for output of EXP. You can assume that EXP is either a `VAR_DECL' - node or a constant of some sort. RELOC indicates whether the - initial value of EXP requires link-time relocations. Select the - section by calling `text_section' or one of the alternatives for - other sections. - - Do not define this macro if you put all read-only variables and - constants in the read-only data section (usually the text section). */ -/* #define SELECT_SECTION (EXP, RELOC) */ - -/* 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. - - Do not define this macro if you put all constants in the read-only - data section. */ -/* #define SELECT_RTX_SECTION (MODE, RTX) */ - -/* Define this macro if jump tables (for `tablejump' insns) should be - output in the text section, along with the assembler instructions. - Otherwise, the readonly data section is used. - - This macro is irrelevant if there is no separate readonly data - section. */ -/* #define JUMP_TABLES_IN_TEXT_SECTION */ - -/* Define this macro if references to a symbol must be treated - differently depending on something about the variable or function - named by the symbol (such as what section it is in). - - The macro definition, if any, is executed immediately after the - rtl for DECL has been created and stored in `DECL_RTL (DECL)'. - The value of the rtl will be a `mem' whose address is a - `symbol_ref'. - - The usual thing for this macro to do is to record a flag in the - `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified - name string in the `symbol_ref' (if one bit is not enough - information). */ -#define ENCODE_SECTION_INFO(DECL) encode_section_info (DECL) - -/* Decode SYM_NAME and store the real name part in VAR, sans the - characters that encode section info. Define this macro if - `ENCODE_SECTION_INFO' alters the symbol's name string. */ -/* #define STRIP_NAME_ENCODING (VAR, SYM_NAME) */ - -/* For objects going into their own sections, a C expression of the - name of the section, expressed as a STRING_CST node, to put DECL - into. The STRING_CST node must be allocated in the saveable - obstack. Function `build_string' can be used to do this. If you - do not define this macro, GNU CC will use the symbol name as the - section name. */ -/* #define UNIQUE_SECTION (DECL) */ - - -/* Position Independent Code */ - -/* The register number of the register used to address a table of - static data addresses in memory. In some cases this register is - defined by a processor's "application binary interface" (ABI). - When this macro is defined, RTL is generated for this register - once, as with the stack pointer and frame pointer registers. If - this macro is not defined, it is up to the machine-dependent files - to allocate such a register (if necessary). */ -/* #define PIC_OFFSET_TABLE_REGNUM */ - -/* Define this macro if the register defined by - `PIC_OFFSET_TABLE_REGNUM' is clobbered by calls. Do not define - this macro if `PPIC_OFFSET_TABLE_REGNUM' is not defined. */ -/* #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 - not check this. You can also assume FLAG_PIC is true, so you need - not check it either. You need not define this macro if all - constants (including `SYMBOL_REF') can be immediate operands when - generating position independent code. */ -/* #define LEGITIMATE_PIC_OPERAND_P (X) */ - - -/* The Overall Framework of an Assembler File */ - -/* A C expression which outputs to the stdio stream STREAM some - appropriate text to go at the start of an assembler file. - - Normally this macro is defined to output a line containing - `#NO_APP', which is a comment that has no effect on most - assemblers but tells the GNU assembler that it can save time by not - checking for certain assembler constructs. - - On systems that use SDB, it is necessary to output certain - commands; see `attasm.h'. */ -/* #define ASM_FILE_START (STREAM) */ - -/* A C expression which outputs to the stdio stream STREAM some - appropriate text to go at the end of an assembler file. - - If this macro is not defined, the default is to output nothing - special at the end of the file. Most systems don't require any - definition. - - On systems that use SDB, it is necessary to output certain - commands; see `attasm.h'. */ -/* #define ASM_FILE_END (STREAM) */ - -/* A C statement to output assembler commands which will identify the - object file as having been compiled with GNU CC (or another GNU - compiler). - - If you don't define this macro, the string `gcc_compiled.:' is - output. This string is calculated to define a symbol which, on - BSD systems, will never be defined for any other reason. GDB - checks for the presence of this symbol when reading the symbol - table of an executable. - - On non-BSD systems, you must arrange communication with GDB in - some other fashion. If GDB is not used on your system, you can - define this macro with an empty body */ -/* #define ASM_IDENTIFY_GCC (FILE) */ - -/* A C string constant describing how to begin a comment in the target - assembler language. The compiler assumes that the comment will - end at the end of the line. */ -#define ASM_COMMENT_START ";" - -/* A C string constant for text to be output before each `asm' - statement or group of consecutive ones. Normally this is - `"#APP"', which is a comment that has no effect on most assemblers - but tells the GNU assembler that it must check the lines that - follow for all valid assembler constructs. */ -#define ASM_APP_ON ";APP_ON\n" - -/* A C string constant for text to be output after each `asm' - statement or group of consecutive ones. Normally this is - `"#NO_APP"', which tells the GNU assembler to resume making the - time-saving assumptions that are valid for ordinary compiler - output. */ -#define ASM_APP_OFF ";APP_OFF\n" - -/* A C statement to output COFF information or DWARF debugging - information which indicates that filename NAME is the current - source file to the stdio stream STREAM. - - This macro need not be defined if the standard form of output for - the file format in use is appropriate. */ -/* #define ASM_OUTPUT_SOURCE_FILENAME (STREAM, NAME) */ - -/* A C statement to output DBX or SDB debugging information before - code for line number LINE of the current source file to the stdio - stream STREAM. - - This macro need not be defined if the standard form of debugging - information for the debugger in use is appropriate */ -/* #define ASM_OUTPUT_SOURCE_LINE (STREAM, LINE) */ - -/* A C statement to output something to the assembler file to handle a - `#ident' directive containing the text STRING. If this macro is - not defined, nothing is output for a `#ident' directive. */ -/* #define ASM_OUTPUT_IDENT (STREAM, STRING) */ - -/* A C statement to output something to the assembler file to switch - to section NAME for object DECL which is either a `FUNCTION_DECL', - a `VAR_DECL' or `NULL_TREE'. Some target formats do not support - arbitrary sections. Do not define this macro in such cases. - - At present this macro is only used to support section attributes. - When this macro is undefined, section attributes are disabled. */ -/* #define ASM_OUTPUT_SECTION_NAME (STREAM, DECL, NAME, RELOC) */ - -/* A C statement to output any assembler statements which are - required to precede any Objective C object definitions or message - sending. The statement is executed only when compiling an - Objective C program. */ -/* #define `BJC_PROLOGUE */ - - -/* Output of Data */ - -/* A C statement to output to the stdio stream STREAM an assembler - instruction to assemble a floating-point constant of `TFmode', - `DFmode', `SFmode', `TQFmode', `HFmode', or `QFmode', - respectively, whose value is VALUE. VALUE will be a C expression - of type `REAL_VALUE_TYPE'. Macros such as - `REAL_VALUE_TO_TARGET_DOUBLE' are useful for writing these - definitions. - -/* #define ASM_OUTPUT_LONG_DOUBLE (STREAM, VALUE) */ -/* #define ASM_OUTPUT_DOUBLE (STREAM, VALUE) */ -/* #define ASM_OUTPUT_FLOAT (STREAM, VALUE) */ -/* #define ASM_OUTPUT_THREE_QUARTER_FLOAT (STREAM, VALUE) */ -/* #define ASM_OUTPUT_SHORT_FLOAT (STREAM, VALUE) */ -/* #define ASM_OUTPUT_BYTE_FLOAT (STREAM, VALUE) */ - -#if 1 -#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ - { \ - if (REAL_VALUE_ISINF (VALUE) \ - || REAL_VALUE_ISNAN (VALUE) \ - || REAL_VALUE_MINUS_ZERO (VALUE)) \ - { \ - long t[2]; \ - REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ - fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n", \ - t[0] & 0xffffffff, t[1] & 0xffffffff); \ - } \ - else \ - { \ - char str[30]; \ - REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", str); \ - fprintf (FILE, "\t.double 0d%s\n", str); \ - } \ - } - -#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ - { \ - if (REAL_VALUE_ISINF (VALUE) \ - || REAL_VALUE_ISNAN (VALUE) \ - || REAL_VALUE_MINUS_ZERO (VALUE)) \ - { \ - long t; \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ - } \ - else \ - { \ - char str[30]; \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ - fprintf (FILE, "\t.float 0d%s\n", str); \ - } \ - } - -#else -#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ -do \ - { \ - long t[2]; \ - char str[30]; \ - \ - REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ - if (REAL_VALUE_ISINF (VALUE)) \ - strcpy (str, "Infinity"); \ - else if (REAL_VALUE_ISNAN (VALUE)) \ - strcpy (str, "NaN"); \ - else if (REAL_VALUE_MINUS_ZERO (VALUE)) \ - strcpy (str, "-0"); \ - else \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20g", str); \ - \ - fprintf (FILE, "\t.long 0x%lx,0x%lx\t; %s\n", \ - t[0] & 0xffffffff, t[1] & 0xffffffff, str); \ - } \ -while (0) - -#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ -do \ - { \ - long t; \ - char str[30]; \ - \ - if (REAL_VALUE_ISINF (VALUE)) \ - strcpy (str, "Infinity"); \ - else if (REAL_VALUE_ISNAN (VALUE)) \ - strcpy (str, "NaN"); \ - else if (REAL_VALUE_MINUS_ZERO (VALUE)) \ - strcpy (str, "-0"); \ - else \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20g", str); \ - \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - fprintf (FILE, "\t.long 0x%lx\t; %s\n", t & 0xffffffff, str); \ - } \ -while (0) -#endif - -/* A C statement to output to the stdio stream STREAM an assembler - instruction to assemble an integer of 16, 8, 4, 2 or 1 bytes, - respectively, whose value is VALUE. The argument EXP will be an - RTL expression which represents a constant value. Use - `output_addr_const (STREAM, EXP)' to output this value as an - assembler expression. - - For sizes larger than `UNITS_PER_WORD', if the action of a macro - would be identical to repeatedly calling the macro corresponding to - a size of `UNITS_PER_WORD', once for each word, you need not define - the macro. - - On the D10V, we want to emit word addresses for functions & labels, - not byte addresses. ENCODE_SECTION_INFO has set TREE_SIDE_EFFECT on - function nodes. */ - -/* #define ASM_OUTPUT_QUADRUPLE_INT (STREAM, EXP) */ -/* #define ASM_OUTPUT_DOUBLE_INT (STREAM, EXP) */ - -#define ASM_OUTPUT_INT(STREAM, EXP) \ -do { \ - fputs ("\t.long ", STREAM); \ - output_addr_const (STREAM, EXP); \ - putc ('\n', STREAM); \ -} while (0) - -/* Use d10v_output_addr_const, not output_addr_const for HI values - to insure proper truncation and sign extension of negative offsets, - which sometimes get converted to unsigned HI values. */ -#define ASM_OUTPUT_SHORT(STREAM, EXP) \ -do { \ - fputs ("\t.word ", STREAM); \ - if (GET_CODE (EXP) == LABEL_REF) \ - { \ - d10v_output_addr_const (STREAM, EXP); \ - fputs ("@word", STREAM); \ - } \ - \ - else if (GET_CODE (EXP) != SYMBOL_REF) \ - d10v_output_addr_const (STREAM, EXP); \ - \ - else \ - { \ - tree id = get_identifier (XSTR (EXP, 0)); \ - if (TREE_SIDE_EFFECTS (id)) \ - fprintf (STREAM, "%s@word", XSTR (EXP, 0)); \ - else \ - d10v_output_addr_const (STREAM, EXP); \ - } \ - \ - putc ('\n', STREAM); \ -} while (0) - -#define ASM_OUTPUT_CHAR(STREAM, EXP) \ -do { \ - fputs ("\t.byte ", STREAM); \ - output_addr_const (STREAM, EXP); \ - putc ('\n', STREAM); \ -} while (0) - -/* A C statement to output to the stdio stream STREAM an assembler - instruction to assemble a single byte containing the number VALUE. */ -#define ASM_OUTPUT_BYTE(STREAM, VALUE) \ - fprintf (STREAM, "\t%s %d\n", ASM_BYTE_OP, VALUE) - -/* A C string constant giving the pseudo-op to use for a sequence of - single-byte constants. If this macro is not defined, the default - is `"byte"'. */ -/* #define ASM_BYTE_OP */ - -/* A C statement to output to the stdio stream STREAM an assembler - instruction to assemble a string constant containing the LEN bytes - at PTR. PTR will be a C expression of type `char *' and LEN a C - expression of type `int'. - - If the assembler has a `.ascii' pseudo-op as found in the Berkeley - Unix assembler, do not define the macro `ASM_OUTPUT_ASCII'. */ -/* #define ASM_OUTPUT_ASCII (STREAM, PTR, LEN) */ - -/* A C statement to output assembler commands to define the start of - the constant pool for a function. FUNNAME is a string giving the - name of the function. Should the return type of the function be - required, it can be obtained via FUNDECL. SIZE is the size, in - bytes, of the constant pool that will be written immediately after - this call. - - If no constant-pool prefix is required, the usual case, this macro - need not be defined. */ -/* #define ASM_OUTPUT_POOL_PROLOGUE (FILE FUNNAME FUNDECL SIZE) */ - -/* A C statement (with or without semicolon) to output a constant in - the constant pool, if it needs special treatment. (This macro - need not do anything for RTL expressions that can be output - normally.) - - The argument FILE is the standard I/O stream to output the - assembler code on. X is the RTL expression for the constant to - output, and MODE is the machine mode (in case X is a `const_int'). - ALIGN is the required alignment for the value X; you should - output an assembler directive to force this much alignment. - - The argument LABELNO is a number to use in an internal label for - the address of this pool entry. The definition of this macro is - responsible for outputting the label definition at the proper - place. Here is how to do this: - - ASM_OUTPUT_INTERNAL_LABEL (FILE, "LC", LABELNO); - - When you output a pool entry specially, you should end with a - `goto' to the label JUMPTO. This will prevent the same pool entry - from being output a second time in the usual manner. - - You need not define this macro if it would do nothing. */ -/* #define ASM_OUTPUT_SPECIAL_POOL_ENTRY (FILE, X, MODE, ALIGN, LABELNO, JUMPTO) */ - -/* Define this macro as a C expression which is nonzero if C is used - as a logical line separator by the assembler. - - If you do not define this macro, the default is that only the - character `;' is treated as a logical line separator. */ -/* #define IS_ASM_LOGICAL_LINE_SEPARATOR (C) */ - -/* These macros are defined as C string constant, describing the - syntax in the assembler for grouping arithmetic expressions. */ - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - - -/* Output of Uninitialized Variables */ - -/* A C statement (sans semicolon) to output to the stdio stream - STREAM the assembler definition of a common-label named NAME whose - size is SIZE bytes. The variable ROUNDED is the size rounded up - to whatever alignment the caller wants. - - Use the expression `assemble_name (STREAM, NAME)' to output the - name itself; before and after that, output the additional - assembler syntax for defining the name, and a newline. - - This macro controls how the assembler definitions of uninitialized - common global variables are output. */ -/* #define ASM_OUTPUT_COMMON (STREAM, NAME, SIZE, ROUNDED) */ - -/* Like `ASM_OUTPUT_COMMON' except takes the required alignment as a - separate, explicit argument. If you define this macro, it is used - in place of `ASM_OUTPUT_COMMON', and gives you more flexibility in - handling the required alignment of the variable. The alignment is - specified as the number of bits. */ -/* #define ASM_OUTPUT_ALIGNED_COMMON (STREAM, NAME, SIZE, ALIGNMENT) */ - -/* If defined, it is similar to `ASM_OUTPUT_COMMON', except that it - is used when NAME is shared. If not defined, `ASM_OUTPUT_COMMON' - will be used. */ -/* #define ASM_OUTPUT_SHARED_COMMON (STREAM, NAME, SIZE, ROUNDED) */ - -/* A C statement (sans semicolon) to output to the stdio stream - STREAM the assembler definition of uninitialized global DECL named - NAME whose size is SIZE bytes. The variable ROUNDED is the size - rounded up to whatever alignment the caller wants. - - Try to use function `asm_output_bss' defined in `varasm.c' when - defining this macro. If unable, use the expression `assemble_name - (STREAM, NAME)' to output the name itself; before and after that, - output the additional assembler syntax for defining the name, and - a newline. - - This macro controls how the assembler definitions of uninitialized - global variables are output. This macro exists to properly - support languages like `c++' which do not have `common' data. - However, this macro currently is not defined for all targets. If - this macro and `ASM_OUTPUT_ALIGNED_BSS' are not defined then - `ASM_OUTPUT_COMMON' or `ASM_OUTPUT_ALIGNED_COMMON' is used. */ -/* #define ASM_OUTPUT_BSS (STREAM, DECL, NAME, SIZE, ROUNDED) */ - -/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a - separate, explicit argument. If you define this macro, it is used - in place of `ASM_OUTPUT_BSS', and gives you more flexibility in - handling the required alignment of the variable. The alignment is - specified as the number of bits. - - Try to use function `asm_output_aligned_bss' defined in file - `varasm.c' when defining this macro. */ -#ifndef ASM_OUTPUT_ALIGNED_BSS -#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGNMENT) \ - asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGNMENT) -#endif - -/* If defined, it is similar to `ASM_OUTPUT_BSS', except that it is - used when NAME is shared. If not defined, `ASM_OUTPUT_BSS' will - be used. */ -/* #define ASM_OUTPUT_SHARED_BSS (STREAM, DECL, NAME, SIZE, ROUNDED) */ - -/* A C statement (sans semicolon) to output to the stdio stream - STREAM the assembler definition of a local-common-label named NAME - whose size is SIZE bytes. The variable ROUNDED is the size - rounded up to whatever alignment the caller wants. - - Use the expression `assemble_name (STREAM, NAME)' to output the - name itself; before and after that, output the additional - assembler syntax for defining the name, and a newline. - - This macro controls how the assembler definitions of uninitialized - static variables are output. */ -/* #define ASM_OUTPUT_LOCAL (STREAM, NAME, SIZE, ROUNDED) */ - -/* Like `ASM_OUTPUT_LOCAL' except takes the required alignment as a - separate, explicit argument. If you define this macro, it is used - in place of `ASM_OUTPUT_LOCAL', and gives you more flexibility in - handling the required alignment of the variable. The alignment is - specified as the number of bits. */ -/* #define ASM_OUTPUT_ALIGNED_LOCAL (STREAM, NAME, SIZE, ALIGNMENT) */ - -/* If defined, it is similar to `ASM_OUTPUT_LOCAL', except that it is - used when NAME is shared. If not defined, `ASM_OUTPUT_LOCAL' will - be used. */ -/* #define ASM_OUTPUT_SHARED_LOCAL (STREAM, NAME, SIZE, ROUNDED) */ - - -/* Output and Generation of Labels */ - -/* A C statement (sans semicolon) to output to the stdio stream - STREAM the assembler definition of a label named NAME. Use the - expression `assemble_name (STREAM, NAME)' to output the name - itself; before and after that, output the additional assembler - syntax for defining the name, and a newline. */ -#define ASM_OUTPUT_LABEL(STREAM, NAME) \ -do { \ - assemble_name (STREAM, NAME); \ - fputs (":\n", STREAM); \ -} while (0) - - -/* A C statement (sans semicolon) to output to the stdio stream - STREAM any text necessary for declaring the name NAME of a - function which is being defined. This macro is responsible for - outputting the label definition (perhaps using - `ASM_OUTPUT_LABEL'). The argument DECL is the `FUNCTION_DECL' - tree node representing the function. - - If this macro is not defined, then the function name is defined in - the usual manner as a label (by means of `ASM_OUTPUT_LABEL'). */ -/* #define ASM_DECLARE_FUNCTION_NAME (STREAM, NAME, DECL) */ - - -/* -`ASM_DECLARE_FUNCTION_SIZE (STREAM, NAME, DECL)' - A C statement (sans semicolon) to output to the stdio stream - STREAM any text necessary for declaring the size of a function - which is being defined. The argument NAME is the name of the - function. The argument DECL is the `FUNCTION_DECL' tree node - representing the function. - - If this macro is not defined, then the function size is not - defined. - -`ASM_DECLARE_OBJECT_NAME (STREAM, NAME, DECL)' - A C statement (sans semicolon) to output to the stdio stream - STREAM any text necessary for declaring the name NAME of an - initialized variable which is being defined. This macro must - output the label definition (perhaps using `ASM_OUTPUT_LABEL'). - The argument DECL is the `VAR_DECL' tree node representing the - variable. - - If this macro is not defined, then the variable name is defined in - the usual manner as a label (by means of `ASM_OUTPUT_LABEL'). - -`ASM_FINISH_DECLARE_OBJECT (STREAM, DECL, TOPLEVEL, ATEND)' - A C statement (sans semicolon) to finish up declaring a variable - name once the compiler has processed its initializer fully and - thus has had a chance to determine the size of an array when - controlled by an initializer. This is used on systems where it's - necessary to declare something about the size of the object. - - If you don't define this macro, that is equivalent to defining it - to do nothing. -*/ - -/* A C statement (sans semicolon) to output to the stdio stream - STREAM some commands that will make the label NAME global; that - is, available for reference from other files. Use the expression - `assemble_name (STREAM, NAME)' to output the name itself; before - and after that, output the additional assembler syntax for making - that name global, and a newline. */ - -#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \ -do { \ - fputs ("\t.globl ", STREAM); \ - assemble_name (STREAM, NAME); \ - fputs ("\n", STREAM); \ -} while (0) - - -/* A C statement (sans semicolon) to output to the stdio stream - STREAM some commands that will make the label NAME weak; that is, - available for reference from other files but only used if no other - definition is available. Use the expression `assemble_name - (STREAM, NAME)' to output the name itself; before and after that, - output the additional assembler syntax for making that name weak, - and a newline. - - If you don't define this macro, GNU CC will not support weak - symbols and you should not define the `SUPPORTS_WEAK' macro. */ -/* #define ASM_WEAKEN_LABEL */ - -/* A C expression which evaluates to true if the target supports weak - symbols. - - If you don't define this macro, `defaults.h' provides a default - definition. If `ASM_WEAKEN_LABEL' is defined, the default - definition is `1'; otherwise, it is `0'. Define this macro if you - want to control weak symbol support with a compiler flag such as - `-melf'. */ -/* #define SUPPORTS_WEAK */ - -/* A C statement (sans semicolon) to output to the stdio stream - STREAM any text necessary for declaring the name of an external - symbol named NAME which is referenced in this compilation but not - defined. The value of DECL is the tree node for the declaration. - - This macro need not be defined if it does not need to output - anything. The GNU assembler and most Unix assemblers don't - require anything. */ - -/* #define ASM_OUTPUT_EXTERNAL(STREAM, DECL, NAME) */ - -/* A C statement (sans semicolon) to output on STREAM an assembler - pseudo-op to declare a library function name external. The name - of the library function is given by SYMREF, which has type `rtx' - and is a `symbol_ref'. - - This macro need not be defined if it does not need to output - anything. The GNU assembler and most Unix assemblers don't - require anything. */ - -#undef ASM_OUTPUT_EXTERNAL_LIBCALL -/* #define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM, SYMREF) */ - -/* A C statement (sans semicolon) to output to the stdio stream - STREAM a reference in assembler syntax to a label named NAME. - This should add `_' to the front of the name, if that is customary - on your operating system, as it is in most Berkeley Unix systems. - This macro is used in `assemble_name'. */ -/* #define ASM_OUTPUT_LABELREF(STREAM, NAME) */ - -/* A C statement to output to the stdio stream STREAM a label whose - name is made from the string PREFIX and the number NUM. - - It is absolutely essential that these labels be distinct from the - labels used for user-level functions and variables. Otherwise, - certain programs will have name conflicts with internal labels. - - It is desirable to exclude internal labels from the symbol table - of the object file. Most assemblers have a naming convention for - labels that should be excluded; on many systems, the letter `L' at - the beginning of a label has this effect. You should find out what - convention your system uses, and follow it. - - The usual definition of this macro is as follows: - - fprintf (STREAM, "L%s%d:\n", PREFIX, NUM) */ -/* #define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) */ - -/* A C statement to store into the string STRING a label whose name - is made from the string PREFIX and the number NUM. - - This string, when output subsequently by `assemble_name', should - produce the output that `ASM_OUTPUT_INTERNAL_LABEL' would produce - with the same PREFIX and NUM. - - If the string begins with `*', then `assemble_name' will output - the rest of the string unchanged. It is often convenient for - `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way. If the - string doesn't start with `*', then `ASM_OUTPUT_LABELREF' gets to - output the string, and may change it. (Of course, - `ASM_OUTPUT_LABELREF' is also part of your machine description, so - you should know what it does on your machine.) */ -/* #define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) */ - -/* A C expression to assign to OUTVAR (which is a variable of type - `char *') a newly allocated string made from the string NAME and - the number NUMBER, with some suitable punctuation added. Use - `alloca' to get space for the string. - - The string will be used as an argument to `ASM_OUTPUT_LABELREF' to - produce an assembler label for an internal static variable whose - name is NAME. Therefore, the string must be such as to result in - valid assembler code. The argument NUMBER is different each time - this macro is executed; it prevents conflicts between - similarly-named internal static variables in different scopes. - - Ideally this string should not be a valid C identifier, to prevent - any conflict with the user's own symbols. Most assemblers allow - periods or percent signs in assembler symbols; putting at least - one of these between the name and the number will suffice. */ -#define ASM_FORMAT_PRIVATE_NAME(OUTVAR, NAME, NUMBER) \ -do { \ - (OUTVAR) = (char *) alloca (strlen ((NAME)) + 12); \ - sprintf ((OUTVAR), "%s.%ld", (NAME), (long)(NUMBER)); \ -} while (0) - -/* -`ASM_OUTPUT_DEF (STREAM, NAME, VALUE)' - A C statement to output to the stdio stream STREAM assembler code - which defines (equates) the symbol NAME to have the value VALUE. - - If SET_ASM_OP is defined, a default definition is provided which is - correct for most systems. - -`OBJC_GEN_METHOD_LABEL (BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME)' - Define this macro to override the default assembler names used for - Objective C methods. - - The default name is a unique method number followed by the name of - the class (e.g. `_1_Foo'). For methods in categories, the name of - the category is also included in the assembler name (e.g. - `_1_Foo_Bar'). - - These names are safe on most systems, but make debugging difficult - since the method's selector is not present in the name. - Therefore, particular systems define other ways of computing names. - - BUF is an expression of type `char *' which gives you a buffer in - which to store the name; its length is as long as CLASS_NAME, - CAT_NAME and SEL_NAME put together, plus 50 characters extra. - - The argument IS_INST specifies whether the method is an instance - method or a class method; CLASS_NAME is the name of the class; - CAT_NAME is the name of the category (or NULL if the method is not - in a category); and SEL_NAME is the name of the selector. - - On systems where the assembler can handle quoted names, you can - use this macro to provide more human-readable names. -*/ - - -/* Macros Controlling Initialization Routines */ - -/* -`INIT_SECTION_ASM_OP' - If defined, a C string constant for the assembler operation to - identify the following data as initialization code. If not - defined, GNU CC will assume such a section does not exist. When - you are using special sections for initialization and termination - functions, this macro also controls how `crtstuff.c' and - `libgcc2.c' arrange to run the initialization functions. - -`HAS_INIT_SECTION' - If defined, `main' will not call `__main' as described above. - This macro should be defined for systems that control the contents - of the init section on a symbol-by-symbol basis, such as OSF/1, - and should not be defined explicitly for systems that support - `INIT_SECTION_ASM_OP'. - -`LD_INIT_SWITCH' - If defined, a C string constant for a switch that tells the linker - that the following symbol is an initialization routine. - -`LD_FINI_SWITCH' - If defined, a C string constant for a switch that tells the linker - that the following symbol is a finalization routine. - -`INVOKE__main' - If defined, `main' will call `__main' despite the presence of - `INIT_SECTION_ASM_OP'. This macro should be defined for systems - where the init section is not actually run automatically, but is - still useful for collecting the lists of constructors and - destructors. - -`ASM_OUTPUT_CONSTRUCTOR (STREAM, NAME)' - Define this macro as a C statement to output on the stream STREAM - the assembler code to arrange to call the function named NAME at - initialization time. - - Assume that NAME is the name of a C function generated - automatically by the compiler. This function takes no arguments. - Use the function `assemble_name' to output the name NAME; this - performs any system-specific syntactic transformations such as - adding an underscore. - - If you don't define this macro, nothing special is output to - arrange to call the function. This is correct when the function - will be called in some other manner--for example, by means of the - `collect2' program, which looks through the symbol table to find - these functions by their names. - -`ASM_OUTPUT_DESTRUCTOR (STREAM, NAME)' - This is like `ASM_OUTPUT_CONSTRUCTOR' but used for termination - functions rather than initialization functions. - - If your system uses `collect2' as the means of processing -constructors, then that program normally uses `nm' to scan an object -file for constructor functions to be called. On certain kinds of -systems, you can define these macros to make `collect2' work faster -(and, in some cases, make it work at all): - -`OBJECT_FORMAT_COFF' - Define this macro if the system uses COFF (Common Object File - Format) object files, so that `collect2' can assume this format - and scan object files directly for dynamic constructor/destructor - functions. - -`OBJECT_FORMAT_ROSE' - Define this macro if the system uses ROSE format object files, so - that `collect2' can assume this format and scan object files - directly for dynamic constructor/destructor functions. - - These macros are effective only in a native compiler; `collect2' as - part of a cross compiler always uses `nm' for the target machine. - -`REAL_NM_FILE_NAME' - Define this macro as a C string constant containing the file name - to use to execute `nm'. The default is to search the path - normally for `nm'. - - If your system supports shared libraries and has a program to list - the dynamic dependencies of a given library or executable, you can - define these macros to enable support for running initialization - and termination functions in shared libraries: - -`LDD_SUFFIX' - Define this macro to a C string constant containing the name of the - program which lists dynamic dependencies, like `"ldd"' under SunOS - 4. - -`PARSE_LDD_OUTPUT (PTR)' - Define this macro to be C code that extracts filenames from the - output of the program denoted by `LDD_SUFFIX'. PTR is a variable - of type `char *' that points to the beginning of a line of output - from `LDD_SUFFIX'. If the line lists a dynamic dependency, the - code must advance PTR to the beginning of the filename on that - line. Otherwise, it must set PTR to `NULL'. -*/ - - -/* Output of Assembler Instructions */ - -/* A C initializer containing the assembler's names for the machine - registers, each one as a C string constant. This is what - translates register numbers in the compiler into assembler - language. */ - -#define REGISTER_NAMES \ -{ \ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "sp", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", \ - "a0", "a1", \ - "ap", \ - "f0", "f1", "c", \ -} - -/* If defined, a C initializer for an array of structures containing - a name and a register number. This macro defines additional names - for hard registers, thus allowing the `asm' option in declarations - to refer to registers using alternate names. */ -#define ADDITIONAL_REGISTER_NAMES \ -{ \ - "r15", STACK_POINTER_REGNUM, \ - "repeat", REPEAT_REGNUM, \ - "carry", CARRY_REGNUM, \ -} - - -/* -`ASM_OUTPUT_OPCODE (STREAM, PTR)' - Define this macro if you are using an unusual assembler that - requires different names for the machine instructions. - - The definition is a C statement or statements which output an - assembler instruction opcode to the stdio stream STREAM. The - macro-operand PTR is a variable of type `char *' which points to - the opcode name in its "internal" form--the form that is written - in the machine description. The definition should output the - opcode name to STREAM, performing any translation you desire, and - increment the variable PTR to point at the end of the opcode so - that it will not be output twice. - - In fact, your macro definition may process less than the entire - opcode name, or more than the opcode name; but if you want to - process text that includes `%'-sequences to substitute operands, - you must take care of the substitution yourself. Just be sure to - increment PTR over whatever text should not be output normally. - - If you need to look at the operand values, they can be found as the - elements of `recog_operand'. - - If the macro definition does nothing, the instruction is output in - the usual way. - -`FINAL_PRESCAN_INSN (INSN, OPVEC, NOPERANDS)' - If defined, a C statement to be executed just prior to the output - of assembler code for INSN, to modify the extracted operands so - they will be output differently. - - Here the argument OPVEC is the vector containing the operands - extracted from INSN, and NOPERANDS is the number of elements of - the vector which contain meaningful data for this insn. The - contents of this vector are what will be used to convert the insn - template into assembler code, so you can change the assembler - output by changing the contents of the vector. - - This macro is useful when various assembler syntaxes share a single - file of instruction patterns; by defining this macro differently, - you can cause a large class of instructions to be output - differently (such as with rearranged operands). Naturally, - variations in assembler syntax affecting individual insn patterns - ought to be handled by writing conditional output routines in - those patterns. - - If this macro is not defined, it is equivalent to a null statement. - -`FINAL_PRESCAN_LABEL' - If defined, `FINAL_PRESCAN_INSN' will be called on each - `CODE_LABEL'. In that case, OPVEC will be a null pointer and - NOPERANDS will be zero. -*/ - -/* 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. */ - -#define PRINT_OPERAND(STREAM, X, CODE) print_operand (STREAM, X, CODE) - -/* A C expression which evaluates to true if CODE is a valid - punctuation character for use in the `PRINT_OPERAND' macro. If - `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no - punctuation characters (except for the standard one, `%') are used - in this way. */ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '|' || (CODE) == '.') - -/* A C compound statement to output to stdio stream STREAM the - assembler syntax for an instruction operand that is a memory - reference whose address is X. X is an RTL expression. - - On some machines, the syntax for a symbolic address depends on the - section that the address refers to. On these machines, define the - macro `ENCODE_SECTION_INFO' to store the information into the - `symbol_ref', and then check for it here. *Note Assembler - Format::. */ - -#define PRINT_OPERAND_ADDRESS(STREAM, X) print_operand_address (STREAM, X) - -/* -`DBR_OUTPUT_SEQEND(FILE)' - 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. - -`REGISTER_PREFIX' -`LOCAL_LABEL_PREFIX' -`USER_LABEL_PREFIX' -`IMMEDIATE_PREFIX' - If defined, C string expressions to be used for the `%R', `%L', - `%U', and `%I' options of `asm_fprintf' (see `final.c'). These - are useful when a single `md' file must support multiple assembler - formats. In that case, the various `tm.h' files can define these - macros differently. - -`ASSEMBLER_DIALECT' - If your target supports multiple dialects of assembler language - (such as different opcodes), define this macro as a C expression - that gives the numeric index of the assembler language dialect to - use, with zero as the first variant. - - If this macro is defined, you may use - `{option0|option1|option2...}' constructs in the output templates - of patterns (*note Output Template::.) or in the first argument of - `asm_fprintf'. This construct outputs `option0', `option1' or - `option2', etc., if the value of `ASSEMBLER_DIALECT' is zero, one - or two, etc. Any special characters within these strings retain - their usual meaning. - - If you do not define this macro, the characters `{', `|' and `}' - do not have any special meaning when used in templates or operands - to `asm_fprintf'. - - Define the macros `REGISTER_PREFIX', `LOCAL_LABEL_PREFIX', - `USER_LABEL_PREFIX' and `IMMEDIATE_PREFIX' if you can express the - variations in assemble language syntax with that mechanism. Define - `ASSEMBLER_DIALECT' and use the `{option0|option1}' syntax if the - syntax variant are larger and involve such things as different - opcodes or operand order. -*/ - -/* A C expression to output to STREAM some assembler code which will - push hard register number REGNO onto the stack. The code need not - be optimal, since this macro is used only when profiling. */ - -#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \ - fprintf (STREAM, "\tsubi %s,-2\n\tst %s,@-%s\n", \ - reg_names[STACK_POINTER_REGNUM], \ - reg_names[REGNO], \ - reg_names[STACK_POINTER_REGNUM]) - -/* A C expression to output to STREAM some assembler code which will - pop hard register number REGNO off of the stack. The code need - not be optimal, since this macro is used only when profiling. */ - -#define ASM_OUTPUT_REG_POP(STREAM, REGNO) \ - fprintf (STREAM, "\tld %s,@%s+\n\taddi %s,2\n", \ - reg_names[REGNO], \ - reg_names[STACK_POINTER_REGNUM], \ - reg_names[STACK_POINTER_REGNUM]) - - -/* Output of Dispatch Tables */ - -/* A C statement to output to the stdio stream STREAM an assembler - pseudo-instruction to generate a difference between two labels. - vALUE and REL are the numbers of two internal labels. The - definitions of these labels are output using - `ASM_OUTPUT_INTERNAL_LABEL', and they must be printed in the same - way here. For example, - - fprintf (STREAM, "\t.word L%d-L%d\n", - VALUE, REL) - - You must provide this macro on machines where the addresses in a - dispatch table are relative to the table's own address. If - defined, GNU CC will also use this macro on all machines when - producing PIC. */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ - fprintf (STREAM, "\t.word .L%d@word-.L%d@word\n", VALUE, REL) - - -/* This macro should be provided on machines where the addresses in a - dispatch table are absolute. - - The definition should be a C statement to output to the stdio - stream STREAM an assembler pseudo-instruction to generate a - reference to a label. VALUE is the number of an internal label - whose definition is output using `ASM_OUTPUT_INTERNAL_LABEL'. */ -#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ - fprintf (STREAM, "\t.word .L%d@word\n", VALUE) - -/* -`ASM_OUTPUT_CASE_LABEL (STREAM, PREFIX, NUM, TABLE)' - Define this if the label before a jump-table needs to be output - specially. The first three arguments are the same as for - `ASM_OUTPUT_INTERNAL_LABEL'; the fourth argument is the jump-table - which follows (a `jump_insn' containing an `addr_vec' or - `addr_diff_vec'). - - This feature is used on system V to output a `swbeg' statement for - the table. - - If this macro is not defined, these labels are output with - `ASM_OUTPUT_INTERNAL_LABEL'. - -`ASM_OUTPUT_CASE_END (STREAM, NUM, TABLE)' - Define this if something special must be output at the end of a - jump-table. The definition should be a C statement to be executed - after the assembler code for the table is written. It should write - the appropriate code to stdio stream STREAM. The argument TABLE - is the jump-table insn, and NUM is the label-number of the - preceding label. - - If this macro is not defined, nothing special is output at the end - of the jump-table. -*/ - - -/* Assembler Commands for Alignment */ - -/* -`LABEL_ALIGN_AFTER_BARRIER(LABEL)' - The alignment (log base 2) to put in front of LABEL, which follows - a BARRIER. - - A C expression to output text to align the location counter in the - way that is desirable at a point in the code that is reached only - by jumping. - - This macro need not be defined if you don't want any special - alignment to be done at such a time. Most machine descriptions do - not currently define the macro. - -`LOOP_ALIGN (LABEL)' - The desired alignment for the location counter at the beginning - of a loop. - - This macro need not be defined if you don't want any special - alignment to be done at such a time. Most machine descriptions do - not currently define the macro. - -`ASM_OUTPUT_SKIP (STREAM, NBYTES)' - A C statement to output to the stdio stream STREAM an assembler - instruction to advance the location counter by NBYTES bytes. - Those bytes should be zero when loaded. NBYTES will be a C - expression of type `int'. - -`ASM_NO_SKIP_IN_TEXT' - Define this macro if `ASM_OUTPUT_SKIP' should not be used in the - text section because it fails put zeros in the bytes that are - skipped. This is true on many Unix systems, where the pseudo-op - to skip bytes produces no-op instructions rather than zeros when - used in the text section. -*/ - -/* A C statement to output to the stdio stream STREAM an assembler - command to advance the location counter to a multiple of 2 to the - POWER bytes. POWER will be a C expression of type `int'. */ - -#define ASM_OUTPUT_ALIGN(STREAM, POWER) \ -do { \ - if ((POWER) != 0) \ - fprintf (STREAM, "\t.align %d\n", (POWER)); \ -} while (0) - - -/* Macros Affecting All Debugging Formats */ - -/* A C expression that returns the DBX register number for the - compiler register number REGNO. In simple cases, the value of this - expression may be REGNO itself. But sometimes there are some - registers that the compiler knows about and DBX does not, or vice - versa. In such cases, some register may need to have one number in - the compiler and another for DBX. - - If two registers have consecutive numbers inside GNU CC, and they - can be used as a pair to hold a multiword value, then they *must* - have consecutive numbers after renumbering with - `DBX_REGISTER_NUMBER'. Otherwise, debuggers will be unable to - access such a pair, because they expect register pairs to be - consecutive in their own numbering scheme. - - If you find yourself defining `DBX_REGISTER_NUMBER' in way that - does not preserve register pairs, then what you must do instead is - redefine the actual register numbering scheme. */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* -`DEBUGGER_AUTO_OFFSET (X)' - A C expression that returns the integer offset value for an - automatic variable having address X (an RTL expression). The - default computation assumes that X is based on the frame-pointer - and gives the offset from the frame-pointer. This is required for - targets that produce debugging output for DBX or COFF-style - debugging output for SDB and allow the frame-pointer to be - eliminated when the `-g' options is used. - -`DEBUGGER_ARG_OFFSET (OFFSET, X)' - A C expression that returns the integer offset value for an - argument having address X (an RTL expression). The nominal offset - is OFFSET. -*/ - -/* A C expression that returns the type of debugging output GNU CC - produces when the user specifies `-g' or `-ggdb'. Define this if - you have arranged for GNU CC to support more than one format of - debugging output. Currently, the allowable values are `DBX_DEBUG', - `SDB_DEBUG', `DWARF_DEBUG', and `XCOFF_DEBUG'. - - The value of this macro only affects the default debugging output; - the user can always get a specific type of output by using - `-gstabs', `-gcoff', `-gdwarf', or `-gxcoff'. */ -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG - -/* Disable Dwarf2 right now, since it wants a fixed size for DOUBLE and INT */ -#undef DWARF2_DEBUGGING_INFO - - -/* Specific Options for DBX Output */ - -/* -`DBX_DEBUGGING_INFO' - Define this macro if GNU CC should produce debugging output for DBX - in response to the `-g' option. - -`XCOFF_DEBUGGING_INFO' - Define this macro if GNU CC should produce XCOFF format debugging - output in response to the `-g' option. This is a variant of DBX - format. - -`DEFAULT_GDB_EXTENSIONS' - Define this macro to control whether GNU CC should by default - generate GDB's extended version of DBX debugging information - (assuming DBX-format debugging information is enabled at all). If - you don't define the macro, the default is 1: always generate the - extended information if there is any occasion to. - -`DEBUG_SYMS_TEXT' - Define this macro if all `.stabs' commands should be output while - in the text section. - -`ASM_STABS_OP' - A C string constant naming the assembler pseudo op to use instead - of `.stabs' to define an ordinary debugging symbol. If you don't - define this macro, `.stabs' is used. This macro applies only to - DBX debugging information format. - -`ASM_STABD_OP' - A C string constant naming the assembler pseudo op to use instead - of `.stabd' to define a debugging symbol whose value is the current - location. If you don't define this macro, `.stabd' is used. This - macro applies only to DBX debugging information format. - -`ASM_STABN_OP' - A C string constant naming the assembler pseudo op to use instead - of `.stabn' to define a debugging symbol with no name. If you - don't define this macro, `.stabn' is used. This macro applies - only to DBX debugging information format. - -`DBX_NO_XREFS' - Define this macro if DBX on your system does not support the - construct `xsTAGNAME'. On some systems, this construct is used to - describe a forward reference to a structure named TAGNAME. On - other systems, this construct is not supported at all. - -`DBX_CONTIN_LENGTH' - A symbol name in DBX-format debugging information is normally - continued (split into two separate `.stabs' directives) when it - exceeds a certain length (by default, 80 characters). On some - operating systems, DBX requires this splitting; on others, - splitting must not be done. You can inhibit splitting by defining - this macro with the value zero. You can override the default - splitting-length by defining this macro as an expression for the - length you desire. - -`DBX_CONTIN_CHAR' - Normally continuation is indicated by adding a `\' character to - the end of a `.stabs' string when a continuation follows. To use - a different character instead, define this macro as a character - constant for the character you want to use. Do not define this - macro if backslash is correct for your system. - -`DBX_STATIC_STAB_DATA_SECTION' - Define this macro if it is necessary to go to the data section - before outputting the `.stabs' pseudo-op for a non-global static - variable. - -`DBX_TYPE_DECL_STABS_CODE' - The value to use in the "code" field of the `.stabs' directive for - a typedef. The default is `N_LSYM'. - -`DBX_STATIC_CONST_VAR_CODE' - The value to use in the "code" field of the `.stabs' directive for - a static variable located in the text section. DBX format does not - provide any "right" way to do this. The default is `N_FUN'. - -`DBX_REGPARM_STABS_CODE' - The value to use in the "code" field of the `.stabs' directive for - a parameter passed in registers. DBX format does not provide any - "right" way to do this. The default is `N_RSYM'. - -`DBX_REGPARM_STABS_LETTER' - The letter to use in DBX symbol data to identify a symbol as a - parameter passed in registers. DBX format does not customarily - provide any way to do this. The default is `'P''. - -`DBX_MEMPARM_STABS_LETTER' - The letter to use in DBX symbol data to identify a symbol as a - stack parameter. The default is `'p''. - -`DBX_FUNCTION_FIRST' - Define this macro if the DBX information for a function and its - arguments should precede the assembler code for the function. - Normally, in DBX format, the debugging information entirely - follows the assembler code. - -`DBX_LBRAC_FIRST' - Define this macro if the `N_LBRAC' symbol for a block should - precede the debugging information for variables and functions - defined in that block. Normally, in DBX format, the `N_LBRAC' - symbol comes first. - -`DBX_BLOCKS_FUNCTION_RELATIVE' - Define this macro if the value of a symbol describing the scope of - a block (`N_LBRAC' or `N_RBRAC') should be relative to the start - of the enclosing function. Normally, GNU C uses an absolute - address. - -`DBX_USE_BINCL' - Define this macro if GNU C should generate `N_BINCL' and `N_EINCL' - stabs for included header files, as on Sun systems. This macro - also directs GNU C to output a type number as a pair of a file - number and a type number within the file. Normally, GNU C does not - generate `N_BINCL' or `N_EINCL' stabs, and it outputs a single - number for a type number. -*/ - - - /* Open-Ended Hooks for DBX Format */ - -/* -`DBX_OUTPUT_LBRAC (STREAM, NAME)' - Define this macro to say how to output to STREAM the debugging - information for the start of a scope level for variable names. The - argument NAME is the name of an assembler symbol (for use with - `assemble_name') whose value is the address where the scope begins. - -`DBX_OUTPUT_RBRAC (STREAM, NAME)' - Like `DBX_OUTPUT_LBRAC', but for the end of a scope level. - -`DBX_OUTPUT_ENUM (STREAM, TYPE)' - Define this macro if the target machine requires special handling - to output an enumeration type. The definition should be a C - statement (sans semicolon) to output the appropriate information - to STREAM for the type TYPE. - -`DBX_OUTPUT_FUNCTION_END (STREAM, FUNCTION)' - Define this macro if the target machine requires special output at - the end of the debugging information for a function. The - definition should be a C statement (sans semicolon) to output the - appropriate information to STREAM. FUNCTION is the - `FUNCTION_DECL' node for the function. - -`DBX_OUTPUT_STANDARD_TYPES (SYMS)' - Define this macro if you need to control the order of output of the - standard data types at the beginning of compilation. The argument - SYMS is a `tree' which is a chain of all the predefined global - symbols, including names of data types. - - Normally, DBX output starts with definitions of the types for - integers and characters, followed by all the other predefined - types of the particular language in no particular order. - - On some machines, it is necessary to output different particular - types first. To do this, define `DBX_OUTPUT_STANDARD_TYPES' to - output those symbols in the necessary order. Any predefined types - that you don't explicitly output will be output afterward in no - particular order. - - Be careful not to define this macro so that it works only for C. - There are no global variables to access most of the built-in - types, because another language may have another set of types. - The way to output a particular type is to look through SYMS to see - if you can find it. Here is an example: - - { - tree decl; - for (decl = syms; decl; decl = TREE_CHAIN (decl)) - if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), - "long int")) - dbxout_symbol (decl); - ... - } - - This does nothing if the expected type does not exist. - - See the function `init_decl_processing' in `c-decl.c' to find the - names to use for all the built-in C types. -*/ - - -/* File Names in DBX Format */ - -/* -`DBX_WORKING_DIRECTORY' - Define this if DBX wants to have the current directory recorded in - each object file. - - Note that the working directory is always recorded if GDB - extensions are enabled. - -`DBX_OUTPUT_MAIN_SOURCE_FILENAME (STREAM, NAME)' - A C statement to output DBX debugging information to the stdio - stream STREAM which indicates that file NAME is the main source - file--the file specified as the input file for compilation. This - macro is called only once, at the beginning of compilation. - - This macro need not be defined if the standard form of output for - DBX debugging information is appropriate. - -`DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (STREAM, NAME)' - A C statement to output DBX debugging information to the stdio - stream STREAM which indicates that the current directory during - compilation is named NAME. - - This macro need not be defined if the standard form of output for - DBX debugging information is appropriate. - -`DBX_OUTPUT_MAIN_SOURCE_FILE_END (STREAM, NAME)' - A C statement to output DBX debugging information at the end of - compilation of the main source file NAME. - - If you don't define this macro, nothing special is output at the - end of compilation, which is correct for most machines. - -`DBX_OUTPUT_SOURCE_FILENAME (STREAM, NAME)' - A C statement to output DBX debugging information to the stdio - stream STREAM which indicates that file NAME is the current source - file. This output is generated each time input shifts to a - different source file as a result of `#include', the end of an - included file, or a `#line' command. - - This macro need not be defined if the standard form of output for - DBX debugging information is appropriate. -*/ - - -/* Macros for SDB and DWARF Output */ - -/* -`SDB_DEBUGGING_INFO' - Define this macro if GNU CC should produce COFF-style debugging - output for SDB in response to the `-g' option. - -`DWARF_DEBUGGING_INFO' - Define this macro if GNU CC should produce dwarf format debugging - output in response to the `-g' option. - -`PUT_SDB_...' - Define these macros to override the assembler syntax for the - special SDB assembler directives. See `sdbout.c' for a list of - these macros and their arguments. If the standard syntax is used, - you need not define them yourself. - -`SDB_DELIM' - Some assemblers do not support a semicolon as a delimiter, even - between SDB assembler directives. In that case, define this macro - to be the delimiter to use (usually `\n'). It is not necessary to - define a new set of `PUT_SDB_OP' macros if this is the only change - required. - -`SDB_GENERATE_FAKE' - Define this macro to override the usual method of constructing a - dummy name for anonymous structure and union types. See - `sdbout.c' for more information. - -`SDB_ALLOW_UNKNOWN_REFERENCES' - Define this macro to allow references to unknown structure, union, - or enumeration tags to be emitted. Standard COFF does not allow - handling of unknown references, MIPS ECOFF has support for it. - -`SDB_ALLOW_FORWARD_REFERENCES' - Define this macro to allow references to structure, union, or - enumeration tags that have not yet been seen to be handled. Some - assemblers choke if forward tags are used, while some require it. -*/ - - -/* Miscellaneous Parameters */ - -/* Use the software emulation of floating point. */ -#define REAL_ARITHMETIC - -/* Define this if you have defined special-purpose predicates in the - file `MACHINE.c'. This macro is called within an initializer of an - array of structures. The first field in the structure is the name - of a predicate and the second field is an array of rtl codes. For - each predicate, list all rtl codes that can be in expressions - matched by the predicate. The list should have a trailing comma. */ - -#define PREDICATE_CODES \ -{ "short_memory_operand", { MEM }}, \ -{ "reg_or_0_operand", { REG, SUBREG, CONST_INT }}, \ -{ "arith16_operand", { REG, SUBREG, CONST_INT }}, \ -{ "arith32_operand", { REG, SUBREG, CONST_INT }}, \ -{ "arith64_operand", { REG, SUBREG, CONST_INT, CONST_DOUBLE }}, \ -{ "arith_4bit_operand", { REG, SUBREG, CONST_INT }}, \ -{ "arith_lower0_operand", { REG, SUBREG, CONST_INT }}, \ -{ "arith_nonnegative_operand", { REG, SUBREG, CONST_INT }}, \ -{ "gpr_operand", { REG, SUBREG }}, \ -{ "accum_operand", { REG, SUBREG }}, \ -{ "ldi_shift_operand", { CONST_INT }}, \ -{ "cond_move_operand", { REG, SUBREG, CONST_INT, MEM }}, \ -{ "cond_exec_operand", { REG, SUBREG, CONST_INT, MEM }}, \ -{ "pc_or_label_operand", { PC, LABEL_REF }}, \ -{ "carry_operand", { REG }}, \ -{ "f0_operand", { REG }}, \ -{ "f1_operand", { REG }}, \ -{ "f_operand", { REG }}, \ -{ "carry_operand", { REG }}, \ -{ "f0_compare_operator", { EQ, NE }}, \ -{ "compare_operator", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \ - LTU, LEU }}, \ -{ "equality_operator", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \ - LTU, LEU }}, \ -{ "unsigned_compare_operator", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \ - LTU, LEU }}, \ -{ "signed_compare_operator", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \ - LTU, LEU }}, \ -{ "unary_parallel_operator", { ABS, NEG, NOT, REG, SUBREG, \ - CONST_INT, MEM, \ - SIGN_EXTEND, ZERO_EXTEND }}, \ -{ "binary_parallel_operator", { PLUS, MINUS, MULT, \ - AND, IOR, XOR, \ - ASHIFT, ASHIFTRT, LSHIFTRT }}, \ -{ "extend_parallel_operator", { SIGN_EXTEND, ZERO_EXTEND }}, \ -{ "minmax_parallel_operator", { SMIN, SMAX }}, - -/* An alias for a machine mode name. This is the machine mode that - elements of a jump-table should have. */ -#define CASE_VECTOR_MODE Pmode - -/* -`CASE_VECTOR_PC_RELATIVE' - Define this macro if jump-tables should contain relative addresses. - -`CASE_DROPS_THROUGH' - Define this if control falls through a `case' insn when the index - value is out of range. This means the specified default-label is - actually ignored by the `case' insn proper. - -`CASE_VALUES_THRESHOLD' - Define this to be the smallest number of different values for - which it is best to use a jump-table instead of a tree of - conditional branches. The default is four for machines with a - `casesi' instruction and five otherwise. This is best for most - machines. -*/ - -/* Define this macro if operations between registers with integral - mode smaller than a word are always performed on the entire - register. Most RISC machines have this property and most CISC - machines do not. */ -#define WORD_REGISTER_OPERATIONS 1 - -/* Define this macro to be a C expression indicating when insns that - read memory in MODE, an integral mode narrower than a word, set the - bits outside of MODE to be either the sign-extension or the - zero-extension of the data read. Return `SIGN_EXTEND' for values - of MODE for which the insn sign-extends, `ZERO_EXTEND' for which - it zero-extends, and `NIL' for other modes. - - This macro is not called with MODE non-integral or with a width - greater than or equal to `BITS_PER_WORD', so you may return any - value in this case. Do not define this macro if it would always - return `NIL'. On machines where this macro is defined, you will - normally define it as the constant `SIGN_EXTEND' or `ZERO_EXTEND'. */ -#define LOAD_EXTEND_OP(MODE) (((MODE) == QImode) ? ZERO_EXTEND : NIL) - -/* An alias for a tree code that should be used by default for - conversion of floating point values to fixed point. Normally, - `FIX_ROUND_EXPR' is used. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - - -/* Define this macro if the same instructions that convert a floating - point number to a signed fixed point number also convert validly - to an unsigned one. */ -/* #define FIXUNS_TRUNC_LIKE_FIX_TRUNC */ - - -/* An alias for a tree code that is the easiest kind of division to - compile code for in the general case. It may be `TRUNC_DIV_EXPR', - `FLOOR_DIV_EXPR', `CEIL_DIV_EXPR' or `ROUND_DIV_EXPR'. These four - division operators differ in how they round the result to an - integer. `EASY_DIV_EXPR' is used when it is permissible to use - any of those kinds of division and the choice should be made on - the basis of efficiency. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* The maximum number of bytes that a single instruction can move - quickly from memory to memory. */ -#define MOVE_MAX 4 - - -/* The maximum number of bytes that a single instruction can move - quickly from memory to memory. If this is undefined, the default - is `MOVE_MAX'. Otherwise, it is the constant value that is the - largest value that `MOVE_MAX' can have at run-time. */ -/* #define MAX_MOVE_MAX */ - -/* -`SHIFT_COUNT_TRUNCATED' - A C expression that is nonzero if on this machine the number of - bits actually used for the count of a shift operation is equal to - the number of bits needed to represent the size of the object - being shifted. When this macro is non-zero, the compiler will - assume that it is safe to omit a sign-extend, zero-extend, and - certain bitwise `and' instructions that truncates the count of a - shift operation. On machines that have instructions that act on - bitfields at variable positions, which may include `bit test' - instructions, a nonzero `SHIFT_COUNT_TRUNCATED' also enables - deletion of truncations of the values that serve as arguments to - bitfield instructions. - - If both types of instructions truncate the count (for shifts) and - position (for bitfield operations), or if no variable-position - bitfield instructions exist, you should define this macro. - - However, on some machines, such as the 80386 and the 680x0, - truncation only applies to shift operations and not the (real or - pretended) bitfield operations. Define `SHIFT_COUNT_TRUNCATED' to - be zero on such machines. Instead, add patterns to the `md' file - that include the implied truncation of the shift instructions. - - You need not define this macro if it would always have the value - of zero. -*/ - -/* A C expression which is nonzero if on this machine it is safe to - "convert" an integer of INPREC bits to one of OUTPREC bits (where - OUTPREC is smaller than INPREC) by merely operating on it as if it - had only OUTPREC bits. - - On many machines, this expression can be 1. - - When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for - modes for which `MODES_TIEABLE_P' is 0, suboptimal code can result. - If this is the case, making `TRULY_NOOP_TRUNCATION' return 0 in - such cases may improve things. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - - -/* A C expression describing the value returned by a comparison - operator with an integral mode and stored by a store-flag - instruction (`sCOND') when the condition is true. This - description must apply to *all* the `sCOND' patterns and all the - comparison operators whose results have a `MODE_INT' mode. - - A value of 1 or -1 means that the instruction implementing the - comparison operator returns exactly 1 or -1 when the comparison is - true and 0 when the comparison is false. Otherwise, the value - indicates which bits of the result are guaranteed to be 1 when the - comparison is true. This value is interpreted in the mode of the - comparison operation, which is given by the mode of the first - operand in the `sCOND' pattern. Either the low bit or the sign - bit of `STORE_FLAG_VALUE' be on. Presently, only those bits are - used by the compiler. - - If `STORE_FLAG_VALUE' is neither 1 or -1, the compiler will - generate code that depends only on the specified bits. It can also - replace comparison operators with equivalent operations if they - cause the required bits to be set, even if the remaining bits are - undefined. For example, on a machine whose comparison operators - return an `SImode' value and where `STORE_FLAG_VALUE' is defined as - `0x80000000', saying that just the sign bit is relevant, the - expression - - (ne:SI (and:SI X (const_int POWER-OF-2)) (const_int 0)) - - can be converted to - - (ashift:SI X (const_int N)) - - where N is the appropriate shift count to move the bit being - tested into the sign bit. - - There is no way to describe a machine that always sets the - low-order bit for a true value, but does not guarantee the value - of any other bits, but we do not know of any machine that has such - an instruction. If you are trying to port GNU CC to such a - machine, include an instruction to perform a logical-and of the - result with 1 in the pattern for the comparison operators and let - us know (*note How to Report Bugs: Bug Reporting.). - - Often, a machine will have multiple instructions that obtain a - value from a comparison (or the condition codes). Here are rules - to guide the choice of value for `STORE_FLAG_VALUE', and hence the - instructions to be used: - - * Use the shortest sequence that yields a valid definition for - `STORE_FLAG_VALUE'. It is more efficient for the compiler to - "normalize" the value (convert it to, e.g., 1 or 0) than for - the comparison operators to do so because there may be - opportunities to combine the normalization with other - operations. - - * For equal-length sequences, use a value of 1 or -1, with -1 - being slightly preferred on machines with expensive jumps and - 1 preferred on other machines. - - * As a second choice, choose a value of `0x80000001' if - instructions exist that set both the sign and low-order bits - but do not define the others. - - * Otherwise, use a value of `0x80000000'. - - Many machines can produce both the value chosen for - `STORE_FLAG_VALUE' and its negation in the same number of - instructions. On those machines, you should also define a pattern - for those cases, e.g., one matching - - (set A (neg:M (ne:M B C))) - - Some machines can also perform `and' or `plus' operations on - condition code values with less instructions than the corresponding - `sCOND' insn followed by `and' or `plus'. On those machines, - define the appropriate patterns. Use the names `incscc' and - `decscc', respectively, for the patterns which perform `plus' or - `minus' operations on condition code values. See `rs6000.md' for - some examples. The GNU Superoptizer can be used to find such - instruction sequences on other machines. - - You need not define `STORE_FLAG_VALUE' if the machine has no - store-flag instructions. */ -#define STORE_FLAG_VALUE 1 - -/* -`FLOAT_STORE_FLAG_VALUE' - A C expression that gives a non-zero floating point value that is - returned when comparison operators with floating-point results are - true. Define this macro on machine that have comparison - operations that return floating-point values. If there are no - such operations, do not define this macro. -*/ - -/* An alias for the machine mode for pointers. On most machines, - define this to be the integer mode corresponding to the width of a - hardware pointer; `SImode' on 32-bit machine or `DImode' on 64-bit - machines. On some machines you must define this to be one of the - partial integer modes, such as `PSImode'. - - The width of `Pmode' must be at least as large as the value of - `POINTER_SIZE'. If it is not equal, you must define the macro - `POINTERS_EXTEND_UNSIGNED' to specify how pointers are extended to - `Pmode'. */ -#define Pmode HImode - -/* An alias for the machine mode used for memory references to - functions being called, in `call' RTL expressions. On most - machines this should be `QImode'. */ -#define FUNCTION_MODE Pmode - -/* -`INTEGRATE_THRESHOLD (DECL)' - A C expression for the maximum number of instructions above which - the function DECL should not be inlined. DECL is a - `FUNCTION_DECL' node. - - The default definition of this macro is 64 plus 8 times the number - of arguments that the function accepts. Some people think a larger - threshold should be used on RISC machines. - -`SCCS_DIRECTIVE' - Define this if the preprocessor should ignore `#sccs' directives - and print no error message. - -`NO_IMPLICIT_EXTERN_C' - Define this macro if the system header files support C++ as well - as C. This macro inhibits the usual method of using system header - files in C++, which is to pretend that the file's contents are - enclosed in `extern "C" {...}'. - -`HANDLE_PRAGMA (STREAM, NODE)' - Define this macro if you want to implement any pragmas. If - defined, it is a C expression whose value is 1 if the pragma was - handled by the function. The argument STREAM is the stdio input - stream from which the source text can be read. NODE is the tree - node for the identifier after the `#pragma'. - - It is generally a bad idea to implement new uses of `#pragma'. The - only reason to define this macro is for compatibility with other - compilers that do support `#pragma' for the sake of any user - programs which already use it. - -`VALID_MACHINE_DECL_ATTRIBUTE (DECL, ATTRIBUTES, IDENTIFIER, ARGS)' - If defined, a C expression whose value is nonzero if IDENTIFIER - with arguments ARGS is a valid machine specific attribute for DECL. - The attributes in ATTRIBUTES have previously been assigned to DECL. - -`VALID_MACHINE_TYPE_ATTRIBUTE (TYPE, ATTRIBUTES, IDENTIFIER, ARGS)' - If defined, a C expression whose value is nonzero if IDENTIFIER - with arguments ARGS is a valid machine specific attribute for TYPE. - The attributes in ATTRIBUTES have previously been assigned to TYPE. - -`COMP_TYPE_ATTRIBUTES (TYPE1, TYPE2)' - If defined, a C expression whose value is zero if the attributes on - TYPE1 and TYPE2 are incompatible, one if they are compatible, and - two if they are nearly compatible (which causes a warning to be - generated). - -`SET_DEFAULT_TYPE_ATTRIBUTES (TYPE)' - If defined, a C statement that assigns default attributes to newly - defined TYPE. - -`MERGE_MACHINE_TYPE_ATTRIBUTES (TYPE1, TYPE2)' - Define this macro if the merging of type attributes needs special - handling. If defined, the result is a list of the combined - TYPE_ATTRIBUTES of TYPE1 and TYPE2. It is assumed that comptypes - has already been called and returned 1. - -`MERGE_MACHINE_DECL_ATTRIBUTES (OLDDECL, NEWDECL)' - Define this macro if the merging of decl attributes needs special - handling. If defined, the result is a list of the combined - DECL_MACHINE_ATTRIBUTES of OLDDECL and NEWDECL. NEWDECL is a - duplicate declaration of OLDDECL. Examples of when this is needed - are when one attribute overrides another, or when an attribute is - nullified by a subsequent definition. - -`DOLLARS_IN_IDENTIFIERS' - Define this macro to control use of the character `$' in identifier - names. The value should be 0, 1, or 2. 0 means `$' is not allowed - by default; 1 means it is allowed by default if `-traditional' is - used; 2 means it is allowed by default provided `-ansi' is not - used. 1 is the default; there is no need to define this macro in - that case. - -`NO_DOLLAR_IN_LABEL' - Define this macro if the assembler does not accept the character - `$' in label names. By default constructors and destructors in - G++ have `$' in the identifiers. If this macro is defined, `.' is - used instead. - -`NO_DOT_IN_LABEL' - Define this macro if the assembler does not accept the character - `.' in label names. By default constructors and destructors in G++ - have names that use `.'. If this macro is defined, these names - are rewritten to avoid `.'. - -`DEFAULT_MAIN_RETURN' - Define this macro if the target system expects every program's - `main' function to return a standard "success" value by default - (if no other value is explicitly returned). - - The definition should be a C statement (sans semicolon) to - generate the appropriate rtl instructions. It is used only when - compiling the end of `main'. - -`HAVE_ATEXIT' - Define this if the target system supports the function `atexit' - from the ANSI C standard. If this is not defined, and - `INIT_SECTION_ASM_OP' is not defined, a default `exit' function - will be provided to support C++. - -`EXIT_BODY' - Define this if your `exit' function needs to do something besides - calling an external function `_cleanup' before terminating with - `_exit'. The `EXIT_BODY' macro is only needed if netiher - `HAVE_ATEXIT' nor `INIT_SECTION_ASM_OP' are defined. - -`INSN_SETS_ARE_DELAYED (INSN)' - Define this macro as a C expression that is nonzero if it is safe - for the delay slot scheduler to place instructions in the delay - slot of INSN, even if they appear to use a resource set or - clobbered in INSN. INSN is always a `jump_insn' or an `insn'; GNU - CC knows that every `call_insn' has this behavior. On machines - where some `insn' or `jump_insn' is really a function call and - hence has this behavior, you should define this macro. - - You need not define this macro if it would always return zero. - -`INSN_REFERENCES_ARE_DELAYED (INSN)' - Define this macro as a C expression that is nonzero if it is safe - for the delay slot scheduler to place instructions in the delay - slot of INSN, even if they appear to set or clobber a resource - referenced in INSN. INSN is always a `jump_insn' or an `insn'. - On machines where some `insn' or `jump_insn' is really a function - call and its operands are registers whose use is actually in the - subroutine it calls, you should define this macro. Doing so - allows the delay slot scheduler to move instructions which copy - arguments into the argument registers into the delay slot of INSN. - - You need not define this macro if it would always return zero. - -`MACHINE_DEPENDENT_REORG (INSN)' - In rare cases, correct code generation requires extra machine - dependent processing between the second jump optimization pass and - delayed branch scheduling. On those machines, define this macro - as a C statement to act on the code starting at INSN. -*/ - - -/* Hack to omit compiling L_shtab in libgcc2. Shtab is an array mapping - n -> 1<> shift); - operands[3] = GEN_INT (shift); -}") - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) != REG) - operands[1] = force_reg (SImode, operands[1]); - /* reload might ask us to use something like (subreg:SI (reg/v:DI 0 r0) 1) . - Example: unsorted/dilayout.c -O1 */ - if (reload_in_progress) - { - int reg0 = true_regnum (operands[0]); - int reg1 = true_regnum (operands[1]); - - if ((reg0 >= 0 && reg0 < FIRST_PSEUDO_REGISTER && (reg0 & 1)) - || (reg1 >= 0 && reg1 < FIRST_PSEUDO_REGISTER && (reg1 & 1))) - { - rtx high, low; - int word0 = 0, word1 = 0; - - if (GET_CODE (operands[0]) == SUBREG) - { - word0 = SUBREG_WORD (operands[0]); - operands[0] = SUBREG_REG (operands[0]); - } - if (GET_CODE (operands[1]) == SUBREG) - { - word1 = SUBREG_WORD (operands[1]); - operands[1] = SUBREG_REG (operands[1]); - } - high = gen_movhi (gen_rtx (SUBREG, HImode, operands[0], word0), - gen_rtx (SUBREG, HImode, operands[1], word1)); - operands[0] = copy_rtx (operands[0]); - operands[1] = copy_rtx (operands[1]); - low = gen_movhi (gen_rtx (SUBREG, HImode, operands[0], word0 + 1), - gen_rtx (SUBREG, HImode, operands[1], word1 + 1)); - /* Check for overlap. We know this is big endian. */ - if (reg0 == reg1 + 1) - { - emit_insn (low); - emit_insn (high); - } - else - { - emit_insn (high); - emit_insn (low); - } - DONE; - } - } -}") - -(define_insn "*movsi_internal" - [(set (match_operand:SI 0 "general_operand" "=e,e,e,Q,m,a,a,e,e,a") - (match_operand:SI 1 "general_operand" "e,Q,m,e,e,e,a,a,i,O"))] - "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" - "* return emit_move_2words (operands[0], operands[1], insn);" - [(set_attr "type" "either,mu,long,mu,long,mu,iu,mu,long,iu") - (set_attr "length" "1,1,2,1,2,1,1,1,4,1")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - " -{ - operands[2] = d10v_subword (operands[0], 0, HImode, SImode); - operands[3] = d10v_subword (operands[0], 1, HImode, SImode); - operands[4] = GEN_INT (SIGN_EXTEND_SHORT (INTVAL (operands[1]) >> 16)); - operands[5] = GEN_INT (SIGN_EXTEND_SHORT (INTVAL (operands[1]))); -}") - -(define_insn "reload_insi" - [(set (match_operand:SI 0 "register_operand" "=a,a") - (match_operand:SI 1 "memory_operand" "Q,m")) - (clobber (match_operand:SI 2 "gpr_operand" "=e,e"))] - "TARGET_ACCUM" - "#" - [(set_attr "type" "long,long") - (set_attr "length" "2,3")]) - -(define_insn "reload_outsi" - [(set (match_operand:SI 0 "memory_operand" "=Q,m") - (match_operand:SI 1 "accum_operand" "a,a")) - (clobber (match_operand:SI 2 "gpr_operand" "=&e,e"))] - "TARGET_ACCUM" - "#" - [(set_attr "type" "long,long") - (set_attr "length" "2,3")]) - -(define_split - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" "")) - (clobber (match_operand:SI 2 "gpr_operand" ""))] - "TARGET_ACCUM && reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) (match_dup 2))] - "") - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - if (GET_CODE (operands[0]) != REG) - operands[1] = force_reg (SFmode, operands[1]); -}") - -(define_insn "*movsf_internal" - [(set (match_operand:SF 0 "general_operand" "=e,e,e,Q,m,e") - (match_operand:SF 1 "general_operand" "e,Q,m,e,e,F"))] - "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)" - "* return emit_move_2words (operands[0], operands[1], insn);" - [(set_attr "type" "either,mu,long,mu,long,long") - (set_attr "length" "1,1,2,1,2,4")]) - -(define_split - [(set (match_operand:SF 0 "gpr_operand" "") - (match_operand:SF 1 "const_double_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - " -{ - REAL_VALUE_TYPE rv; - HOST_WIDE_INT value; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_SINGLE (rv, value); - - operands[2] = d10v_subword (operands[0], 0, HImode, SFmode); - operands[3] = d10v_subword (operands[0], 1, HImode, SFmode); - operands[4] = GEN_INT (SIGN_EXTEND_SHORT (value >> 16)); - operands[5] = GEN_INT (SIGN_EXTEND_SHORT (value)); -}") - -(define_expand "movdi" - [(parallel [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" "")) - (clobber (match_scratch:SI 2 "")) - (clobber (match_scratch:HI 3 ""))])] - "" - "") - -(define_insn "*movdi_internal" - [(set (match_operand:DI 0 "general_operand" "=e,e,o,e,o,o,o,??o,??o") - (match_operand:DI 1 "general_operand" "e,o,e,iF,o,OG,iF,o,o")) - (clobber (match_scratch:SI 2 "=X,X,X,X,&e,X,&e,X,e")) - (clobber (match_scratch:HI 3 "=X,X,X,X,X,X,X,&d,X"))] - "" - "* return emit_move_4words (operands[0], operands[1], operands[2], operands[3], insn);" - [(set_attr "type" "long,long,long,long,long,long,long,long,long") - (set_attr "length" "4,4,4,4,8,8,16,32,32")]) - -(define_expand "movdf" - [(parallel [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" "")) - (clobber (match_scratch:SI 2 "")) - (clobber (match_scratch:HI 3 ""))])] - "" - "") - -(define_insn "*movdf_internal" - [(set (match_operand:DF 0 "general_operand" "=e,e,o,e,o,o,o,??o,??o") - (match_operand:DF 1 "general_operand" "e,o,e,iF,o,OG,F,o,o")) - (clobber (match_scratch:SI 2 "=X,X,X,X,&e,X,&e,X,e")) - (clobber (match_scratch:HI 3 "=X,X,X,X,X,X,X,&d,X"))] - "" - "* return emit_move_4words (operands[0], operands[1], operands[2], operands[3], insn);" - [(set_attr "type" "long,long,long,long,long,long,long,long,long") - (set_attr "length" "4,4,4,4,8,8,16,32,32")]) - -(define_insn "movcc" - [(set (match_operand:CC 0 "general_operand" "=x") - (match_operand:CC 1 "general_operand" "x"))] - "" - "cpfg %0,%1" - [(set_attr "type" "mu") - (set_attr "length" "1")]) - - -;; .................... -;; -;; Unconditional branch, return, and case table -;; -;; .................... - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "bra %l0" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -;; Note, do not list a dependency on r13, since jump.c currently can't handle a parallel -;; operation. -(define_expand "return" - [(return)] - "direct_return ()" - "") - -(define_insn "*return_1" - [(return)] - "direct_return () && (d10v_stack_info ())->total_size == 0" - "* -{ - operands[0] = gen_rtx (REG, Pmode, RETURN_ADDRESS_REGNUM); - return \"jmp %0\"; -}" - [(set_attr "type" "mu") - (set_attr "length" "1")]) - -(define_insn "*return_2" - [(return)] - "direct_return () && (d10v_stack_info ())->total_size != 0" - "* -{ - d10v_stack_t *info = d10v_stack_info (); - - operands[0] = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM); - operands[1] = gen_rtx (REG, Pmode, RETURN_ADDRESS_REGNUM); - if (info->total_size == UNITS_PER_WORD && info->save_p[RETURN_ADDRESS_REGNUM]) - return \"ld %1,@%0+\;jmp %1\"; - - else if (info->total_size == info->vars_size - && IN_RANGE_P (info->total_size, 1, 16)) - { - operands[2] = GEN_INT (info->total_size); - return \"addi %0,%2\;jmp %1\"; - } - - else - fatal_insn (\"return_2 unexpected return stack\", insn); - - return \"\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "indirect_jump" - [(set (pc) (match_operand:HI 0 "gpr_operand" "d"))] - "" - "jmp %0" - [(set_attr "type" "mu") - (set_attr "length" "1")]) - -;; No operation -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -;; Table jump for switch statements: -(define_insn "tablejump" - [(set (pc) (match_operand:HI 0 "gpr_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] - "" - "jmp %0" - [(set_attr "type" "mu") - (set_attr "length" "1")]) - - -;; .................... -;; -;; Calls -;; -;; .................... - -(define_expand "call" - [(parallel [(call (match_operand 0 "memory_operand" "") - (match_operand 1 "" "")) - (clobber (match_scratch:HI 2 "=l"))])] - "" - " -{ - rtx addr; - - addr = XEXP (operands[0], 0); - if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) - { - rtx reg = gen_reg_rtx (Pmode); - emit_move_insn (reg, addr); - operands[0] = gen_rtx (MEM, FUNCTION_MODE, reg); - } -}") - -(define_insn "*call_internal1" - [(call (match_operand 0 "memory_operand" "m") - (match_operand 1 "" "i")) - (clobber (match_scratch:HI 2 "=l"))] ;; return address, r13 - "GET_CODE (XEXP (operands[0], 0)) == REG" - "jl %0" - [(set_attr "type" "mu") - (set_attr "length" "1")]) - -(define_insn "*call_internal2" - [(call (match_operand 0 "memory_operand" "m") - (match_operand 1 "" "i")) - (clobber (match_scratch:HI 2 "=l"))] ;; return address, r13 - "CONSTANT_ADDRESS_P (XEXP (operands[0], 0))" - "bl %0" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "gpr_operand" "") - (call (match_operand 1 "memory_operand" "m") - (match_operand 2 "" "i"))) - (clobber (match_scratch:HI 3 "=l"))])] - "" - " -{ - rtx addr; - - addr = XEXP (operands[1], 0); - if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) - { - rtx reg = gen_reg_rtx (Pmode); - emit_move_insn (reg, addr); - operands[1] = gen_rtx (MEM, FUNCTION_MODE, reg); - } -}") - -(define_insn "*call_value_internal1" - [(set (match_operand 0 "gpr_operand" "=e") - (call (match_operand 1 "memory_operand" "m") - (match_operand 2 "" "i"))) - (clobber (match_scratch:HI 3 "=l"))] ;; return address, r13 - "GET_CODE (XEXP (operands[1], 0)) == REG" - "jl %1" - [(set_attr "type" "mu") - (set_attr "length" "1")]) - -(define_insn "*call_value_internal2" - [(set (match_operand 0 "gpr_operand" "=e") - (call (match_operand 1 "memory_operand" "m") - (match_operand 2 "" "i"))) - (clobber (match_scratch:HI 3 "=l"))] ;; return address, r13 - "CONSTANT_ADDRESS_P (XEXP (operands[1], 0))" - "bl %1" - [(set_attr "type" "long") - (set_attr "length" "2")]) - - -;; -;; .................... -;; -;; Comparisons -;; -;; .................... - -;; Flow here is rather complex: -;; -;; 1) The cmp{hi,si,di,sf,df} routine is called. It deposits the -;; arguments into global variables, and the type into -;; branch_type. No RTL is generated. -;; -;; 2) The appropriate branch define_expand is called, which then -;; creates the appropriate RTL for the comparison and branch. - -(define_expand "cmphi" - [(set (cc0) - (compare:CC (match_operand:HI 0 "gpr_operand" "") - (match_operand:HI 1 "arith16_operand" "")))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - compare_op0 = operands[0]; - compare_op1 = operands[1]; - DONE; - } -}") - -(define_expand "tsthi" - [(set (cc0) - (match_operand:HI 0 "gpr_operand" ""))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - compare_op0 = operands[0]; - compare_op1 = const0_rtx; - DONE; - } -}") - -(define_expand "cmpsi" - [(set (cc0) - (compare:CC (match_operand:SI 0 "gpr_operand" "") - (match_operand:SI 1 "reg_or_0_operand" "")))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - compare_op0 = operands[0]; - compare_op1 = operands[1]; - DONE; - } -}") - -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "gpr_operand" ""))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - compare_op0 = operands[0]; - compare_op1 = const0_rtx; - DONE; - } -}") - -(define_expand "cmpdi" - [(set (cc0) - (compare:CC (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "reg_or_0_operand" "")))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - compare_op0 = operands[0]; - compare_op1 = operands[1]; - DONE; - } -}") - -(define_expand "tstdi" - [(set (cc0) (match_operand:DI 0 "general_operand" ""))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - compare_op0 = operands[0]; - compare_op1 = const0_rtx; - DONE; - } -}") - -(define_insn "*tst_ne_true" - [(set (match_operand:CC 0 "f0_operand" "") - (ne:CC (and:HI (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "const_int_operand" "P,n")) - (const_int 0)))] - "" - "* -{ - int log = exact_log2 (INTVAL (operands[2])); - - if (IN_RANGE_P (log, 0, 15)) - { - operands[3] = GEN_INT (15 - log); - return \"btsti %1,%3\"; - } - - return \"tst0i %1,%2\"; -}" - [(set_attr "type" "iu,long") - (set_attr "length" "1,2")]) - -; the following is wrong -;(define_insn "*tst_eq_true" -; [(set (match_operand:CC 0 "f0_operand" "") -; (eq:CC (and:HI (match_operand:HI 1 "gpr_operand" "d") -; (match_operand:HI 2 "const_int_operand" "n")) -; (const_int 0)))] -; "" -; "tst0i %1,%2" -; [(set_attr "type" "long") -; (set_attr "length" "2")]) -; -;(define_insn "*tst_ne_false" -; [(set (match_operand:CC_REV 0 "f0_operand" "") -; (ne:CC_REV (and:HI (match_operand:HI 1 "gpr_operand" "d") -; (match_operand:HI 2 "const_int_operand" "n")) -; (const_int 0)))] -; "" -; "tst0i %1,%2" -; [(set_attr "type" "long") -; (set_attr "length" "2")]) - -(define_insn "*tst_eq_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (eq:CC_REV (and:HI (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "const_int_operand" "P,n")) - (const_int 0)))] - "" - "* -{ - int log = exact_log2 (INTVAL (operands[2])); - - if (IN_RANGE_P (log, 0, 15)) - { - operands[3] = GEN_INT (15 - log); - return \"btsti %1,%3\"; - } - - return \"tst0i %1,%2\"; -}" - [(set_attr "type" "iu,long") - (set_attr "length" "1,2")]) - -(define_insn "*eq_hi_true" - [(set (match_operand:CC 0 "f0_operand" "") - (eq:CC (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "arith16_operand" "dL,i")))] - "emit_comparison (EQ, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (EQ, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either,long") - (set_attr "length" "1,2")]) - -(define_insn "*lt_hi_true" - [(set (match_operand:CC 0 "f0_operand" "") - (lt:CC (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "arith16_operand" "dL,i")))] - "emit_comparison (LT, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (LT, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either,long") - (set_attr "length" "1,2")]) - -(define_insn "*le_hi_true" - [(set (match_operand:CC 0 "f0_operand" "") - (le:CC (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "const_int_operand" "O,i")))] - "emit_comparison (LE, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (LE, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either,long") - (set_attr "length" "1,2")]) - -(define_insn "*gt_hi_true" - [(set (match_operand:CC 0 "f0_operand" "") - (gt:CC (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "gpr_operand" "d")))] - "emit_comparison (GT, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (GT, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "*ltu_hi_true" - [(set (match_operand:CC 0 "f0_operand" "") - (ltu:CC (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "arith16_operand" "d,i")))] - "emit_comparison (LTU, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (LTU, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either,long") - (set_attr "length" "1,2")]) - -(define_insn "*leu_hi_true" - [(set (match_operand:CC 0 "f0_operand" "") - (leu:CC (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "const_int_operand" "i")))] - "emit_comparison (LEU, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (LEU, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*gtu_hi_true" - [(set (match_operand:CC 0 "f0_operand" "") - (gtu:CC (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "gpr_operand" "d")))] - "emit_comparison (GTU, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (GTU, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "*ne_hi_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (ne:CC_REV (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "arith16_operand" "dL,i")))] - "!emit_comparison (NE, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (NE, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either,long") - (set_attr "length" "1,2")]) - -(define_insn "*le_hi_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (le:CC_REV (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "gpr_operand" "d")))] - "!emit_comparison (LE, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (LE, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "*gt_hi_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (gt:CC_REV (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "const_int_operand" "O,i")))] - "!emit_comparison (GT, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (GT, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either,long") - (set_attr "length" "1,2")]) - -(define_insn "*ge_hi_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (ge:CC_REV (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "arith16_operand" "dL,i")))] - "!emit_comparison (GE, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (GE, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either,long") - (set_attr "length" "1,2")]) - -(define_insn "*leu_hi_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (leu:CC_REV (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "gpr_operand" "d")))] - "!emit_comparison (LEU, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (LEU, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "*gtu_hi_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (gtu:CC_REV (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "const_int_operand" "i")))] - "!emit_comparison (GTU, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (GTU, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*geu_hi_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (geu:CC_REV (match_operand:HI 1 "gpr_operand" "d,d") - (match_operand:HI 2 "arith16_operand" "dL,i")))] - "!emit_comparison (GEU, operands[1], operands[2], NULL_RTX, NULL_RTX, HImode, FALSE)" - "* -{ - emit_comparison (GEU, operands[1], operands[2], NULL_RTX, insn, HImode, TRUE); - return \"\"; -}" - [(set_attr "type" "either,long") - (set_attr "length" "1,2")]) - -(define_insn "*equality_si_true" - [(set (match_operand:CC 0 "f0_operand" "") - (match_operator:CC 1 "equality_operator" - [(match_operand:SI 2 "gpr_operand" "e,e,e") - (match_operand:SI 3 "arith_lower0_operand" "e,O,K")]))] - "emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, NULL_RTX, SImode, FALSE)" - "* -{ - !emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, insn, SImode, TRUE); - return \"\"; -}" - [(set_attr "type" "long,long,long") - (set_attr "length" "4,4,4")]) - -(define_insn "*signed_si_true" - [(set (match_operand:CC 0 "f0_operand" "") - (match_operator:CC 1 "signed_compare_operator" - [(match_operand:SI 2 "gpr_operand" "e,e") - (match_operand:SI 3 "reg_or_0_operand" "e,O")]))] - "emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, NULL_RTX, SImode, FALSE)" - "* -{ - emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, insn, SImode, TRUE); - return \"\"; -}" - [(set_attr "type" "long,long") - (set_attr "length" "4,4")]) - -(define_insn "*unsigned_si_true" - [(set (match_operand:CC 0 "f0_operand" "") - (match_operator:CC 1 "unsigned_compare_operator" - [(match_operand:SI 2 "gpr_operand" "e,e") - (match_operand:SI 3 "reg_or_0_operand" "e,O")]))] - "emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, NULL_RTX, SImode, FALSE)" - "* -{ - emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, insn, SImode, TRUE); - return \"\"; -}" - [(set_attr "type" "long,long") - (set_attr "length" "4,4")]) - -(define_insn "*equality_si_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (match_operator:CC_REV 1 "equality_operator" - [(match_operand:SI 2 "gpr_operand" "e,e,e") - (match_operand:SI 3 "arith_lower0_operand" "e,O,K")]))] - "!emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, NULL_RTX, SImode, FALSE)" - "* -{ - emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, insn, SImode, TRUE); - return \"\"; -}" - [(set_attr "type" "long,long,long") - (set_attr "length" "4,4,4")]) - -(define_insn "*signed_si_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (match_operator:CC_REV 1 "signed_compare_operator" - [(match_operand:SI 2 "gpr_operand" "e,e") - (match_operand:SI 3 "reg_or_0_operand" "e,O")]))] - "!emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, NULL_RTX, SImode, FALSE)" - "* -{ - emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, insn, SImode, TRUE); - return \"\"; -}" - [(set_attr "type" "long,long") - (set_attr "length" "4,4")]) - -(define_insn "*unsigned_si_false" - [(set (match_operand:CC_REV 0 "f0_operand" "") - (match_operator:CC_REV 1 "unsigned_compare_operator" - [(match_operand:SI 2 "gpr_operand" "e,e") - (match_operand:SI 3 "reg_or_0_operand" "e,O")]))] - "!emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, NULL_RTX, SImode, FALSE)" - "* -{ - emit_comparison (GET_CODE (operands[1]), operands[2], operands[3], NULL_RTX, insn, SImode, TRUE); - return \"\"; -}" - [(set_attr "type" "long,long") - (set_attr "length" "4,4")]) - - - -;; -;; .................... -;; -;; Conditional moves -;; -;; .................... - -(define_expand "movqicc" - [(match_dup 4) - (set (match_operand:QI 0 "cond_move_operand" "") - (if_then_else:QI (match_operand 1 "" "") - (match_operand:QI 2 "cond_move_operand" "") - (match_operand:QI 3 "cond_move_operand" "")))] - "TARGET_COND_MOVE" - " -{ - rtx f0; - - if (GET_CODE (operands[0]) == MEM) - { - if (GET_CODE (operands[2]) != REG && !(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0)) - FAIL; - - if (GET_CODE (operands[3]) != REG && !(GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) == 0)) - FAIL; - } - - operands[4] = expand_comparison (GET_CODE (operands[1]), compare_op0, compare_op1, &f0); - operands[1] = gen_rtx (NE, GET_MODE (f0), f0, const0_rtx); -}") - -(define_insn "*movqicc_internal" - [(set (match_operand:QI 0 "cond_move_operand" "=d,d,?d,d,d,?d,Q") - (if_then_else:QI (match_operator:CC 1 "f0_compare_operator" - [(match_operand:CC 2 "f0_operand" "") - (const_int 0)]) - (match_operand:QI 3 "cond_move_operand" "0,d,d,0,LQ,LQd,Od") - (match_operand:QI 4 "cond_move_operand" "d,0,d,LQ,0,LQd,Od")))] - "TARGET_COND_MOVE - && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[3]) == REG - || (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) == 0) - || GET_CODE (operands[4]) == REG - || (GET_CODE (operands[4]) == CONST_INT && INTVAL (operands[4]) == 0))" - "* return emit_cond_move (operands, insn);" - [(set_attr "type" "either,either,long,long,long,long,long") - (set_attr "length" "1,1,2,2,2,4,4")]) - -(define_expand "movhicc" - [(match_dup 4) - (set (match_operand:HI 0 "cond_move_operand" "") - (if_then_else:HI (match_operand 1 "" "") - (match_operand:HI 2 "cond_move_operand" "") - (match_operand:HI 3 "cond_move_operand" "")))] - "TARGET_COND_MOVE" - " -{ - rtx f0; - - if (GET_CODE (operands[0]) == MEM) - { - if (GET_CODE (operands[2]) != REG && !(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0)) - FAIL; - - if (GET_CODE (operands[3]) != REG && !(GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) == 0)) - FAIL; - } - - operands[4] = expand_comparison (GET_CODE (operands[1]), compare_op0, compare_op1, &f0); - operands[1] = gen_rtx (NE, GET_MODE (f0), f0, const0_rtx); -}") - -(define_insn "*movhicc_internal" - [(set (match_operand:HI 0 "cond_move_operand" "=d,d,?d,d,d,?d,Q") - (if_then_else:HI (match_operator:CC 1 "f0_compare_operator" - [(match_operand:CC 2 "f0_operand" "") - (const_int 0)]) - (match_operand:HI 3 "cond_move_operand" "0,d,d,0,LQ,LQd,Od") - (match_operand:HI 4 "cond_move_operand" "d,0,d,LQ,0,LQd,Od")))] - "TARGET_COND_MOVE - && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[3]) == REG - || (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) == 0) - || GET_CODE (operands[4]) == REG - || (GET_CODE (operands[4]) == CONST_INT && INTVAL (operands[4]) == 0))" - "* return emit_cond_move (operands, insn);" - [(set_attr "type" "either,either,long,long,long,long,long") - (set_attr "length" "1,1,2,2,2,4,4")]) - -(define_expand "movsicc" - [(match_dup 4) - (set (match_operand:SI 0 "cond_move_operand" "") - (if_then_else:SI (match_operand 1 "" "") - (match_operand:SI 2 "cond_move_operand" "") - (match_operand:SI 3 "cond_move_operand" "")))] - "TARGET_COND_MOVE" - " -{ - rtx f0; - - if (GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[2]) != REG || GET_CODE (operands[3]) != REG)) - { - FAIL; - } - - operands[4] = expand_comparison (GET_CODE (operands[1]), compare_op0, compare_op1, &f0); - operands[1] = gen_rtx (NE, GET_MODE (f0), f0, const0_rtx); -}") - -(define_insn "*movsicc_internal" - [(set (match_operand:SI 0 "cond_move_operand" "=e,e,?e,Q") - (if_then_else:SI (match_operator:CC 1 "f0_compare_operator" - [(match_operand:CC 2 "f0_operand" "") - (const_int 0)]) - (match_operand:SI 3 "cond_move_operand" "0,Qe,Qe,e") - (match_operand:SI 4 "cond_move_operand" "Qe,0,Qe,e")))] - "TARGET_COND_MOVE - && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[3]) == REG - || GET_CODE (operands[4]) == REG)" - "* return emit_cond_move (operands, insn);" - [(set_attr "type" "long,long,long,long") - (set_attr "length" "2,2,4,4")]) - -(define_expand "movsfcc" - [(match_dup 4) - (set (match_operand:SF 0 "cond_move_operand" "") - (if_then_else:SF (match_operand 1 "" "") - (match_operand:SF 2 "cond_move_operand" "") - (match_operand:SF 3 "cond_move_operand" "")))] - "TARGET_COND_MOVE" - " -{ - rtx f0; - - if (GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[2]) != REG || GET_CODE (operands[3]) != REG)) - { - FAIL; - } - - operands[4] = expand_comparison (GET_CODE (operands[1]), compare_op0, compare_op1, &f0); - operands[1] = gen_rtx (NE, GET_MODE (f0), f0, const0_rtx); -}") - -(define_insn "*movsfcc_internal" - [(set (match_operand:SF 0 "cond_move_operand" "=e,e,?e,Q") - (if_then_else:SF (match_operator:CC 1 "f0_compare_operator" - [(match_operand:CC 2 "f0_operand" "") - (const_int 0)]) - (match_operand:SF 3 "cond_move_operand" "0,Qe,Qe,e") - (match_operand:SF 4 "cond_move_operand" "Qe,0,Qe,e")))] - "TARGET_COND_MOVE - && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[3]) == REG - || GET_CODE (operands[4]) == REG)" - "* return emit_cond_move (operands, insn);" - [(set_attr "type" "long,long,long,long") - (set_attr "length" "2,2,4,4")]) - - -;; -;; .................... -;; -;; Conditional execution -;; -;; .................... - -(define_insn "*cond_exec_qi_store_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:QI 0 "short_memory_operand" "=Q,Q") - (match_operand:QI 1 "reg_or_0_operand" "d,O")) - (const_int 0))] - "" - "@ - stb %1,%M0 || exef0%T2 - stb %.,%M0 || exef0%T2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_qi_store_false" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:QI 0 "short_memory_operand" "=Q,Q") - (match_operand:QI 1 "reg_or_0_operand" "d,O")))] - "" - "@ - stb %1,%M0 || exef0%F2 - stb %.,%M0 || exef0%F2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_qi_load_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:QI 0 "gpr_operand" "=d,d,d") - (match_operand:QI 1 "cond_exec_operand" "d,L,Q")) - (const_int 0))] - "" - "@ - exef0%T2 || mv %0,%1 - exef0%T2 || ldi %0,%1 - ldub %0,%M1 || exef0%T2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_qi_load_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:QI 0 "gpr_operand" "=d,d,d") - (match_operand:QI 1 "cond_exec_operand" "d,L,Q")))] - "" - "@ - exef0%F2 || mv %0,%1 - exef0%F2 || ldi %0,%1 - ldub %0,%M1 || exef0%F2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_binary_true" - [(if_then_else (match_operator 3 "f0_compare_operator" - [(match_operand:CC 4 "f0_operand" "") - (const_int 0)]) - (set (match_operand:HI 0 "gpr_operand" "=d") - (match_operator:HI 5 "binary_parallel_operator" - [(match_operand:HI 1 "gpr_operand" "0") - (match_operand:HI 2 "arith16_operand" "di")])) - (const_int 0))] - "rtx_equal_p (operands[0], operands[1])" - "* -{ - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - switch (GET_CODE (operands[5])) - { - case PLUS: return \"exef0%T3 || add %0,%2\"; - case MINUS: return \"exef0%T3 || sub %0,%2\"; - case MULT: return \"exef0%T3 || mul %0,%2\"; - case AND: return \"exef0%T3 || and %0,%2\"; - case IOR: return \"exef0%T3 || or %0,%2\"; - case XOR: return \"exef0%T3 || xor %0,%2\"; - case ASHIFT: return \"exef0%T3 || sll %0,%2\"; - case ASHIFTRT: return \"exef0%T3 || sra %0,%2\"; - case LSHIFTRT: return \"exef0%T3 || srl %0,%2\"; - } - - else if (GET_CODE (operands[2]) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (operands[2]); - int log; - - switch (GET_CODE (operands[5])) - { - case PLUS: - if (IN_RANGE_P (value, 1, 16)) - return \"exef0%T3 || addi %0,%2\"; - - else if (IN_RANGE_P (value, -16, -1)) - return \"exef0%T3 || subi %0,%n2\"; - - else if (value == 0) - return \"\"; - - else - break; - - case MINUS: - if (IN_RANGE_P (value, 1, 16)) - return \"exef0%T3 || subi %0,%2\"; - - else if (IN_RANGE_P (value, -16, -1)) - return \"exef0%T3 || addi %0,%n2\"; - - else if (value == 0) - return \"\"; - - else - break; - - case IOR: - case XOR: - if (value == 0) - return \"\"; - - log = exact_log2 (value); - if (IN_RANGE_P (log, 0, 15)) - { - operands[2] = GEN_INT (15 - log); - return ((GET_CODE (operands[5]) == IOR) - ? \"exef0%T3 || bseti %0,%2\" - : \"exef0%T3 || bnoti %0,%2\"); - } - break; - - case AND: - if ((value & 0xffff) == 0xffff) - return \"\"; - - log = exact_log2 (~value); - if (IN_RANGE_P (log, 0, 15)) - { - operands[2] = GEN_INT (15 - log); - return \"exef0%T3 || bclri %0,%2\"; - } - break; - } - } - - fatal_insn (\"cond_exec_hi_binary_true\", insn); - return \"\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_binary_false" - [(if_then_else (match_operator 3 "f0_compare_operator" - [(match_operand:CC 4 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:HI 0 "gpr_operand" "=d") - (match_operator:HI 5 "binary_parallel_operator" - [(match_operand:HI 1 "gpr_operand" "0") - (match_operand:HI 2 "arith16_operand" "di")])))] - "rtx_equal_p (operands[0], operands[1])" - "* -{ - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - switch (GET_CODE (operands[5])) - { - case PLUS: return \"exef0%F3 || add %0,%2\"; - case MINUS: return \"exef0%F3 || sub %0,%2\"; - case MULT: return \"exef0%F3 || mul %0,%2\"; - case AND: return \"exef0%F3 || and %0,%2\"; - case IOR: return \"exef0%F3 || or %0,%2\"; - case XOR: return \"exef0%F3 || xor %0,%2\"; - case ASHIFT: return \"exef0%F3 || sll %0,%2\"; - case ASHIFTRT: return \"exef0%F3 || sra %0,%2\"; - case LSHIFTRT: return \"exef0%F3 || srl %0,%2\"; - } - - else if (GET_CODE (operands[2]) == CONST_INT) - { - HOST_WIDE_INT value = INTVAL (operands[2]); - int log; - - switch (GET_CODE (operands[5])) - { - case PLUS: - if (IN_RANGE_P (value, 1, 16)) - return \"exef0%F3 || addi %0,%2\"; - - else if (IN_RANGE_P (value, -16, -1)) - return \"exef0%F3 || subi %0,%n2\"; - - else if (value == 0) - return \"\"; - - else - break; - - case MINUS: - if (IN_RANGE_P (value, 1, 16)) - return \"exef0%F3 || subi %0,%2\"; - - else if (IN_RANGE_P (value, -16, -1)) - return \"exef0%F3 || addi %0,%n2\"; - - else if (value == 0) - return \"\"; - - else - break; - - case IOR: - case XOR: - if (value == 0) - return \"\"; - - log = exact_log2 (value); - if (IN_RANGE_P (log, 0, 15)) - { - operands[2] = GEN_INT (15 - log); - return ((GET_CODE (operands[5]) == IOR) - ? \"exef0%F3 || bseti %0,%2\" - : \"exef0%F3 || bnoti %0,%2\"); - } - break; - - case AND: - if ((value & 0xffff) == 0xffff) - return \"\"; - - log = exact_log2 (~value); - if (IN_RANGE_P (log, 0, 15)) - { - operands[2] = GEN_INT (15 - log); - return \"exef0%F3 || bclri %0,%2\"; - } - break; - } - } - - fatal_insn (\"cond_exec_hi_binary_false\", insn); - return \"\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_unary_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:HI 0 "gpr_operand" "=d") - (match_operator:HI 4 "unary_parallel_operator" - [(match_operand:HI 1 "gpr_operand" "0")])) - (const_int 0))] - "rtx_equal_p (operands[0], operands[1])" - "* -{ - switch (GET_CODE (operands[4])) - { - case NEG: return \"exef0%T2 || neg %0\"; - case NOT: return \"exef0%T2 || not %0\"; - - case SIGN_EXTEND: - if (GET_CODE (operands[1]) == MEM) - return \"ldb %0,%M1 || exef0%T2\"; - else if (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG) - return \"exef0%T2 || mvb %0,%1\"; - break; - - case ZERO_EXTEND: - if (GET_CODE (operands[1]) == MEM) - return \"ldub %0,%M1 || exef0%T2\"; - else if (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG) - return \"exef0%T2 || mvub %0,%1\"; - break; - } - - fatal_insn (\"cond_exec_hi_unary_true\", insn); - return \"\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_unary_false" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:HI 0 "gpr_operand" "=d") - (match_operator:HI 4 "unary_parallel_operator" - [(match_operand:HI 1 "gpr_operand" "0")])))] - "rtx_equal_p (operands[0], operands[1])" - "* -{ - switch (GET_CODE (operands[4])) - { - case NEG: return \"exef0%F2 || neg %0\"; - case NOT: return \"exef0%F2 || not %0\"; - - case SIGN_EXTEND: - if (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG) - return \"exef0%F2 || mvb %0,%1\"; - break; - - case ZERO_EXTEND: - if (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG) - return \"exef0%F2 || mvub %0,%1\"; - break; - } - - fatal_insn (\"cond_exec_hi_unary_false\", insn); - return \"\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_abs_true" - [(if_then_else (match_operator 3 "f0_compare_operator" - [(match_operand:CC 4 "f0_operand" "") - (const_int 0)]) - (parallel [(set (match_operand:HI 0 "gpr_operand" "=d") - (abs:HI (match_operand:HI 1 "gpr_operand" "0"))) - (clobber (match_operand:CC 2 "f0_operand" ""))]) - (const_int 0))] - "rtx_equal_p (operands[0], operands[1])" - "exef0%T3 || abs %0" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_abs_false" - [(if_then_else (match_operator 3 "f0_compare_operator" - [(match_operand:CC 4 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (parallel [(set (match_operand:HI 0 "gpr_operand" "=d") - (abs:HI (match_operand:HI 1 "gpr_operand" "0"))) - (clobber (match_operand:CC 2 "f0_operand" ""))]))] - "rtx_equal_p (operands[0], operands[1])" - "exef0%F3 || abs %0" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_minmax_true" - [(if_then_else (match_operator 5 "f0_compare_operator" - [(match_operand:CC 6 "f0_operand" "") - (const_int 0)]) - (parallel [(set (match_operand:HI 0 "gpr_operand" "=d") - (match_operator:HI 3 "minmax_parallel_operator" - [(match_operand:HI 1 "gpr_operand" "%0") - (match_operand:HI 2 "gpr_operand" "d")])) - (clobber (match_operand:CC 4 "f0_operand" ""))]) - (const_int 0))] - "rtx_equal_p (operands[0], operands[1])" - "* -{ - if (GET_CODE (operands[3]) == SMIN) - return \"exef0%T5 || min %0,%2\"; - else - return \"exef0%T5 || max %0,%2\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_minmax_false" - [(if_then_else (match_operator 5 "f0_compare_operator" - [(match_operand:CC 6 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (parallel [(set (match_operand:HI 0 "gpr_operand" "=d") - (match_operator:HI 3 "minmax_parallel_operator" - [(match_operand:HI 1 "gpr_operand" "%0") - (match_operand:HI 2 "gpr_operand" "d")])) - (clobber (match_operand:CC 4 "f0_operand" ""))]))] - "rtx_equal_p (operands[0], operands[1])" - "* -{ - if (GET_CODE (operands[3]) == SMIN) - return \"exef0%F5 || min %0,%2\"; - else - return \"exef0%F5 || max %0,%2\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_extend_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:HI 0 "gpr_operand" "=d") - (match_operator:HI 4 "extend_parallel_operator" - [(match_operand:QI 1 "short_memory_operand" "Q")])) - (const_int 0))] - "" - "ld%u4b %0,%M1 || exef0%T2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_extend_false" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:HI 0 "gpr_operand" "=d") - (match_operator:HI 4 "extend_parallel_operator" - [(match_operand:QI 1 "short_memory_operand" "Q")])))] - "" - "ld%u4b %0,%M1 || exef0%F2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_store_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:HI 0 "short_memory_operand" "=Q,Q") - (match_operand:HI 1 "reg_or_0_operand" "d,O")) - (const_int 0))] - "" - "@ - st %1,%M0 || exef0%T2 - st %.,%M0 || exef0%T2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_store_false" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:HI 0 "short_memory_operand" "=Q,Q") - (match_operand:HI 1 "reg_or_0_operand" "d,O")))] - "" - "@ - st %1,%M0 || exef0%F2 - st %.,%M0 || exef0%F2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_load_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (match_operand:HI 1 "cond_exec_operand" "d,L,Q")) - (const_int 0))] - "" - "@ - exef0%T2 || mv %0,%1 - exef0%T2 || ldi %0,%1 - ld %0,%M1 || exef0%T2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_hi_load_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (match_operand:HI 1 "cond_exec_operand" "d,L,Q")))] - "" - "@ - exef0%F2 || mv %0,%1 - exef0%F2 || ldi %0,%1 - ld %0,%M1 || exef0%F2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_si_binary_true" - [(if_then_else (match_operator 3 "f0_compare_operator" - [(match_operand:CC 4 "f0_operand" "") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=e") - (match_operator:SI 5 "binary_parallel_operator" - [(match_operand:SI 1 "gpr_operand" "0") - (match_operand:SI 2 "gpr_operand" "e")])) - (const_int 0))] - "rtx_equal_p (operands[0], operands[1])" - "* -{ - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - switch (GET_CODE (operands[5])) - { - case PLUS: return \"exef0%T3 || add2w %0,%2\"; - case MINUS: return \"exef0%T3 || sub2w %0,%2\"; - } - - fatal_insn (\"cond_exec_si_binary_true\", insn); - return \"\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_si_binary_false" - [(if_then_else (match_operator 3 "f0_compare_operator" - [(match_operand:CC 4 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=d") - (match_operator:SI 5 "binary_parallel_operator" - [(match_operand:SI 1 "gpr_operand" "0") - (match_operand:SI 2 "arith16_operand" "di")])))] - "rtx_equal_p (operands[0], operands[1])" - "* -{ - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - switch (GET_CODE (operands[5])) - { - case PLUS: return \"exef0%F3 || add2w %0,%2\"; - case MINUS: return \"exef0%F3 || sub2w %0,%2\"; - } - - fatal_insn (\"cond_exec_si_binary_false\", insn); - return \"\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_si_store_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:SI 0 "short_memory_operand" "=Q") - (match_operand:SI 1 "gpr_operand" "e")) - (const_int 0))] - "" - "st2w %1,%M0 || exef0%T2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_si_store_false" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "short_memory_operand" "=Q") - (match_operand:SI 1 "gpr_operand" "d")))] - "" - "st2w %1,%M0 || exef0%F2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_si_load_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=e,e") - (match_operand:SI 1 "cond_exec_operand" "e,Q")) - (const_int 0))] - "" - "@ - exef0%T2 || mv2w %0,%1 - ld2w %0,%M1 || exef0%T2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_si_load_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=e,e") - (match_operand:SI 1 "cond_exec_operand" "e,Q")))] - "" - "@ - exef0%F2 || mv2w %0,%1 - ld2w %0,%M1 || exef0%F2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_sf_store_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:SF 0 "short_memory_operand" "=Q") - (match_operand:SF 1 "gpr_operand" "e")) - (const_int 0))] - "" - "st2w %1,%M0 || exef0%T2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_sf_store_false" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:SF 0 "short_memory_operand" "=Q") - (match_operand:SF 1 "gpr_operand" "d")))] - "" - "st2w %1,%M0 || exef0%F2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_sf_load_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (set (match_operand:SF 0 "gpr_operand" "=e,e") - (match_operand:SF 1 "cond_exec_operand" "e,Q")) - (const_int 0))] - "" - "@ - exef0%T2 || mv2w %0,%1 - ld2w %0,%M1 || exef0%T2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_sf_load_true" - [(if_then_else (match_operator 2 "f0_compare_operator" - [(match_operand:CC 3 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (set (match_operand:SF 0 "gpr_operand" "=e,e") - (match_operand:SF 1 "cond_exec_operand" "e,Q")))] - "" - "@ - exef0%F2 || mv2w %0,%1 - ld2w %0,%M1 || exef0%F2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_call_true" - [(if_then_else (match_operator 3 "f0_compare_operator" - [(match_operand:CC 4 "f0_operand" "") - (const_int 0)]) - (parallel [(call (match_operand 0 "memory_operand" "m") - (match_operand 1 "" "i")) - (clobber (match_scratch:HI 2 "=l"))]) ;; return address, r13 - (const_int 0))] - "GET_CODE (XEXP (operands[0], 0)) == REG" - "jl %0 || exef0%T3" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_call_false" - [(if_then_else (match_operator 3 "f0_compare_operator" - [(match_operand:CC 4 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (parallel [(call (match_operand 0 "memory_operand" "m") - (match_operand 1 "" "i")) - (clobber (match_scratch:HI 2 "=l"))]))] ;; return address, r13 - "GET_CODE (XEXP (operands[0], 0)) == REG" - "jl %0 || exef0%F3" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_call_value_true" - [(if_then_else (match_operator 4 "f0_compare_operator" - [(match_operand:CC 5 "f0_operand" "") - (const_int 0)]) - (parallel [(set (match_operand 0 "gpr_operand" "=r") - (call (match_operand 1 "memory_operand" "m") - (match_operand 2 "" "i"))) - (clobber (match_scratch:HI 3 "=l"))]) ;; return address, r13 - (const_int 0))] - "GET_CODE (XEXP (operands[1], 0)) == REG" - "jl %1 || exef0%T4" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_insn "*cond_exec_call_value_false" - [(if_then_else (match_operator 4 "f0_compare_operator" - [(match_operand:CC 5 "f0_operand" "") - (const_int 0)]) - (const_int 0) - (parallel [(set (match_operand 0 "gpr_operand" "=r") - (call (match_operand 1 "memory_operand" "m") - (match_operand 2 "" "i"))) - (clobber (match_scratch:HI 3 "=l"))]))] ;; return address, r13 - "GET_CODE (XEXP (operands[1], 0)) == REG" - "jl %1 || exef0%F4" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -;; -;; .................... -;; -;; Conditional branches -;; -;; .................... - -(define_expand "beq" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (EQ, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "bne" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (NE, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "bgt" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (GT, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "bge" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (GE, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "blt" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (LT, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "ble" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (LE, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "bgtu" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (GTU, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "bgeu" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (GEU, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "bltu" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (LTU, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "bleu" - [(match_dup 2) - (set (pc) - (if_then_else (match_dup 1) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (LEU, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_insn "*cond_branch" - [(set (pc) - (if_then_else (match_operator:CC 0 "f0_compare_operator" - [(match_operand:CC 1 "f0_operand" "") - (const_int 0)]) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] - "" - "* -{ - if (operands[2] == pc_rtx) - return (GET_CODE (operands[3]) == RETURN) ? \"jmp r13 || exef0%T0\" : \"brf0%T0 %l3\"; - else - return (GET_CODE (operands[2]) == RETURN) ? \"jmp r13 || exef0%F0\" : \"brf0%F0 %l2\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - - -;; -;; .................... -;; -;; Set from condition code -;; -;; .................... - -(define_expand "seq" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (EQ, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "sne" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (NE, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "sgt" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (GT, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "sge" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (GE, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "slt" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (LT, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "sle" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (LE, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "sgtu" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (GTU, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "sgeu" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (GEU, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "sltu" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (LTU, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_expand "sleu" - [(match_dup 2) - (set (match_operand:HI 0 "gpr_operand" "") - (match_dup 1))] - "" - " -{ - rtx reg; - operands[2] = expand_comparison (LEU, compare_op0, compare_op1, ®); - operands[1] = gen_rtx (NE, GET_MODE (reg), reg, const0_rtx); -}") - -(define_insn "*scc" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (match_operator 1 "f0_compare_operator" - [(match_operand:CC 2 "f0_operand" "") - (const_int 0)]))] - "" - "setf0%F1 %0" - [(set_attr "type" "mu") - (set_attr "length" "1")]) - - -;; -;; .................... -;; -;; Data conversion -;; -;; .................... - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,Q,m")))] - "" - "@ - mvub %0,%1 - ldub %0,%M1 - ldub %0,%M1" - [(set_attr "type" "iu,mu,long") - (set_attr "length" "1,1,2")]) - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,Q,m")))] - "" - "@ - mvub %L0,%1\;ldi %U0,0 - ldub %L0,%M1\;ldi %U0,0 - ldub %L0,%M1\;ldi %U0,0" - [(set_attr "type" "long,long,long") - (set_attr "length" "2,2,3")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "reload_completed" - [(set (match_dup 3) (zero_extend:HI (match_dup 1))) - (set (match_dup 2) (const_int 0))] - " -{ - operands[2] = d10v_subword (operands[0], 0, HImode, SImode); - operands[3] = d10v_subword (operands[0], 1, HImode, SImode); -}") - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "gpr_operand" "=e,e,e") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "e,Q,m")))] - "" - "@ - mv %L0,%1\;ldi %U0,0 - ld %L0,%M1\;ldi %U0,0 - ld %L0,%M1\;ldi %U0,0" - [(set_attr "type" "long,long,long") - (set_attr "length" "2,2,3")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "reload_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 2) (const_int 0))] - " -{ - operands[2] = d10v_subword (operands[0], 0, HImode, SImode); - operands[3] = d10v_subword (operands[0], 1, HImode, SImode); -}") - -(define_insn "zero_extendqidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "d,Q,m")))] - "" - "@ - mvub %D0,%1\;ldi %C0,0\;ldi %B0,0\;ldi %A0,0 - ldub %D0,%M1\;ldi %C0,0\;ldi %B0,0\;ldi %A0,0 - ldub %D0,%M1\;ldi %C0,0\;ldi %B0,0\;ldi %A0,0" - [(set_attr "type" "long,long,long") - (set_attr "length" "4,4,5")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (zero_extend:DI (match_operand:QI 1 "gpr_operand" "")))] - "reload_completed" - [(set (match_dup 5) (zero_extend:HI (match_dup 1))) - (set (match_dup 2) (const_int 0)) - (set (match_dup 3) (const_int 0)) - (set (match_dup 4) (const_int 0))] - " -{ - operands[2] = d10v_subword (operands[0], 0, HImode, DImode); - operands[3] = d10v_subword (operands[0], 1, HImode, DImode); - operands[4] = d10v_subword (operands[0], 2, HImode, DImode); - operands[5] = d10v_subword (operands[0], 3, HImode, DImode); -}") - -(define_insn "zero_extendhidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,Q,m")))] - "" - "@ - mv %D0,%1\;ldi %C0,0\;ldi %B0,0\;ldi %A0,0 - ld %D0,%M1\;ldi %C0,0\;ldi %B0,0\;ldi %A0,0 - ld %D0,%M1\;ldi %C0,0\;ldi %B0,0\;ldi %A0,0" - [(set_attr "type" "long,long,long") - (set_attr "length" "4,4,5")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "")))] - "reload_completed" - [(set (match_dup 5) (match_dup 1)) - (set (match_dup 2) (const_int 0)) - (set (match_dup 3) (const_int 0)) - (set (match_dup 4) (const_int 0))] - " -{ - operands[2] = d10v_subword (operands[0], 0, HImode, DImode); - operands[3] = d10v_subword (operands[0], 1, HImode, DImode); - operands[4] = d10v_subword (operands[0], 2, HImode, DImode); - operands[5] = d10v_subword (operands[0], 3, HImode, DImode); -}") - -(define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "e,Q,m")))] - "" - "@ - mv2w %C0,%1\;ldi %B0,0\;ldi %A0,0 - ld2w %C0,%M1\;ldi %B0,0\;ldi %A0,0 - ld2w %C0,%M1\;ldi %B0,0\;ldi %A0,0" - [(set_attr "type" "long,long,long") - (set_attr "length" "3,3,4")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))] - "reload_completed" - [(set (match_dup 4) (match_dup 1)) - (set (match_dup 2) (const_int 0)) - (set (match_dup 3) (const_int 0))] - " -{ - operands[2] = d10v_subword (operands[0], 0, HImode, DImode); - operands[3] = d10v_subword (operands[0], 1, HImode, DImode); - operands[4] = d10v_subword (operands[0], 2, SImode, DImode); -}") - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,Q,m")))] - "" - "@ - mvb %0,%1 - ldb %0,%M1 - ldb %0,%M1" - [(set_attr "type" "iu,mu,long") - (set_attr "length" "1,1,2")]) - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "gpr_operand" "=e,e,e") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "e,Q,m")))] - "" - "@ - mvb %L0,%1\;mv %U0,%L0\;srai %U0,15 - ldb %L0,%M1\;mv %U0,%L0\;srai %U0,15 - ldb %L0,%M1\;mv %U0,%L0\;srai %U0,15" - [(set_attr "type" "long,long,long") - (set_attr "length" "3,3,4")]) - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "gpr_operand" "=e,e,e,a") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "e,Q,m,e")))] - "" - "* -{ - if (ACCUM_P (REGNO (operands[0]))) - return \"mvtaclo %1,%0\"; - - if (GET_CODE (operands[1]) == MEM) - return \"ld %L0,%M1\;mv %U0,%L0\;srai %U0,15\"; - - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"mv %L0,%1\;srai %U0,15\"; - - return \"mv %L0,%1\;mv %U0,%L0\;srai %U0,15\"; -}" - [(set_attr "type" "long,long,long,iu") - (set_attr "length" "3,3,4,1")]) - -(define_insn "extendqidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "e,Q,m")))] - "" - "@ - mvb %D0,%1\;mv %C0,%D0\;srai %C0,15\;mv %B0,%C0\;mv %A0,%C0 - ldb %D0,%M1\;mv %C0,%D0\;srai %C0,15\;mv %B0,%C0\;mv %A0,%C0 - ldb %D0,%M1\;mv %C0,%D0\;srai %C0,15\;mv %B0,%C0\;mv %A0,%C0" - [(set_attr "type" "long,long,long") - (set_attr "length" "5,5,6")]) - -(define_insn "extendhidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "e,Q,m")))] - "" - "@ - mv %D0,%1\;mv %C0,%D0\;srai %C0,15\;mv %B0,%C0\;mv %A0,%C0 - ld %D0,%M1\;mv %C0,%D0\;srai %C0,15\;mv %B0,%C0\;mv %A0,%C0 - ld %D0,%M1\;mv %C0,%D0\;srai %C0,15\;mv %B0,%C0\;mv %A0,%C0" - [(set_attr "type" "long,long,long") - (set_attr "length" "5,5,6")]) - -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "e,Q,m")))] - "" - "@ - mv2w %C0,%1\;mv %B0,%C0\;srai %B0,15\;mv %A0,%B0 - ld2w %C0,%M1\;mv %B0,%C0\;srai %B0,15\;mv %A0,%B0 - ld2w %C0,%M1\;mv %B0,%C0\;srai %B0,15\;mv %A0,%B0" - [(set_attr "type" "long,long,long") - (set_attr "length" "4,4,5")]) - - -;; -;; .................... -;; -;; Addition -;; -;; .................... - -(define_expand "addhi3" - [(set (match_operand:HI 0 "gpr_operand" "") - (plus:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - "") - -(define_insn "*addhi3_no_small_insns" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d,d") - (plus:HI (match_operand:HI 1 "gpr_operand" "%0,0,0,d") - (match_operand:HI 2 "arith16_operand" "d,I,N,i")))] - "TARGET_NO_SMALL_INSNS || !optimize" - "@ - add %0,%2 - addi %0,%2 - subi %0,%n2 - add3 %0,%1,%2" - [(set_attr "type" "either,either,either,long") - (set_attr "length" "1,1,1,2")]) - -(define_insn "*addhi3_small_insns" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d,d,d,d") - (plus:HI (match_operand:HI 1 "gpr_operand" "%0,0,0,d,d,d") - (match_operand:HI 2 "arith16_operand" "d,I,N,I,N,i")))] - "TARGET_SMALL_INSNS && optimize" - "@ - add %0,%2 - addi %0,%2 - subi %0,%n2 - mv %0,%1\;addi %0,%2 - mv %0,%1\;subi %0,%n2 - add3 %0,%1,%2" - [(set_attr "type" "either,either,either,long,long,long") - (set_attr "length" "1,1,1,2,2,2")]) - -(define_split - [(set (match_operand:HI 0 "gpr_operand" "") - (plus:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && TARGET_SMALL_INSNS && optimize - && REGNO (operands[0]) != REGNO (operands[1]) - && IN_RANGE_P (INTVAL (operands[2]), -16, 16) - && INTVAL (operands[2]) != 0" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 2)))] - "") - -(define_expand "addsi3" - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")))] - "" - "") - -(define_insn "*addsi3_noaccum" - [(set (match_operand:SI 0 "gpr_operand" "=e") - (plus:SI (match_operand:SI 1 "gpr_operand" "%0") - (match_operand:SI 2 "gpr_operand" "e")))] - "!TARGET_ACCUM" - "add2w %0,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*addsi3_noaddac3" - [(set (match_operand:SI 0 "register_operand" "=e,a") - (plus:SI (match_operand:SI 1 "register_operand" "%0,0") - (match_operand:SI 2 "register_operand" "e,ea")))] - "TARGET_ACCUM && !TARGET_ADDAC3" - "@ - add2w %0,%2 - add %0,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*addsi3_addac3" - [(set (match_operand:SI 0 "register_operand" "=e,e,a") - (plus:SI (match_operand:SI 1 "register_operand" "%0,ea,0") - (match_operand:SI 2 "register_operand" "e,a,ea")))] - "TARGET_ACCUM && TARGET_ADDAC3" - "@ - add2w %0,%2 - addac3 %0,%1,%2 - add %0,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_expand "adddi3" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (plus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "arith_nonnegative_operand" ""))) - (clobber (match_dup 3))])] - "TARGET_LONGLONG_ALU" - "operands[3] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*adddi3_internal" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (plus:DI (match_operand:DI 1 "gpr_operand" "%0,0,0") - (match_operand:DI 2 "arith_nonnegative_operand" "e,I,M"))) - (clobber (match_operand:CC 3 "f0_operand" ""))])] - "TARGET_LONGLONG_ALU" - "* return emit_add (operands, insn);" - [(set_attr "type" "long") - (set_attr "length" "10,10,12")]) - - -;; -;; .................... -;; -;; Subtraction -;; -;; .................... - -(define_expand "subhi3" - [(set (match_operand:HI 0 "gpr_operand" "") - (minus:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - "") - -(define_insn "*subhi3_no_small_insns" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d,d") - (minus:HI (match_operand:HI 1 "gpr_operand" "0,0,0,d") - (match_operand:HI 2 "arith16_operand" "d,I,N,i")))] - "TARGET_NO_SMALL_INSNS || !optimize" - "@ - sub %0,%2 - subi %0,%2 - addi %0,%n2 - add3 %0,%1,%n2" - [(set_attr "type" "either,either,either,long") - (set_attr "length" "1,1,1,2")]) - -(define_insn "*subhi3_small_insns" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d,d,d,d") - (minus:HI (match_operand:HI 1 "gpr_operand" "0,0,0,d,d,d") - (match_operand:HI 2 "arith16_operand" "d,I,N,I,N,i")))] - "TARGET_SMALL_INSNS && optimize" - "@ - sub %0,%2 - subi %0,%2 - addi %0,%n2 - mv %0,%1\;subi %0,%2 - mv %0,%1\;addi %0,%n2 - add3 %0,%1,%n2" - [(set_attr "type" "either,either,either,long,long,long") - (set_attr "length" "1,1,1,2,2,2")]) - -(define_split - [(set (match_operand:HI 0 "gpr_operand" "") - (minus:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && TARGET_SMALL_INSNS && optimize - && REGNO (operands[0]) != REGNO (operands[1]) - && IN_RANGE_P (INTVAL (operands[2]), -16, 16) - && INTVAL (operands[2]) != 0" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (minus:HI (match_dup 0) (match_dup 2)))] - "") - - -(define_expand "subsi3" - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")))] - "" - "") - -(define_insn "*subsi3_noaccum" - [(set (match_operand:SI 0 "gpr_operand" "=e") - (minus:SI (match_operand:SI 1 "gpr_operand" "0") - (match_operand:SI 2 "gpr_operand" "e")))] - "!TARGET_ACCUM" - "sub2w %0,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*subsi3_noaddac3" - [(set (match_operand:SI 0 "register_operand" "=e,a") - (minus:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "register_operand" "e,ea")))] - "TARGET_ACCUM && !TARGET_ADDAC3" - "@ - sub2w %0,%2 - sub %0,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*subsi3_addac3" - [(set (match_operand:SI 0 "register_operand" "=e,e,a") - (minus:SI (match_operand:SI 1 "register_operand" "0,ea,0") - (match_operand:SI 2 "register_operand" "e,a,ea")))] - "TARGET_ACCUM && TARGET_ADDAC3" - "@ - sub2w %0,%2 - subac3 %0,%1,%2 - sub %0,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_expand "subdi3" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (minus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_operand" ""))) - (clobber (match_dup 3))])] - "TARGET_LONGLONG_ALU" - "operands[3] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*subdi3_internal1" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "=e") - (minus:DI (match_operand:DI 1 "gpr_operand" "0") - (match_operand:DI 2 "gpr_operand" "e"))) - (clobber (match_operand:CC 3 "f0_operand" ""))])] - "TARGET_LONGLONG_ALU" - "* return emit_subtract (operands, insn);" - [(set_attr "type" "long") - (set_attr "length" "10")]) - - -;; -;; .................... -;; -;; Negation -;; -;; .................... - -(define_insn "neghi2" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (neg:HI (match_operand:HI 1 "gpr_operand" "0")))] - "" - "neg %0" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_expand "negsi2" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (neg:SI (match_operand:SI 1 "register_operand" ""))) - (clobber (match_dup 2))])] - "" - "operands[2] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*negsi2_internal" - [(set (match_operand:SI 0 "register_operand" "=a,e") - (neg:SI (match_operand:SI 1 "register_operand" "0,0"))) - (clobber (match_operand:CC 2 "f0_operand" ""))] - "" - "@ - neg %0 - not %U0\;neg %L0\;cmpeqi %L0,0\;exef0t || addi %U0,1" - [(set_attr "type" "iu,long") - (set_attr "length" "1,6")]) - -(define_expand "negdi2" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (neg:DI (match_operand:DI 1 "gpr_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_LONGLONG_ALU" - "operands[2] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*negdi2_internal" - [(set (match_operand:DI 0 "gpr_operand" "=e") - (neg:DI (match_operand:DI 1 "gpr_operand" "0"))) - (clobber (match_operand:CC 2 "f0_operand" ""))] - "TARGET_LONGLONG_ALU" - "not %A0\;not %B0\;not %C0\;neg %D0\;cmpeqi %D0,0\;exef0t || addi %C0,1\;exef0t || cmpeqi %C0,0\;exef0t || addi %B0,1\;exef0t || cmpeqi %B0,0\;exef0t || addi %A0,1" - [(set_attr "type" "long") - (set_attr "length" "16")]) - - -;; -;; .................... -;; -;; Multiplication -;; -;; .................... - -(define_insn "mulhi3" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (mult:HI (match_operand:HI 1 "gpr_operand" "%0") - (match_operand:HI 2 "gpr_operand" "d")))] - "" - "mul %0,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*mulhisi3_add" - [(set (match_operand:SI 0 "accum_operand" "=a") - (plus:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "gpr_operand" "%d")) - (sign_extend:SI (match_operand:HI 2 "gpr_operand" "d"))) - (match_operand:SI 3 "register_operand" "0")))] - "TARGET_ACCUM" - "mac %0,%1,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "mulhisi3" - [(set (match_operand:SI 0 "accum_operand" "=a") - (mult:SI (sign_extend:SI (match_operand:HI 1 "gpr_operand" "%d")) - (sign_extend:SI (match_operand:HI 2 "gpr_operand" "d"))))] - "TARGET_ACCUM" - "mulx %0,%1,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*umulhisi3_add" - [(set (match_operand:SI 0 "accum_operand" "=a") - (plus:SI (mult:SI (zero_extend:SI (match_operand:HI 1 "gpr_operand" "%d")) - (zero_extend:SI (match_operand:HI 2 "gpr_operand" "d"))) - (match_operand:SI 3 "register_operand" "0")))] - "TARGET_ACCUM" - "macu %0,%1,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "umulhisi3" - [(set (match_operand:SI 0 "accum_operand" "=a") - (mult:SI (zero_extend:SI (match_operand:HI 1 "gpr_operand" "%d")) - (zero_extend:SI (match_operand:HI 2 "gpr_operand" "d"))))] - "TARGET_ACCUM" - "mulxu %0,%1,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*mulhisi3_mixed_add1" - [(set (match_operand:SI 0 "accum_operand" "=a") - (plus:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "gpr_operand" "%d")) - (zero_extend:SI (match_operand:HI 2 "gpr_operand" "d"))) - (match_operand:SI 3 "register_operand" "0")))] - "TARGET_ACCUM" - "macsu %0,%1,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*mulhisi3_mixed1" - [(set (match_operand:SI 0 "accum_operand" "=a") - (mult:SI (sign_extend:SI (match_operand:HI 1 "gpr_operand" "%d")) - (zero_extend:SI (match_operand:HI 2 "gpr_operand" "d"))))] - "TARGET_ACCUM" - "mulxsu %0,%1,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*mulhisi3_mixed_add2" - [(set (match_operand:SI 0 "accum_operand" "=a") - (plus:SI (mult:SI (zero_extend:SI (match_operand:HI 1 "gpr_operand" "%d")) - (sign_extend:SI (match_operand:HI 2 "gpr_operand" "d"))) - (match_operand:SI 3 "register_operand" "0")))] - "TARGET_ACCUM" - "macsu %0,%2,%1" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "*mulhisi3_mixed2" - [(set (match_operand:SI 0 "accum_operand" "=a") - (mult:SI (zero_extend:SI (match_operand:HI 1 "gpr_operand" "%d")) - (sign_extend:SI (match_operand:HI 2 "gpr_operand" "d"))))] - "TARGET_ACCUM" - "mulxsu %0,%2,%1" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_insn "mulsi3" - [(set (match_operand:SI 0 "accum_operand" "=a") - (mult:SI (match_operand:SI 1 "gpr_operand" "e") - (match_operand:SI 2 "gpr_operand" "e")))] - "TARGET_ACCUM" - "#" - [(set_attr "type" "long") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (mult:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_operand" "")))] - "TARGET_ACCUM && reload_completed" - [(set (match_dup 0) - (mult:SI (zero_extend:SI (match_dup 3)) - (zero_extend:SI (match_dup 6)))) - (set (match_dup 0) - (plus:SI (mult:SI (zero_extend:SI (match_dup 4)) - (zero_extend:SI (match_dup 5))) - (match_dup 0))) - (set (match_dup 0) - (ashift:SI (match_dup 0) - (const_int 16))) - (set (match_dup 0) - (plus:SI (mult:SI (zero_extend:SI (match_dup 4)) - (zero_extend:SI (match_dup 6))) - (match_dup 0)))] - " -{ - operands[3] = d10v_subword (operands[1], 0, HImode, SImode); - operands[4] = d10v_subword (operands[1], 1, HImode, SImode); - - operands[5] = d10v_subword (operands[2], 0, HImode, SImode); - operands[6] = d10v_subword (operands[2], 1, HImode, SImode); -}") - - -;; -;; .................... -;; -;; Division -;; -;; .................... - -(define_expand "divmodhi4" - [(parallel [(set (match_operand:HI 0 "gpr_operand" "") - (div:HI (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (set (match_operand:HI 3 "gpr_operand" "") - (mod:HI (match_dup 1) - (match_dup 2)))])] - "" - " -{ - d10v_expand_divmod (operands, FALSE); - DONE; -}") - -(define_expand "udivmodhi4" - [(parallel [(set (match_operand:HI 0 "gpr_operand" "") - (udiv:HI (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (set (match_operand:HI 3 "gpr_operand" "") - (umod:HI (match_dup 1) - (match_dup 2)))])] - "" - " -{ - d10v_expand_divmod (operands, TRUE); - DONE; -}") - - -;; -;; .................... -;; -;; Logical operations -;; -;; .................... - -(define_expand "andhi3" - [(set (match_operand:HI 0 "gpr_operand" "") - (and:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - "") - -(define_insn "*andhi3_register" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (and:HI (match_operand:HI 1 "gpr_operand" "%0") - (match_operand:HI 2 "gpr_operand" "d")))] - "" - "and %0,%2" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "*andhi3_move" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (and:HI (match_operand:HI 1 "gpr_operand" "%d") - (match_operand:HI 2 "const_int_operand" "n")))] - "(INTVAL (operands[2]) & 0xffff) == 0xffff" - "mv %0,%1" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "*andhi3_constant" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (and:HI (match_operand:HI 1 "gpr_operand" "%d,0,d") - (match_operand:HI 2 "const_int_operand" "O,J,n")))] - "" - "* -{ - HOST_WIDE_INT value = INTVAL (operands[2]); - - if (value == 0) - return \"ldi %0,0\"; - - if ((value & 0xffff) == 0xffff) - return \"mv %0,%1\"; - - if (IN_RANGE_P (exact_log2 (~value), 0, 15)) - { - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"bclri %0,%b2\"; - - if (TARGET_SMALL_INSNS && optimize) - return \"mv %0,%1\;bclri %0,%b2\"; - } - - return \"and3 %0,%1,%2\"; -}" - [(set_attr "type" "either,iu,long") - (set_attr "length" "1,1,2")]) - -(define_split - [(set (match_operand:HI 0 "gpr_operand" "") - (and:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && TARGET_SMALL_INSNS && optimize - && !rtx_equal_p (operands[0], operands[1]) - && IN_RANGE_P (exact_log2 (~ INTVAL (operands[2])), 0, 15)" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (and:HI (match_dup 0) (match_dup 2)))] - "") - -(define_insn "andsi3" - [(set (match_operand:SI 0 "gpr_operand" "=e,e,e") - (and:SI (match_operand:SI 1 "gpr_operand" "%0,0,?e") - (match_operand:SI 2 "arith32_operand" "e,n,n")))] - "" - "#" - [(set_attr "type" "long,long,long") - (set_attr "length" "2,4,4")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (and:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "reload_completed" - [(match_dup 3)] - "operands[3] = d10v_split_logical_op (operands, AND);") - -(define_insn "anddi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (and:DI (match_operand:DI 1 "gpr_operand" "0,0,?e") - (match_operand:DI 2 "arith64_operand" "e,nF,nF")))] - "" - "#" - [(set_attr "type" "long") - (set_attr "length" "4,8,8")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (and:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "arith64_operand" "")))] - "reload_completed" - [(match_dup 3)] - "operands[3] = d10v_split_logical_op (operands, AND);") - -(define_expand "iorhi3" - [(set (match_operand:HI 0 "gpr_operand" "") - (ior:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - "") - -(define_insn "*iorhi3_register" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (ior:HI (match_operand:HI 1 "gpr_operand" "%0") - (match_operand:HI 2 "gpr_operand" "d")))] - "" - "or %0,%2" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "*iorhi3_neg1" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (ior:HI (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "const_int_operand" "n")))] - "(INTVAL (operands[2]) & 0xffff) == 0xffff" - "ldi %0,-1" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "*iorhi3_constant" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (ior:HI (match_operand:HI 1 "gpr_operand" "%d,0,d") - (match_operand:HI 2 "const_int_operand" "O,P,n")))] - "" - "* -{ - HOST_WIDE_INT value = INTVAL (operands[2]); - int log = exact_log2 (value); - - if (value == 0) - return \"mv %0,%1\"; - - if ((value & 0xffff) == 0xffff) - return \"ldi %0,-1\"; - - if (IN_RANGE_P (exact_log2 (value), 0, 15)) - { - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"bseti %0,%b2\"; - - if (TARGET_SMALL_INSNS && optimize) - return \"mv %0,%1\;bseti %0,%b2\"; - } - - return \"or3 %0,%1,%2\"; -}" - [(set_attr "type" "either,iu,long") - (set_attr "length" "1,1,2")]) - -(define_split - [(set (match_operand:HI 0 "gpr_operand" "") - (ior:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && TARGET_SMALL_INSNS && optimize - && !rtx_equal_p (operands[0], operands[1]) - && IN_RANGE_P (exact_log2 (INTVAL (operands[2])), 0, 15)" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (ior:HI (match_dup 0) (match_dup 2)))] - "") - -(define_insn "iorsi3" - [(set (match_operand:SI 0 "gpr_operand" "=e,e") - (ior:SI (match_operand:SI 1 "gpr_operand" "%0,e") - (match_operand:SI 2 "arith32_operand" "e,i")))] - "" - "#" - [(set_attr "type" "long,long") - (set_attr "length" "2,4")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (ior:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "reload_completed" - [(match_dup 3)] - "operands[3] = d10v_split_logical_op (operands, IOR);") - -(define_insn "iordi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (ior:DI (match_operand:DI 1 "gpr_operand" "0,0,?e") - (match_operand:DI 2 "arith64_operand" "e,nF,nF")))] - "" - "#" - [(set_attr "type" "long") - (set_attr "length" "4,8,8")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (ior:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "arith64_operand" "")))] - "reload_completed" - [(match_dup 3)] - "operands[3] = d10v_split_logical_op (operands, IOR);") - -(define_expand "xorhi3" - [(set (match_operand:HI 0 "gpr_operand" "") - (xor:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - "") - -(define_insn "*xorhi3_register" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (xor:HI (match_operand:HI 1 "gpr_operand" "%0") - (match_operand:HI 2 "gpr_operand" "d")))] - "" - "xor %0,%2" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "*xorhi3_not" - [(set (match_operand:HI 0 "gpr_operand" "=d,?d") - (xor:HI (match_operand:HI 1 "gpr_operand" "%0,d") - (match_operand:HI 2 "const_int_operand" "n,n")))] - "(INTVAL (operands[2]) & 0xffff) == 0xffff" - "@ - not %0 - mv %0,%1\;not %0" - [(set_attr "type" "either,long") - (set_attr "length" "1,2")]) - -(define_split - [(set (match_operand:HI 0 "gpr_operand" "") - (xor:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "const_int_operand" "n")))] - "(INTVAL (operands[2]) & 0xffff) == 0xffff - && !rtx_equal_p (operands[0], operands[1])" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (not:HI (match_dup 0)))] - "") - -(define_insn "*xorhi3_constant" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (xor:HI (match_operand:HI 1 "gpr_operand" "%d") - (match_operand:HI 2 "const_int_operand" "n")))] - "" - "* -{ - HOST_WIDE_INT value = INTVAL (operands[2]); - int log = exact_log2 (value); - - if (value == 0) - return \"mv %0,%1\"; - - if ((value & 0xffff) == 0xffff && REGNO (operands[0]) == REGNO (operands[1])) - return \"not %0\"; - - if (IN_RANGE_P (exact_log2 (value), 0, 15)) - { - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"bnoti %0,%b2\"; - - if (TARGET_SMALL_INSNS && optimize) - return \"mv %0,%1\;bnoti %0,%b2\"; - } - - return \"xor3 %0,%1,%2\"; -}" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_split - [(set (match_operand:HI 0 "gpr_operand" "") - (xor:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && TARGET_SMALL_INSNS && optimize - && !rtx_equal_p (operands[0], operands[1]) - && IN_RANGE_P (exact_log2 (INTVAL (operands[2])), 0, 15)" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (xor:HI (match_dup 0) (match_dup 2)))] - "") - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "gpr_operand" "=e,e") - (xor:SI (match_operand:SI 1 "gpr_operand" "%0,e") - (match_operand:SI 2 "arith32_operand" "e,i")))] - "" - "#" - [(set_attr "type" "long,long") - (set_attr "length" "2,4")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (xor:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "arith32_operand" "")))] - "reload_completed" - [(match_dup 3)] - "operands[3] = d10v_split_logical_op (operands, XOR);") - -(define_insn "xordi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (xor:DI (match_operand:DI 1 "gpr_operand" "0,0,?e") - (match_operand:DI 2 "arith64_operand" "e,nF,nF")))] - "" - "#" - [(set_attr "type" "long") - (set_attr "length" "4,8,8")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (xor:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "arith64_operand" "")))] - "reload_completed" - [(match_dup 3)] - "operands[3] = d10v_split_logical_op (operands, XOR);") - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (not:HI (match_operand:HI 1 "gpr_operand" "0")))] - "" - "not %0" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "gpr_operand" "=e") - (not:SI (match_operand:SI 1 "gpr_operand" "0")))] - "" - "#" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (not:SI (match_operand:SI 1 "gpr_operand" "")))] - "reload_completed" - [(match_dup 2)] - "operands[2] = d10v_split_logical_op (operands, NOT);") - -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "gpr_operand" "=e") - (not:DI (match_operand:DI 1 "gpr_operand" "0")))] - "" - "#" - [(set_attr "type" "long") - (set_attr "length" "4")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (not:DI (match_operand:SI 1 "gpr_operand" "")))] - "reload_completed" - [(match_dup 2)] - "operands[2] = d10v_split_logical_op (operands, NOT);") - - -;; -;; .................... -;; -;; Shifts -;; -;; .................... - -(define_expand "ashlhi3" - [(set (match_operand:HI 0 "gpr_operand" "") - (ashift:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT && !IN_RANGE_P (INTVAL (operands[2]), 0, 15)) - operands[2] = force_reg (HImode, operands[2]); -}") - -(define_insn "*ashlhi3_internal" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (ashift:HI (match_operand:HI 1 "gpr_operand" "0,0,0") - (match_operand:HI 2 "arith16_operand" "I,O,d")))] - "GET_CODE (operands[2]) != CONST_INT || IN_RANGE_P (INTVAL (operands[2]), 0, 15)" - "@ - slli %0,%2 - nop - sll %0,%2" - [(set_attr "type" "iu,either,iu") - (set_attr "length" "1,1,1")]) - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashift:SI (match_operand:SI 1 "register_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - " -{ - if (!TARGET_ACCUM && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 16)) - FAIL; - - if (GET_CODE (operands[2]) == CONST_INT && ((unsigned long)INTVAL (operands[2])) > 31) - operands[2] = force_reg (HImode, operands[2]); - - if (GET_CODE (operands[2]) != CONST_INT) - { - emit_insn (gen_ashlsi3_variable (operands[0], operands[1], operands[2], - gen_reg_rtx (HImode), - gen_rtx (REG, CCmode, F0_REGNUM), - gen_rtx (REG, HImode, GPR_ZERO_REGNUM))); - DONE; - } -}") - -(define_insn "*ashlsi3_16" - [(set (match_operand:SI 0 "register_operand" "=e,a") - (ashift:SI (match_operand:SI 1 "register_operand" "e,0") - (const_int 16)))] - "" - "@ - mv %U0,%L1\;ldi %L0,0 - slli %0,16" - [(set_attr "type" "long,long") - (set_attr "length" "2,2")]) - -(define_insn "*ashlsi3_constant" - [(set (match_operand:SI 0 "accum_operand" "=a,a,a") - (ashift:SI (match_operand:SI 1 "accum_operand" "0,0,0") - (match_operand:SI 2 "const_int_operand" "I,O,n")))] - "TARGET_ACCUM && ((unsigned HOST_WIDE_INT)INTVAL (operands[2])) <= 31" - "* -{ - HOST_WIDE_INT shift_value = INTVAL (operands[2]); - - if (shift_value == 0) - return \"\"; - - if (shift_value <= 16) - return \"slli %0,%2\"; - - operands[3] = GEN_INT (16); - operands[4] = GEN_INT (shift_value - 16); - return \"slli %0,%3\;slli %0,%4\"; -}" - [(set_attr "type" "iu,either,long") - (set_attr "length" "1,1,2")]) - -(define_insn "ashlsi3_variable" - [(set (match_operand:SI 0 "accum_operand" "=a") - (ashift:SI (match_operand:SI 1 "accum_operand" "0") - (match_operand:HI 2 "gpr_operand" "d"))) - (clobber (match_operand:HI 3 "gpr_operand" "=&d")) - (clobber (match_operand:CC 4 "f0_operand" "")) - (use (match_operand:HI 5 "gpr_operand" "d")) - (use (const_int 0))] - "TARGET_ACCUM" - "#" - [(set_attr "type" "long") - (set_attr "length" "10")]) - -(define_insn "*ashlsi3_variable2" - [(set (match_operand:SI 0 "accum_operand" "=a") - (ashift:SI (match_operand:SI 1 "accum_operand" "0") - (match_operand:HI 2 "gpr_operand" "d"))) - (use (const_int 1))] - "TARGET_ACCUM" - "sll %0,%2" - [(set_attr "type" "long") - (set_attr "length" "1")]) - -(define_split - [(set (match_operand:SI 0 "accum_operand" "") - (ashift:SI (match_operand:SI 1 "accum_operand" "") - (match_operand:HI 2 "gpr_operand" ""))) - (clobber (match_operand:HI 3 "gpr_operand" "")) - (clobber (match_operand:CC 4 "f0_operand" "")) - (use (match_operand:HI 5 "gpr_operand" "")) - (use (const_int 0))] - "TARGET_ACCUM && reload_completed" - [(set (match_dup 3) - (and:HI (match_dup 2) - (const_int 15))) - (parallel [(set (match_dup 0) - (ashift:SI (match_dup 0) - (match_dup 3))) - (use (const_int 1))]) - (set (match_dup 3) - (plus:HI (match_dup 2) - (const_int -15))) - (parallel [(set (match_dup 3) - (smax:HI (match_dup 3) - (match_dup 5))) - (clobber (match_dup 4))]) - (parallel [(set (match_dup 0) - (ashift:SI (match_dup 0) - (match_dup 3))) - (use (const_int 1))])] - "") - -(define_expand "ashrhi3" - [(set (match_operand:HI 0 "gpr_operand" "") - (ashiftrt:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT && !IN_RANGE_P (INTVAL (operands[2]), 0, 15)) - operands[2] = force_reg (HImode, operands[2]); -}") - -(define_insn "*ashrhi3_internal" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (ashiftrt:HI (match_operand:HI 1 "gpr_operand" "0,0,0") - (match_operand:HI 2 "arith16_operand" "I,O,d")))] - "GET_CODE (operands[2]) != CONST_INT || IN_RANGE_P (INTVAL (operands[2]), 0, 15)" - "@ - srai %0,%2 - nop - sra %0,%2" - [(set_attr "type" "iu,either,iu") - (set_attr "length" "1,1,1")]) - -(define_expand "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - " -{ - if (!TARGET_ACCUM && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 16)) - FAIL; - - if (GET_CODE (operands[2]) == CONST_INT && ((unsigned long)INTVAL (operands[2])) > 31) - operands[2] = force_reg (HImode, operands[2]); - - if (GET_CODE (operands[2]) != CONST_INT) - { - emit_insn (gen_ashrsi3_variable (operands[0], operands[1], operands[2], - gen_reg_rtx (HImode), - gen_rtx (REG, CCmode, F0_REGNUM), - gen_rtx (REG, HImode, GPR_ZERO_REGNUM))); - DONE; - } -}") - -(define_insn "*ashrsi3_16" - [(set (match_operand:SI 0 "register_operand" "=e,e,a") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,e,0") - (const_int 16)))] - "" - "@ - mv %L0,%U1\;srai %U0,15 - mv %L0,%U1\;mv %U0,%U1\;srai %U0,15 - srai %0,16" - [(set_attr "type" "long,long,long") - (set_attr "length" "2,3,2")]) - -(define_insn "*ashrsi3_constant" - [(set (match_operand:SI 0 "accum_operand" "=a,a,a") - (ashiftrt:SI (match_operand:SI 1 "accum_operand" "0,0,0") - (match_operand:SI 2 "const_int_operand" "I,O,n")))] - "TARGET_ACCUM && ((unsigned HOST_WIDE_INT)INTVAL (operands[2])) <= 31" - "* -{ - HOST_WIDE_INT shift_value = INTVAL (operands[2]); - - if (shift_value == 0) - return \"\"; - - if (shift_value <= 16) - return \"srai %0,%2\"; - - operands[3] = GEN_INT (16); - operands[4] = GEN_INT (shift_value - 16); - return \"srai %0,%3\;srai %0,%4\"; -}" - [(set_attr "type" "iu,either,long") - (set_attr "length" "1,1,2")]) - -(define_insn "ashrsi3_variable" - [(set (match_operand:SI 0 "accum_operand" "=a") - (ashiftrt:SI (match_operand:SI 1 "accum_operand" "0") - (match_operand:HI 2 "gpr_operand" "d"))) - (clobber (match_operand:HI 3 "gpr_operand" "=&d")) - (clobber (match_operand:CC 4 "f0_operand" "")) - (use (match_operand:HI 5 "gpr_operand" "d")) - (use (const_int 0))] - "TARGET_ACCUM" - "#" - [(set_attr "type" "long") - (set_attr "length" "10")]) - -(define_insn "*ashrsi3_variable2" - [(set (match_operand:SI 0 "accum_operand" "=a") - (ashiftrt:SI (match_operand:SI 1 "accum_operand" "0") - (match_operand:HI 2 "gpr_operand" "d"))) - (use (const_int 1))] - "TARGET_ACCUM" - "sra %0,%2" - [(set_attr "type" "long") - (set_attr "length" "1")]) - -(define_split - [(set (match_operand:SI 0 "accum_operand" "") - (ashiftrt:SI (match_operand:SI 1 "accum_operand" "") - (match_operand:HI 2 "gpr_operand" ""))) - (clobber (match_operand:HI 3 "gpr_operand" "")) - (clobber (match_operand:CC 4 "f0_operand" "")) - (use (match_operand:HI 5 "gpr_operand" "")) - (use (const_int 0))] - "TARGET_ACCUM && reload_completed" - [(set (match_dup 3) - (and:HI (match_dup 2) - (const_int 15))) - (parallel [(set (match_dup 0) - (ashiftrt:SI (match_dup 0) - (match_dup 3))) - (use (const_int 1))]) - (set (match_dup 3) - (plus:HI (match_dup 2) - (const_int -15))) - (parallel [(set (match_dup 3) - (smax:HI (match_dup 3) - (match_dup 5))) - (clobber (match_dup 4))]) - (parallel [(set (match_dup 0) - (ashiftrt:SI (match_dup 0) - (match_dup 3))) - (use (const_int 1))])] - "") - -(define_expand "lshrhi3" - [(set (match_operand:HI 0 "gpr_operand" "") - (lshiftrt:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT && !IN_RANGE_P (INTVAL (operands[2]), 0, 15)) - operands[2] = force_reg (HImode, operands[2]); -}") - -(define_insn "*lshrhi3_internal" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (lshiftrt:HI (match_operand:HI 1 "gpr_operand" "0,0,0") - (match_operand:HI 2 "arith16_operand" "I,O,d")))] - "GET_CODE (operands[2]) != CONST_INT || IN_RANGE_P (INTVAL (operands[2]), 0, 15)" - "@ - srli %0,%2 - nop - srl %0,%2" - [(set_attr "type" "iu,either,iu") - (set_attr "length" "1,1,1")]) - -(define_expand "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "") - (match_operand:HI 2 "arith16_operand" "")))] - "" - " -{ - if (!TARGET_ACCUM && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 16)) - FAIL; - - if (GET_CODE (operands[2]) == CONST_INT && ((unsigned long)INTVAL (operands[2])) > 31) - operands[2] = force_reg (HImode, operands[2]); - - if (GET_CODE (operands[2]) != CONST_INT) - { - emit_insn (gen_lshrsi3_variable (operands[0], operands[1], operands[2], - gen_reg_rtx (HImode), - gen_rtx (REG, CCmode, F0_REGNUM), - gen_rtx (REG, HImode, GPR_ZERO_REGNUM))); - DONE; - } -}") - -(define_insn "*lshlsi3_16" - [(set (match_operand:SI 0 "register_operand" "=e,a") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "e,0") - (const_int 16)))] - "" - "@ - mv %L0,%U1\;ldi %U0,0 - srli %0,16" - [(set_attr "type" "long,long") - (set_attr "length" "2,2")]) - -(define_insn "*lshlsi3_constant" - [(set (match_operand:SI 0 "accum_operand" "=a,a,a") - (lshiftrt:SI (match_operand:SI 1 "accum_operand" "0,0,0") - (match_operand:SI 2 "const_int_operand" "I,O,n")))] - "TARGET_ACCUM && ((unsigned HOST_WIDE_INT)INTVAL (operands[2])) <= 31" - "* -{ - HOST_WIDE_INT shift_value = INTVAL (operands[2]); - - if (shift_value == 0) - return \"\"; - - if (shift_value <= 16) - return \"srli %0,%2\"; - - operands[3] = GEN_INT (16); - operands[4] = GEN_INT (shift_value - 16); - return \"srli %0,%3\;srli %0,%4\"; -}" - [(set_attr "type" "iu,either,long") - (set_attr "length" "1,1,2")]) - -(define_insn "lshrsi3_variable" - [(set (match_operand:SI 0 "accum_operand" "=a") - (lshiftrt:SI (match_operand:SI 1 "accum_operand" "0") - (match_operand:HI 2 "gpr_operand" "d"))) - (clobber (match_operand:HI 3 "gpr_operand" "=&d")) - (clobber (match_operand:CC 4 "f0_operand" "")) - (use (match_operand:HI 5 "gpr_operand" "d")) - (use (const_int 0))] - "TARGET_ACCUM" - "#" - [(set_attr "type" "long") - (set_attr "length" "10")]) - -(define_insn "*lshrsi3_variable2" - [(set (match_operand:SI 0 "accum_operand" "=a") - (lshiftrt:SI (match_operand:SI 1 "accum_operand" "0") - (match_operand:HI 2 "gpr_operand" "d"))) - (use (const_int 1))] - "TARGET_ACCUM" - "srl %0,%2" - [(set_attr "type" "long") - (set_attr "length" "1")]) - -(define_split - [(set (match_operand:SI 0 "accum_operand" "") - (lshiftrt:SI (match_operand:SI 1 "accum_operand" "") - (match_operand:HI 2 "gpr_operand" ""))) - (clobber (match_operand:HI 3 "gpr_operand" "")) - (clobber (match_operand:CC 4 "f0_operand" "")) - (use (match_operand:HI 5 "gpr_operand" "")) - (use (const_int 0))] - "TARGET_ACCUM && reload_completed" - [(set (match_dup 3) - (and:HI (match_dup 2) - (const_int 15))) - (parallel [(set (match_dup 0) - (lshiftrt:SI (match_dup 0) - (match_dup 3))) - (use (const_int 1))]) - (set (match_dup 3) - (plus:HI (match_dup 2) - (const_int -15))) - (parallel [(set (match_dup 3) - (smax:HI (match_dup 3) - (match_dup 5))) - (clobber (match_dup 4))]) - (parallel [(set (match_dup 0) - (lshiftrt:SI (match_dup 0) - (match_dup 3))) - (use (const_int 1))])] - "") - - -;; -;; .................... -;; -;; Min/max/abs -;; -;; .................... - -(define_expand "sminhi3" - [(parallel [(set (match_operand:HI 0 "gpr_operand" "") - (smin:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "reg_or_0_operand" ""))) - (clobber (match_dup 3))])] - "" - "operands[3] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*sminhi3_internal" - [(set (match_operand:HI 0 "gpr_operand" "=d,d") - (smin:HI (match_operand:HI 1 "gpr_operand" "%0,0") - (match_operand:HI 2 "reg_or_0_operand" "d,O"))) - (clobber (match_operand:CC 3 "f0_operand" ""))] - "" - "@ - min %0,%2 - min %0,%." - [(set_attr "type" "iu,iu") - (set_attr "length" "1,1")]) - -(define_expand "sminsi3" - [(parallel [(set (match_operand:SI 0 "gpr_operand" "") - (smin:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_operand" ""))) - (clobber (match_dup 3))])] - "TARGET_ACCUM" - "operands[3] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*sminsi3_internal" - [(set (match_operand:SI 0 "gpr_operand" "=a") - (smin:SI (match_operand:SI 1 "gpr_operand" "%0") - (match_operand:SI 2 "gpr_operand" "ad"))) - (clobber (match_operand:CC 3 "f0_operand" ""))] - "TARGET_ACCUM" - "min %0,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_expand "smaxhi3" - [(parallel [(set (match_operand:HI 0 "gpr_operand" "") - (smax:HI (match_operand:HI 1 "gpr_operand" "") - (match_operand:HI 2 "reg_or_0_operand" ""))) - (clobber (match_dup 3))])] - "" - "operands[3] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*smaxhi3_internal" - [(set (match_operand:HI 0 "gpr_operand" "=d,d") - (smax:HI (match_operand:HI 1 "gpr_operand" "%0,0") - (match_operand:HI 2 "reg_or_0_operand" "d,O"))) - (clobber (match_operand:CC 3 "f0_operand" ""))] - "" - "@ - max %0,%2 - max %0,%." - [(set_attr "type" "iu,iu") - (set_attr "length" "1,1")]) - -(define_expand "smaxsi3" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (smax:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" ""))) - (clobber (match_dup 3))])] - "TARGET_ACCUM" - "operands[3] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*smaxsi3_internal" - [(set (match_operand:SI 0 "accum_operand" "=a") - (smax:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "register_operand" "ad"))) - (clobber (match_operand:CC 3 "f0_operand" ""))] - "TARGET_ACCUM" - "max %0,%2" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_expand "abshi2" - [(parallel [(set (match_operand:HI 0 "gpr_operand" "") - (abs:HI (match_operand:HI 1 "gpr_operand" ""))) - (clobber (match_dup 3))])] - "" - "operands[3] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*abshi2_internal" - [(set (match_operand:HI 0 "gpr_operand" "=d") - (abs:HI (match_operand:HI 1 "gpr_operand" "0"))) - (clobber (match_operand:CC 3 "f0_operand" ""))] - "" - "abs %0" - [(set_attr "type" "either") - (set_attr "length" "1")]) - -(define_expand "abssi2" - [(parallel [(set (match_operand:SI 0 "register_operand" "") - (abs:SI (match_operand:SI 1 "register_operand" ""))) - (clobber (match_dup 3))])] - "TARGET_ACCUM" - "operands[3] = gen_rtx (REG, CCmode, F0_REGNUM);") - -(define_insn "*abssi2_internal" - [(set (match_operand:SI 0 "accum_operand" "=a") - (abs:SI (match_operand:SI 1 "register_operand" "0"))) - (clobber (match_operand:CC 3 "f0_operand" ""))] - "TARGET_ACCUM" - "abs %0" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - - -;; -;; .................... -;; -;; Peepholes -;; -;; .................... - -(define_peephole - [(set (match_operand:HI 0 "gpr_operand" "=e") (match_operand:HI 1 "gpr_operand" "e")) - (set (match_operand:HI 2 "gpr_operand" "=d") (match_operand:HI 3 "gpr_operand" "d"))] - "((REGNO (operands[0]) & 1) == 0 && (REGNO (operands[2]) == REGNO (operands[0]) + 1) - && (REGNO (operands[1]) & 1) == 0 && (REGNO (operands[3]) == REGNO (operands[1]) + 1))" - "mv2w %0,%1" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_peephole - [(set (match_operand:HI 0 "gpr_operand" "=d") (match_operand:HI 1 "gpr_operand" "d")) - (set (match_operand:HI 2 "gpr_operand" "=e") (match_operand:HI 3 "gpr_operand" "e"))] - "((REGNO (operands[2]) & 1) == 0 && (REGNO (operands[2]) == REGNO (operands[0]) - 1) - && (REGNO (operands[3]) & 1) == 0 && (REGNO (operands[3]) == REGNO (operands[1]) - 1))" - "mv2w %2,%3" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_peephole - [(set (match_operand:HI 0 "gpr_operand" "=e,e") (match_operand:HI 1 "memory_operand" "Q,m")) - (set (match_operand:HI 2 "gpr_operand" "=d,d") (match_operand:HI 3 "memory_operand" "Q,m"))] - "((REGNO (operands[0]) & 1) == 0 && (REGNO (operands[2]) == REGNO (operands[0]) + 1) - && adjacent_memory_operands (operands[1], operands[3], insn) - && !reg_mentioned_p (operands[0], operands[3]))" - "ld2w %0,%M1" - [(set_attr "type" "mu,mu") - (set_attr "length" "1,2")]) - -(define_peephole - [(set (match_operand:HI 0 "gpr_operand" "=d,d") (match_operand:HI 1 "memory_operand" "Q,m")) - (set (match_operand:HI 2 "gpr_operand" "=e,e") (match_operand:HI 3 "memory_operand" "Q,m"))] - "((REGNO (operands[2]) & 1) == 0 && (REGNO (operands[2]) == REGNO (operands[0]) - 1) - && adjacent_memory_operands (operands[3], operands[1], insn) - && !reg_mentioned_p (operands[0], operands[3]))" - "ld2w %2,%M3" - [(set_attr "type" "mu,mu") - (set_attr "length" "1,2")]) - -(define_peephole - [(set (match_operand:HI 0 "memory_operand" "=Q,m") (match_operand:HI 1 "gpr_operand" "e,e")) - (set (match_operand:HI 2 "memory_operand" "=Q,m") (match_operand:HI 3 "gpr_operand" "d,d"))] - "((REGNO (operands[1]) & 1) == 0 && (REGNO (operands[3]) == REGNO (operands[1]) + 1) - && adjacent_memory_operands (operands[0], operands[2], insn))" - "st2w %1,%M0" - [(set_attr "type" "mu,mu") - (set_attr "length" "1,2")]) - -(define_peephole - [(set (match_operand:HI 0 "memory_operand" "=Q,m") (match_operand:HI 1 "gpr_operand" "d,d")) - (set (match_operand:HI 2 "memory_operand" "=Q,m") (match_operand:HI 3 "gpr_operand" "e,e"))] - "((REGNO (operands[3]) & 1) == 0 && (REGNO (operands[3]) == REGNO (operands[1]) - 1) - && adjacent_memory_operands (operands[2], operands[0], insn))" - "st2w %3,%M2" - [(set_attr "type" "mu,mu") - (set_attr "length" "1,2")]) - -;; Peepholes for tst0i, tst1i, and btsti instructions -(define_peephole - [(set (match_operand:HI 0 "gpr_operand" "=d") - (and:HI (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "const_int_operand" "n"))) - (set (match_operand:CC_REV 3 "f0_operand" "") - (ne:CC_REV (match_dup 0) - (const_int 0))) - (set (pc) - (if_then_else (match_operator:CC 4 "f0_compare_operator" - [(match_dup 3) - (const_int 0)]) - (match_operand 5 "pc_or_label_operand" "") - (match_operand 6 "pc_or_label_operand" "")))] - "IN_RANGE_P (exact_log2 (INTVAL (operands[2])), 0, 15) - && find_regno_note (prev_nonnote_insn (insn), REG_DEAD, REGNO (operands[0])) - && find_regno_note (insn, REG_DEAD, F0_REGNUM)" - "* -{ - operands[7] = GEN_INT (15 - exact_log2 (INTVAL (operands[2]))); - output_asm_insn (\"btsti %1,%7\", operands); - - if (operands[5] == pc_rtx) - return (GET_CODE (operands[6]) == RETURN) ? \"jmp r13 || exef0%T4\" : \"brf0%F4 %l6\"; - else - return (GET_CODE (operands[5]) == RETURN) ? \"jmp r13 || exef0%F4\" : \"brf0%T4 %l5\"; -}" - [(set_attr "type" "long") - (set_attr "length" "4")]) - -(define_peephole - [(set (match_operand:HI 0 "gpr_operand" "=d") - (and:HI (not:HI (match_operand:HI 1 "gpr_operand" "d")) - (match_operand:HI 2 "const_int_operand" "n"))) - (set (match_operand:CC_REV 3 "f0_operand" "") - (ne:CC (match_dup 0) - (const_int 0)))] - "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))" - "tst1i %1,%2" - [(set_attr "type" "long") - (set_attr "length" "2")]) - -(define_peephole - [(set (match_operand:HI 0 "gpr_operand" "=d") - (and:HI (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "const_int_operand" "n"))) - (set (match_operand:CC 3 "f0_operand" "") - (eq:CC_REV (match_dup 0) - (const_int 0)))] - "IN_RANGE_P (exact_log2 (INTVAL (operands[2])), 0, 15) - && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))" - "* -{ - operands[4] = GEN_INT (15 - exact_log2 (INTVAL (operands[2]))); - return \"btsti %1,%4\"; -}" - [(set_attr "type" "iu") - (set_attr "length" "1")]) - -(define_peephole - [(set (match_operand:HI 0 "gpr_operand" "=d") - (and:HI (match_operand:HI 1 "gpr_operand" "d") - (match_operand:HI 2 "const_int_operand" "n"))) - (set (match_operand:CC 3 "f0_operand" "") - (eq:CC_REV (match_dup 0) - (const_int 0)))] - "!IN_RANGE_P (exact_log2 (INTVAL (operands[2])), 0, 15) - && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))" - "tst0i %1,%2" - [(set_attr "type" "long") - (set_attr "length" "2")]) -;; END CYGNUS LOCAL -- meissner/d10v abi change diff --git a/gcc/config/d10v/libgcc1.asm b/gcc/config/d10v/libgcc1.asm deleted file mode 100755 index 2ee2040..0000000 --- a/gcc/config/d10v/libgcc1.asm +++ /dev/null @@ -1,556 +0,0 @@ -/* Assembly support functions for libgcc1. - * - * 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, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, 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. - */ - - -#ifdef L_ashlsi3 -/* Shift of 32 bit int left, r0-r1 == value to be shifted, r2 = shift amount */ - - .file "_ashlsi3.s" - .text - .globl __ashlsi3 - .type __ashlsi3,@function -__ashlsi3: - mv2wfac r4,a0 /* preserve accumulator & guard digits */ - mvfacg r12,a0 - mv2wtac r0,a0 - cmpui r2,16 - and3 r0,r2,15 - exef0f || slli a0,16 - sll a0,r0 - mv2wfac r0,a0 - mv2wtac r4,a0 - mvtacg r12,a0 - jmp r13 - .size __ashlsi3,.-__ashlsi3 -#endif - -#ifdef L_ashrsi3 -/* Shift of 32 bit signed int right, r0-r1 == value to be shifted, r2 = shift amount */ - - .file "_ashrsi3.s" - .text - .globl __ashrsi3 - .type __ashrsi3,@function -__ashrsi3: - mv2wfac r4,a0 /* preserve accumulator & guard digits */ - mvfacg r12,a0 - mv2wtac r0,a0 - cmpui r2,16 - and3 r0,r2,15 - exef0f || srai a0,16 - sra a0,r0 - mv2wfac r0,a0 - mv2wtac r4,a0 - mvtacg r12,a0 - jmp r13 - .size __ashrsi3,.-__ashrsi3 -#endif - -#ifdef L_lshrsi3 -/* Shift of 32 bit unsigned int right, r0-r1 == value to be shifted, r2 = shift amount */ - - .file "_lshrsi3.s" - .text - .globl __lshrsi3 - .type __lshrsi3,@function -__lshrsi3: - mv2wfac r4,a0 /* preserve accumulator & guard digits */ - mvfacg r12,a0 - mv2wtac r0,a0 - mvtacg r14,a0 /* zero guard digits */ - cmpui r2,16 - and3 r0,r2,15 - exef0f || srli a0,16 - srl a0,r0 - mv2wfac r0,a0 - mv2wtac r4,a0 - mvtacg r12,a0 - jmp r13 - .size __lshrsi3,.-__lshrsi3 -#endif - -#ifdef L_mulsi3 -/* Multiply 2 32-bit signed integers with a 32-bit result, r0-r1 = first number, - r2-r3 = second number. */ - - .file "_mulsi3.s" - .text - .globl __mulsi3 - .type __mulsi3,@function -__mulsi3: - mv2wfac r4,a0 /* preserve accumulator & guard digits */ - mvfacg r12,a0 - mulxu a0,r0,r3 - macu a0,r1,r2 - slli a0,16 - macu a0,r1,r3 - mv2wfac r0,a0 - mv2wtac r4,a0 - mvtacg r12,a0 - jmp r13 - .size __mulsi3,.-__mulsi3 -#endif - - -#ifdef L_udivmodhi4 -/* Unsigned divide 2 16-bit numbers, leaving the remainder in r0, and quotient - in r1. */ - - .file "_udivmodhi4.s" - .text - .globl __udivmodhi4 - .type __udivmodhi4,@function - .globl __umodhi3 - .type __umodhi3,@function -__udivmodhi4: -__umodhi3: - mv r2,r1 -> mv r1,r0 /* move divisor to safe register & create 32-bit value for dividend */ - ldi r0,0 /* high part of dividend */ - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - jmp r13 - .size __udivmodhi4,.-__udivmodhi4 - .size __umodhi3,.-__umodhi3 - - .globl __udivhi3 - .type __udivhi3,@function -__udivhi3: - st r13,@-sp - bl __udivmodhi4 - mv r0,r1 - ld r13,@sp+ - jmp r13 - .size __udivhi3,.-__udivhi3 -#endif - - -#ifdef L_divmodhi4 -/* Signed divide 2 16-bit numbers, leaving the remainder in r0, and quotient - in r1. */ - - .file "_divmodhi4.s" - .text - .globl __divmodhi4 - .type __divmodhi4,@function - .globl __modhi3 - .type __modhi3,@function -__divmodhi4: -__modhi3: - mv r2,r1 -> mv r1,r0 /* move divisor to safe register & create 32-bit value for dividend */ - ldi r0,0 || abs r1 /* high part of dividend */ - abs r2 || nop /* make sure divisor & dividend are positive (F0/F1 indicate if args were negative) */ - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - divs r0,r2 - exef1t || neg r0 - exef0t || neg r1 - exef1t || neg r1 - jmp r13 - .size __divmodhi4,.-__divmodhi4 - .size __modhi3,.-__modhi3 - - .globl __divhi3 - .type __divhi3,@function -__divhi3: - st r13,@-sp - bl __divmodhi4 - mv r0,r1 - ld r13,@sp+ - jmp r13 - .size __divhi3,.-__divhi3 -#endif - - -#ifdef L_udivmodsi4 -/* Unsigned divide 2 32-bit numbers, leaving the remainder in r0-r1, and quotient - in r2-r3. */ - - .file "_udivmodsi4.s" - .text - .globl __udivmodsi4 - .type __udivmodsi4,@function - .globl __udivsi3 - .type __udivsi3,@function - /* input: r0-r1 = dividend, r2-r3 = divisor */ - /* output: r0-r1 = quotient, r2-r3 = remainder */ -__udivmodsi4: -__udivsi3: - cmpeqi r0,0 -> brf0f.s .Llong /* if we are doing short/short do it with divs */ - cmpeqi r2,0 -> brf0f.s .Llong - - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - divs r0,r3 - mv r3,r0 - ldi r0,0 - jmp r13 - -.Llong: - st2w r6,@-sp - st2w r8,@-sp - mv2w r4,r2 /* divisor (b) */ - ldi r2,0 /* high part of dividend (ah) */ - ldi r3,0 - ldi r12,32 /* number of iterations */ -.Lloop: - mv2w r6,r2 /* tmp1 = (ah << 1) | (al >> 31) */ - add2w r6,r6 - cmpi r0,0 - exef0t || addi r7,1 - - mv2w r8,r6 /* tmp2 = tmp1 - b */ - sub2w r8,r4 - - cmpeq r6,r4 /* tmpf = (tmp1 >= b), ie f0 = !(tmp1 < b) */ - cmpu r6,r4 - exef1t || cmpu r7,r5 - - mv2w r2,r6 /* ah = (tmpf) ? tmp1 : tmp2 */ - exef0f || mv2w r2,r8 - - add2w r0,r0 /* al = (al << 1) | tmpf */ - exef0f || addi r1,1 - - subi r12,1 /* decrement and loop */ - cmpeqi r12,0 - brf0f.s .Lloop /* work around simulator bug with .s version of brf0f */ - - ld2w r8,@sp+ - ld2w r6,@sp+ - jmp r13 - .size __udivmodsi4,.-__udivmodsi4 - .size __udivsi3,.-__udivsi3 - - .globl __umodsi3 - .type __umodsi3,@function -__umodsi3: - st r13,@-sp - bl __udivmodsi4 - mv2w r0,r2 - ld r13,@sp+ - jmp r13 - .size __modvsi3,.-__modvsi3 -#endif - - -#ifdef L_divmodsi4 -/* Signed divide 2 32-bit numbers, leaving the remainder in r0-r1, and quotient - in r2-r3. */ - - .file "_divmodsi4.s" - .text - .globl __divmodsi4 - .type __divmodsi4,@function - .globl __divsi3 - .type __divsi3,@function -__divmodsi4: -__divsi3: - cmpi r0,0 /* divisor negative? */ - brf0t.s .Lneg1 - - cmpi r2,0 /* dividend negative? */ - brf0t.s .Lneg3 - - bra __udivmodsi4 /* both positive, just do division, __udivmodsi4 will return to caller */ - -.Lneg1: /* divisor negative, dividend sign not yet checked */ - st r13,@-sp - not r0 /* negate divisor */ - neg r1 - cmpeqi r1,0 - exef0t || addi r0,1 - - cmpi r2,0 /* dividend negative? */ - brf0t.s .Lneg2 - - bl __udivmodsi4 /* do division */ - - not r0 /* negate quotient */ - neg r1 - cmpeqi r1,0 - exef0t || addi r0,1 - - not r2 /* negate remainder */ - neg r3 - cmpeqi r3,0 - exef0t || addi r2,1 - ld r13,@sp+ - jmp r13 - -.Lneg2: /* divisor & dividend negative */ - not r2 /* negate dividend */ - neg r3 - cmpeqi r3,0 - exef0t || addi r2,1 - - bl __udivmodsi4 /* do division */ - - not r2 /* negate remainder */ - neg r3 - cmpeqi r3,0 - exef0t || addi r2,1 - ld r13,@sp+ - jmp r13 - -.Lneg3: /* divisor positive, dividend negative */ - st r13,@-sp - not r2 /* negate dividend */ - neg r3 - cmpeqi r3,0 - exef0t || addi r2,1 - - bl __udivmodsi4 /* do division */ - - not r0 /* negate quotient */ - neg r1 - cmpeqi r1,0 - exef0t || addi r0,1 - ld r13,@sp+ - jmp r13 - .size __divmodsi4,.-__divmodsi4 - .size __divsi3,.-__divsi3 - - .globl __modsi3 - .type __modsi3,@function -__modsi3: - st r13,@-sp - bl __divmodsi4 - mv2w r0,r2 - ld r13,@sp+ - jmp r13 - .size __modsi3,.-__modsi3 -#endif - - -#ifdef L_cmpdi -/* Signed compare 2 64-bit ints */ - - .file "__cmpdi.s" - .text - .globl __cmpdi - .type __cmpdi,@function - /* input: r0-r3 is first value to compare, second value to compare on stack */ - /* output: r0 is 0 if op0 < op1, 1 if op0 == op1, 2 if op0 > op1 */ -__cmpdi: - ld2w r4,@sp /* compare first word */ - cmp r0,r4 - brf0t.s .Lneg - cmp r4,r0 - brf0t.s .Lpos - - cmpu r1,r5 /* compare second word */ - brf0t.s .Lneg - cmpu r5,r1 - brf0t.s .Lpos - - ld2w r4,@(4,sp) /* compare third word */ - cmpu r2,r4 - brf0t.s .Lneg - cmpu r4,r2 - brf0t.s .Lpos - - cmpu r3,r5 /* compare fourth word */ - brf0t.s .Lneg - cmpu r5,r3 - brf0t.s .Lpos - - ldi r0,1 /* op1 == op2 */ - jmp r13 - -.Lneg: - ldi r0,0 /* op1 < op2 */ - jmp r13 - -.Lpos: - ldi r0,2 /* op1 > op2 */ - jmp r13 - .size __cmpdi,.-__cmpdi -#endif - - -#ifdef L_cmpdi0 -/* Signed compare 64-bit int against 0 */ - - .file "__cmpdi0.s" - .text - .globl __cmpdi0 - .type __cmpdi0,@function - /* input: r0-r3 is value to compare */ - /* output: r0 is -1 if op0 < 0, 0 if op0 == 0, 1 if op0 > 0 */ -__cmpdi0: - cmpi r0,0 /* compare first word */ - brf0t.s .Lneg - cmpeqi r0,0 - brf0f.s .Lpos - - cmpeqi r1,0 /* compare second word */ - brf0f.s .Lpos - - cmpeqi r2,0 /* compare third word */ - brf0f.s .Lpos - - cmpeqi r3,0 /* compare fourth word */ - brf0f.s .Lpos - - ldi r0,1 /* op1 == 0 */ - jmp r13 - -.Lneg: - ldi r0,0 /* op1 < 0 */ - jmp r13 - -.Lpos: - ldi r0,2 /* op1 > 0 */ - jmp r13 - .size __cmpdi0,.-__cmpdi0 -#endif - - -#ifdef L_ucmpdi -/* Unsigned compare 2 64-bit ints */ - - .file "__ucmpdi.s" - .text - .globl __ucmpdi - .type __ucmpdi,@function - /* input: r0-r3 is first value to compare, second value to compare on stack */ - /* output: r0 is -1 if (unsigned)op0 < (unsigned)op1, 0 if op0 == op1, 1 if (unsigned)op0 > (unsigned)op1 */ -__ucmpdi: - ld2w r4,@sp /* compare first word */ - cmpu r0,r4 - brf0t.s .Lneg - cmpu r4,r0 - brf0t.s .Lpos - - cmpu r1,r5 /* compare second word */ - brf0t.s .Lneg - cmpu r5,r1 - brf0t.s .Lpos - - ld2w r4,@(4,sp) /* compare third word */ - cmpu r2,r4 - brf0t.s .Lneg - cmpu r4,r2 - brf0t.s .Lpos - - cmpu r3,r5 /* compare fourth word */ - brf0t.s .Lneg - cmpu r5,r3 - brf0t.s .Lpos - - ldi r0,1 /* op1 == op2 */ - jmp r13 - -.Lneg: - ldi r0,0 /* op1 < op2 */ - jmp r13 - -.Lpos: - ldi r0,2 /* op1 > op2 */ - jmp r13 - .size __ucmpdi,.-__ucmpdi -#endif - - -#ifdef L_ucmpdi0 -/* Unsigned compare 64-bit int against 0 */ - - .file "__ucmpdi0.s" - .text - .globl __ucmpdi0 - .type __ucmpdi0,@function - /* input: r0-r3 is value to compare */ - /* output: r0 is 0 if op0 == 0, 1 if op0 > 0 */ -__ucmpdi0: - cmpeqi r0,0 /* compare first word */ - brf0f.s .Lpos - - cmpeqi r1,0 /* compare second word */ - brf0f.s .Lpos - - cmpeqi r2,0 /* compare third word */ - brf0f.s .Lpos - - cmpeqi r3,0 /* compare fourth word */ - brf0f.s .Lpos - - ldi r0,1 /* op1 == 0 */ - jmp r13 - -.Lpos: - ldi r0,2 /* op1 > 0 */ - jmp r13 - .size __ucmpdi0,.-__ucmpdi0 -#endif diff --git a/gcc/config/d10v/scrt0.asm b/gcc/config/d10v/scrt0.asm deleted file mode 100755 index 1aea69a..0000000 --- a/gcc/config/d10v/scrt0.asm +++ /dev/null @@ -1,45 +0,0 @@ -/* - * special crt0 support for simulator - * - * Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. - * Written By Michael Meissner - * - * 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, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, 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. - */ - - .file "scrt0.s" - .text - .type _start,@function - .globl _start -_start: ldi r14,0 - ldi sp, _stack - bl main - stop - .size _start,.-_start diff --git a/gcc/config/d10v/sim.asm b/gcc/config/d10v/sim.asm deleted file mode 100755 index 08393ed..0000000 --- a/gcc/config/d10v/sim.asm +++ /dev/null @@ -1,81 +0,0 @@ -/* - * special support for simulator - * - * Copyright (C) 1996 Free Software Foundation, Inc. - * Written By Michael Meissner - * - * 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, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, 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. - */ - - .file "sim.s" - .text - - .globl printf - .type printf,@function -printf: - trap 2 - jmp r13 - .size printf,.-printf - - .globl putchar - .type putchar,@function -putchar: - trap 3 - jmp r13 - .size putchar,.-putchar - - .globl putstr - .type putstr,@function -putstr: - trap 1 - jmp r13 - .size putstr,.-putstr - - .globl exit - .type exit,@function - .globl _exit - .type _exit,@function -exit: -_exit: - ldi r6,1 -> trap 0 /* SYS_exit */ - stop - .size exit,.-exit - .size _exit,.-_exit - - .globl abort - .type aobrt,@function -abort: - ldi r2,amsg - trap 1 - ldi r6,1 || ldi r2,1 /* SYS_exit & non-zero return code */ - trap 0 -> stop - - .section .rodata -amsg: .ascii "Abort called\n\0" diff --git a/gcc/config/d10v/t-d10v b/gcc/config/d10v/t-d10v deleted file mode 100755 index 8693aaa..0000000 --- a/gcc/config/d10v/t-d10v +++ /dev/null @@ -1,30 +0,0 @@ -# Build libgcc1 from assembler sources -LIBGCC1 = libgcc1-asm.a -CROSS_LIBGCC1 = libgcc1-asm.a -LIB1ASMSRC = d10v/libgcc1.asm -LIB1ASMFUNCS = _ashlsi3 _ashrsi3 _lshrsi3 _mulsi3 _udivmodhi4 _divmodhi4 _udivmodsi4 _divmodsi4 _cmpdi _cmpdi0 _ucmpdi _ucmpdi0 - -# These are really part of libgcc1, but this will cause them to be -# built correctly, so... -LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c - -dp-bit.c: $(srcdir)/config/fp-bit.c - echo '#define CMPtype HItype' > dp-bit.c - echo '#define SMALL_MACHINE' >> dp-bit.c - cat $(srcdir)/config/fp-bit.c >> dp-bit.c - -fp-bit.c: $(srcdir)/config/fp-bit.c - echo '#define FLOAT' > fp-bit.c - echo '#define CMPtype HItype' >> fp-bit.c - echo '#define SMALL_MACHINE' >> fp-bit.c - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - -# Build libgcc.a with different options. - -MULTILIB_OPTIONS = mint16/mint32 mdouble32/mdouble64 -MULTILIB_DIRNAMES = int16 int32 dbl32 dbl64 -MULTILIB_MATCHES = -MULTILIB_EXCEPTIONS = - -LIBGCC = stmp-multilib -INSTALL_LIBGCC = install-multilib diff --git a/gcc/config/d10v/xm-d10v.h b/gcc/config/d10v/xm-d10v.h deleted file mode 100755 index 46c3f97..0000000 --- a/gcc/config/d10v/xm-d10v.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Configuration for Mitsubishi D10V. - Copyright (C) 1996 Free Software Foundation, Inc. - Contributed by Cygnus Support. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 8 -#define HOST_BITS_PER_SHORT 16 -#if __INT_MAX__==32767 -#define HOST_BITS_PER_INT 16 -#else -#define HOST_BITS_PER_INT 32 -#endif -#define HOST_BITS_PER_LONG 32 -#define HOST_BITS_PER_LONGLONG 64 - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* Declare all of the functions in string.h and malloc functions when - compiling libgcc2 with -mint32 so that we account for size_t being - a short. */ -#ifdef __D10V__ -#include - -void *memchr(const void *, int, size_t); -int memcmp(const void *, const void *, size_t); -void *memcpy(void *, const void *, size_t); -void *memmove(void *, const void *, size_t); -void *memset(void *, int, size_t); -char *strcat(char *, const char *); -char *strchr(const char *, int); -int strcmp(const char *, const char *); -int strcoll(const char *, const char *); -char *strcpy(char *, const char *); -size_t strcspn(const char *, const char *); -char *strerror(int); -size_t strlen(const char *); -char *strncat(char *, const char *, size_t); -int strncmp(const char *, const char *, size_t); -char *strncpy(char *, const char *, size_t); -char *strpbrk(const char *, const char *); -char *strrchr(const char *, int); -size_t strspn(const char *, const char *); -char *strstr(const char *, const char *); -int ffs(int); - -extern void *malloc (size_t); -extern void *realloc (void *, size_t); -extern void free (void *); -#endif - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ - -#include "tm.h" diff --git a/gcc/config/d30v/abi b/gcc/config/d30v/abi deleted file mode 100755 index a434483..0000000 --- a/gcc/config/d30v/abi +++ /dev/null @@ -1,234 +0,0 @@ -CYGNUS LOCAL -- meissner/d30v - -*- Text -*- - -This document describes the proposed ABI for the D30V processor. This is -revision 2 of the document. - -Revision history: - -Revision 1: - Original revision of this document. - -Revision 2: - Done after consultation with Mitsubshi about the calling sequence. - This revision now reduces the number of registers the compiler will not - touch from 18 registers down to 8. - - Register 1 is now a normal temporary register, since mvfacc rx,ay,32 is - legal. - - Arguments greater than 4 bytes must be passed in an even register or at - a double word alignment. - - The va_list type is a structure, not a char *. - - The stack must be aligned to 8 byte boundary. Doubles and long longs - must also be aligned to 8 byte boundaries. - - System calls are specified via trap 31. - -Revision 3: - I added discussion about compiler switches. - -Register usage: -=============== - - Registers Call Status Usage - --------- ----------- ----- - R0 hardware Hardwired to 0 - R1 volatile temp - R2 volatile Arg 1 and main return value. - R3 volatile Arg 2 and low bits of 64 bit returns - R4 - R17 volatile Args 3-16 - R18 volatile Static chain if used - R19 - R25 volatile temps - R26 - R33 saved Reserved for user use - R34 - R60 saved Registers preserved across calls - R61 saved Frame pointer if needed. - R62 saved Return address pointer (hardware) - R63 saved Stack pointer - CR0 - CR3 hardware {normal,backup} {psw,pc} - CR4 - CR6 hardware Reserved for future use - CR7 - CR9 volatile Repeat count, addresses - CR10 - CR11 saved Modulo start/end - CR12 - CR14 hardware Reserved for future use - CR15 - CR17 hardware Interrupt support - F0 - F1 volatile Execution flags - F2 - F3 volatile General flags - F4 - F7 volatile Special purpose flags - A0 volatile Accumulator - A1 saved Accumulator - -Notes on the register usage: -============================ - - 1) R61 will hold the frame pointer if it is needed. Normally the frame - pointer will not be needed, in which case this will become another - saved register. - - 2) Repeat instructions and delayed branches cannot cross call boundaries. - Similarly, all flags are assumed to not be preserved across calls. - - 3) Since so many registers are available, I reserved 8 registers (r26-r33) - for the user to use for any purpose (global variables, interrupt - routines, thread pointer, etc.). These registers will not be used by - the compiler for any purpose. - - 4) One of the two accumulators is saved across calls. - - 5) Doubles and long longs will only be allocated to even/odd register - pairs to allow use of the ld2w/st2w instructions. - -Miscellaneous call information: -=============================== - - 1) Structures are passed in registers, rounding them up to word - boundaries. - - 2) Any argument that is greater than word size (4 bytes) must be aligned - to a double word boundary and/or start in an even register. The - intention here is to be able to use the ld2w/st2w instructions for - moving doubles and long longs. - - 3) Variable argument functions are called with the same calling sequence - as non-variable argument functions. When called, a variable argument - function first saves the 16 registers (R2 - R17) used for passing - arguments. The va_list type is a structure. The first element of the - structure is a pointer to the first word saved on the stack, and the - second element is a number that gives which argument number is being - processed. - - 4) Word and double word sized structures/unions are returned in registers, - other functions returning structures expect a temporary area address to - be passed as the first argument. - - -The stack frame when a function is called looks like: - -high | .... | - +-------------------------------+ - | Argument word #20 | - +-------------------------------+ - | Argument word #19 | - +-------------------------------+ - | Argument word #18 | - +-------------------------------+ - | Argument word #17 | -low SP----> +-------------------------------+ - -After the prologue is executed, the stack frame will look like: - -high | .... | - +-------------------------------+ - | Argument word #20 | - +-------------------------------+ - | Argument word #19 | - +-------------------------------+ - | Argument word #18 | - +-------------------------------+ - | Argument word #17 | - Prev sp +-------------------------------+ - | | - | Save for arguments 1..16 if | - | the func. uses stdarg/varargs | - | | - +-------------------------------+ - | | - | Save area for preserved regs | - | | - +-------------------------------+ - | | - | Local variables | - | | - +-------------------------------+ - | | - | alloca space if used | - | | - +-------------------------------+ - | | - | Space for outgoing arguments | - | | -low SP----> +-------------------------------+ - -System Calls -============ - -System calls will be done using "TRAP 31". Input arguments will be in R2 - R5, -and the system call number will be in R6. Return values from the system call -will be in R2. Negative values of the return indicate the system call failed, -and the value is the negative of the error code. Here are the assigned system -call numbers (value in R6): - - exit 1 - open 2 - close 3 - read 4 - write 5 - lseek 6 - unlink 7 - getpid 8 - kill 9 - fstat 10 - (11 is reserved for sbrk) - argvlen 12 - argv 13 - chdir 14 - stat 15 - chmod 16 - utime 17 - time 18 - -Compiler Switches -================= - -The following d30v specific compiler switches are currently supported: - - -mextmem Link .text/.data/.bss/etc in external memory. - - -mextmemory Same as -mextmem. - - -monchip Link .text/.data/.bss/etc in the onchip data/text - memory. - - -mno-asm-optimize Do not pass -O to the assembler when optimizing (the -O - switch will mark two short instructions that don't - interfere with each other as being done parallel - instead of sequentially). - - -masm-optimize [default] If optimizing, pass -O to the assembler. - - -mbranch-cost=n Increase the internal costs of branches to n. Higher - costs means that the compiler will issue more - instructions to avoid doing a branch. The default is - 2. - - -mcond-exec=n Replace branches around n insns with conditional - execution if we can. Default is 4. - - -Sections -======== - -You can override the effect of the -mextmem/-monchip options by putting -functions into either the ".stext" or ".etext" sections. If you put them into -the ".stext" section, the linker will always link the function into the onchip -memory area. Similarly, if you put the function in the ".etext" section, the -linker will always link the function into the external memory area. - -Data can be controlled as well. If you put the data in the ".sdata" section, -the linker will put the data into the onchip data area. Similarly, if you put -the data in the ".edata" section, the linker will put the data into the -external memory. - - -Stack pointer -============= - -The crt0.o that we ship loads up the stack pointer with the value of the label -__stack. If you do not define a value for __stack, the linker will choose the -top of the onchip data area (0x20008000) for the stack pointer. You can set a -new value via the options: - - -Wl,-defsym,__stack=0x20008000 - -END CYGNUS LOCAL -- meissner/d30v diff --git a/gcc/config/d30v/d30v.c b/gcc/config/d30v/d30v.c deleted file mode 100755 index 8e70c4a..0000000 --- a/gcc/config/d30v/d30v.c +++ /dev/null @@ -1,3514 +0,0 @@ -/* CYGNUS LOCAL -- meissner/d30v */ -/* Definitions of target machine for use as an example. - Hack to fit. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. - Contributed by Cygnus Solutions. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "recog.h" -#include "expr.h" -#include "obstack.h" -#include "tree.h" -#include "except.h" -#include "function.h" - -static void d30v_print_operand_memory_reference PROTO((FILE *, rtx)); -static void d30v_build_long_insn PROTO((HOST_WIDE_INT, HOST_WIDE_INT, rtx, rtx)); - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -struct rtx_def *d30v_compare_op0; -struct rtx_def *d30v_compare_op1; - -/* Define the information needed to modify the epilogue for EH. */ - -rtx d30v_eh_epilogue_sp_ofs; - -/* Cached value of d30v_stack_info */ -static d30v_stack_t *d30v_stack_cache = (d30v_stack_t *)0; - -/* Cache for __builtin_return_addr */ -static rtx d30v_return_addr_rtx; - -/* Values of the -mbranch-cost=n string. */ -int d30v_branch_cost = D30V_DEFAULT_BRANCH_COST; -char *d30v_branch_cost_string = (char *)0; - -/* Values of the -mcond-exec=n string. */ -int d30v_cond_exec = D30V_DEFAULT_MAX_CONDITIONAL_EXECUTE; -char *d30v_cond_exec_string = (char *)0; - -/* Whether or not a hard register can accept a register */ -unsigned char hard_regno_mode_ok[ (int)MAX_MACHINE_MODE ][FIRST_PSEUDO_REGISTER]; - -/* Whether to try and avoid moves between two different modes */ -unsigned char modes_tieable_p[ (NUM_MACHINE_MODES) * (NUM_MACHINE_MODES) ]; - -/* Map register number to smallest register class. */ -enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER]; - -/* Map class letter into register class */ -enum reg_class reg_class_from_letter[256]; - - -/* Sometimes certain combinations of command options do not make - sense on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. - - Don't use this macro to turn on various extra optimizations for - `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ - -void -override_options () -{ - int regno, i, ok_p; - enum machine_mode mode1, mode2; - - /* Set up the branch cost information */ - if (d30v_branch_cost_string) - d30v_branch_cost = atoi (d30v_branch_cost_string); - - /* Set up max # instructions to use with conditional execution */ - if (d30v_cond_exec_string) - d30v_cond_exec = atoi (d30v_cond_exec_string); - - /* Setup hard_regno_mode_ok/modes_tieable_p */ - for (mode1 = VOIDmode; - (int)mode1 < NUM_MACHINE_MODES; - mode1 = (enum machine_mode)((int)mode1 + 1)) - { - int size = GET_MODE_SIZE (mode1); - int large_p = size > UNITS_PER_WORD; - int int_p = GET_MODE_CLASS (mode1) == MODE_INT; - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - if (mode1 == VOIDmode) - ok_p = FALSE; - - else if (GPR_P (regno)) - { - if (!large_p) - ok_p = TRUE; - else - ok_p = (((regno - GPR_FIRST) & 1) == 0); - } - - else if (FLAG_P (regno)) - ok_p = (mode1 == CCmode); - - else if (CR_P (regno)) - ok_p = int_p && !large_p; - - else if (ACCUM_P (regno)) - ok_p = (mode1 == DImode); - - else if (SPECIAL_REG_P (regno)) - ok_p = (mode1 == SImode); - - else - ok_p = FALSE; - - hard_regno_mode_ok[ (int)mode1 ][ regno ] = ok_p; - } - - /* A C expression that is nonzero if it is desirable to choose - register allocation so as to avoid move instructions between a - value of mode MODE1 and a value of mode MODE2. - - If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, - MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1, - MODE2)' must be zero. */ - for (mode2 = VOIDmode; - (int)mode2 <= NUM_MACHINE_MODES; - mode2 = (enum machine_mode)((int)mode2 + 1)) - { - if (mode1 == mode2) - ok_p = TRUE; - -#if 0 - else if (GET_MODE_CLASS (mode1) == MODE_INT - && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD - && GET_MODE_CLASS (mode2) == MODE_INT - && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD) - ok_p = TRUE; -#endif - - else - ok_p = FALSE; - - modes_tieable_p[ ((int)mode1 * (NUM_MACHINE_MODES)) + (int)mode2 ] = ok_p; - } - } - -#if 0 - for (mode1 = VOIDmode; - (int)mode1 < NUM_MACHINE_MODES; - mode1 = (enum machine_mode)((int)mode1 + 1)) - { - for (mode2 = VOIDmode; - (int)mode2 <= NUM_MACHINE_MODES; - mode2 = (enum machine_mode)((int)mode2 + 1)) - { - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (ok_p - && (hard_regno_mode_ok[(int)mode1][regno] - != hard_regno_mode_ok[(int)mode2][regno])) - error ("Bad modes_tieable_p for register %s, mode1 %s, mode2 %s", - reg_names[regno], GET_MODE_NAME (mode1), - GET_MODE_NAME (mode2)); - } - } -#endif - - /* A C expression whose value is a register class containing hard - register REGNO. In general there is more than one such class; - choose a class which is "minimal", meaning that no smaller class - also contains the register. */ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - enum reg_class class; - - if (GPR_P (regno)) - class = (IN_RANGE_P (regno, GPR_FIRST+2, GPR_FIRST+62) - && ((regno - GPR_FIRST) & 1) == 0) ? EVEN_REGS : GPR_REGS; - - else if (regno == FLAG_F0) - class = F0_REGS; - - else if (regno == FLAG_F1) - class = F1_REGS; - - else if (FLAG_P (regno)) - class = OTHER_FLAG_REGS; - - else if (ACCUM_P (regno)) - class = ACCUM_REGS; - - else if (regno == CR_RPT_C) - class = REPEAT_REGS; - - else if (CR_P (regno)) - class = CR_REGS; - - else if (SPECIAL_REG_P (regno)) - class = GPR_REGS; - - else - class = NO_REGS; - - regno_reg_class[regno] = class; - -#if 0 - { - static char *names[] = REG_CLASS_NAMES; - fprintf (stderr, "Register %s class is %s, can hold modes", reg_names[regno], names[class]); - for (mode1 = VOIDmode; - (int)mode1 < NUM_MACHINE_MODES; - mode1 = (enum machine_mode)((int)mode1 + 1)) - { - if (hard_regno_mode_ok[ (int)mode1 ][ regno ]) - fprintf (stderr, " %s", GET_MODE_NAME (mode1)); - } - fprintf (stderr, "\n"); - } -#endif - } - - /* A C expression which defines the machine-dependent operand - constraint letters for register classes. If CHAR is such a - letter, the value should be the register class corresponding to - it. Otherwise, the value should be `NO_REGS'. The register - letter `r', corresponding to class `GENERAL_REGS', will not be - passed to this macro; you do not need to handle it. - - The following letters are unavailable, due to being used as - constraints: - '0'..'9' - '<', '>' - 'E', 'F', 'G', 'H' - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' - 'Q', 'R', 'S', 'T', 'U' - 'V', 'X' - 'g', 'i', 'm', 'n', 'o', 'p', 'r', 's' */ - - for (i = 0; i < 256; i++) - reg_class_from_letter[i] = NO_REGS; - - reg_class_from_letter['a'] = ACCUM_REGS; - reg_class_from_letter['b'] = BR_FLAG_REGS; - reg_class_from_letter['c'] = CR_REGS; - reg_class_from_letter['d'] = GPR_REGS; - reg_class_from_letter['e'] = EVEN_REGS; - reg_class_from_letter['f'] = FLAG_REGS; - reg_class_from_letter['l'] = REPEAT_REGS; - reg_class_from_letter['x'] = F0_REGS; - reg_class_from_letter['y'] = F1_REGS; - reg_class_from_letter['z'] = OTHER_FLAG_REGS; -} - - -/* Return true if a memory operand is a short memory operand. */ - -int -short_memory_operand (op, mode_int) - register rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return (d30v_legitimate_address_p (mode_int, XEXP (op, 0), reload_completed) - == 1); -} - -/* Return true if a memory operand is a long operand. */ - -int -long_memory_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return (d30v_legitimate_address_p (mode_int, XEXP (op, 0), reload_completed) - == 2); -} - -/* Return true if a memory operand is valid for the D30V. */ - -int -d30v_memory_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return (d30v_legitimate_address_p (mode_int, XEXP (op, 0), reload_completed) - != 0); -} - -/* Return true if a memory operand uses a single register for the - address. */ - -int -single_reg_memory_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx addr; - int regno; - - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - addr = XEXP (op, 0); - if (! d30v_legitimate_address_p (mode_int, addr, reload_completed)) - return FALSE; - - if (GET_CODE (addr) == SUBREG) - addr = SUBREG_REG (addr); - - return (GET_CODE (addr) == REG); -} - -/* Return true if a memory operand uses a constant address. */ - -int -const_addr_memory_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (! d30v_legitimate_address_p (mode_int, XEXP (op, 0), reload_completed)) - return FALSE; - - switch (GET_CODE (XEXP (op, 0))) - { - default: - break; - - case SYMBOL_REF: - case LABEL_REF: - case CONST_INT: - case CONST: - return TRUE; - } - - return FALSE; -} - -/* Return true if operand is a memory reference suitable for a call. */ - -int -call_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (! d30v_legitimate_address_p (mode_int, XEXP (op, 0), reload_completed)) - return FALSE; - - switch (GET_CODE (XEXP (op, 0))) - { - default: - break; - - case SUBREG: - op = SUBREG_REG (op); - if (GET_CODE (op) != REG) - return FALSE; - - /* fall through */ - - case REG: - return (GPR_OR_PSEUDO_P (REGNO (XEXP (op, 0)))); - - case SYMBOL_REF: - case LABEL_REF: - case CONST_INT: - case CONST: - return TRUE; - } - - return FALSE; -} - -/* Return true if operand is a GPR register. */ - -int -gpr_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is an accumulator register. */ - -int -accum_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return ACCUM_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a GPR or an accumulator register. */ - -int -gpr_or_accum_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - if (ACCUM_P (REGNO (op))) - return TRUE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a CR register. */ - -int -cr_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return CR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is the repeat count register. */ - -int -repeat_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return (REGNO (op) == CR_RPT_C || REGNO (op) >= FIRST_PSEUDO_REGISTER); -} - -/* Return true if operand is a FLAG register. */ - -int -flag_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return FLAG_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is either F0 or F1. */ - -int -br_flag_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return BR_FLAG_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is either F0/F1 or the constants 0/1. */ - -int -br_flag_or_constant_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) == CONST_INT) - return (INTVAL (op) == 0 || INTVAL (op) == 1); - - if (GET_CODE (op) != REG) - return FALSE; - - return BR_FLAG_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is either F0 or F1, or a GPR register. */ - -int -gpr_or_br_flag_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)) || BR_FLAG_P (REGNO (op)); -} - -/* Return true if operand is the F0 register. */ - -int -f0_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return (REGNO (op) == FLAG_F0 || REGNO (op) >= FIRST_PSEUDO_REGISTER); -} - -/* Return true if operand is the F1 register. */ - -int -f1_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return (REGNO (op) == FLAG_F1 || REGNO (op) >= FIRST_PSEUDO_REGISTER); -} - -/* Return true if operand is the F1 register. */ - -int -carry_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) != REG) - return FALSE; - - return (REGNO (op) == FLAG_CARRY || REGNO (op) >= FIRST_PSEUDO_REGISTER); -} - -/* Return true if operand is a register of any flavor or a 0 of the - appropriate type. */ - -int -reg_or_0_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - switch (GET_CODE (op)) - { - case REG: - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return register_operand (op, mode); - - case CONST_INT: - return INTVAL (op) == 0; - - case CONST_DOUBLE: - return CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == 0; - } - - return FALSE; -} - -/* Return true if operand is a GPR register or a signed 6 bit immediate. */ - -int -gpr_or_signed6_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -32, 31); - - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a GPR register or an unsigned 5 bit immediate. */ - -int -gpr_or_unsigned5_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), 0, 31); - - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a GPR register or an unsigned 6 bit immediate. */ - -int -gpr_or_unsigned6_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), 0, 63); - - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a GPR register or a constant of some form. */ - -int -gpr_or_constant_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - switch (GET_CODE (op)) - { - default: - break; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - case SUBREG: - op = SUBREG_REG (op); - if (GET_CODE (op) != REG) - break; - - /* fall through */ - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); - } - - return FALSE; -} - -/* Return true if operand is a GPR register or a constant of some form, - including a CONST_DOUBLE, which gpr_or_constant_operand doesn't recognize. */ - -int -gpr_or_dbl_const_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - switch (GET_CODE (op)) - { - default: - break; - - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - case SUBREG: - op = SUBREG_REG (op); - if (GET_CODE (op) != REG) - break; - - /* fall through */ - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); - } - - return FALSE; -} - -/* Return true if operand is a gpr register or a valid memory operation. */ - -int -gpr_or_memory_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - switch (GET_CODE (op)) - { - default: - break; - - case SUBREG: - op = SUBREG_REG (op); - if (GET_CODE (op) != REG) - break; - - /* fall through */ - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); - - case MEM: - return d30v_legitimate_address_p (mode_int, XEXP (op, 0), reload_completed); - } - - return FALSE; -} - -/* Return true if operand is something that can be an input for a move - operation. */ - -int -move_input_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - switch (GET_CODE (op)) - { - default: - break; - - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - op = SUBREG_REG (op); - if (GET_CODE (op) != REG) - break; - - return TRUE; - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return TRUE; - - case MEM: - if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) - return TRUE; - return d30v_legitimate_address_p (mode_int, XEXP (op, 0), - reload_completed); - } - - return FALSE; -} - -/* Return true if operand is something that can be an output for a move - operation. */ - -int -move_output_operand (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - switch (GET_CODE (op)) - { - default: - break; - - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - op = SUBREG_REG (op); - if (GET_CODE (op) != REG) - break; - - return TRUE; - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return TRUE; - - case MEM: - if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) - return TRUE; - return d30v_legitimate_address_p (mode_int, XEXP (op, 0), - reload_completed); - } - - return FALSE; -} - -/* Return true if operand is a signed 6 bit immediate. */ - -int -signed6_operand (op, mode_int) - rtx op; - int mode_int; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -32, 31); - - return FALSE; -} - -/* Return true if operand is an unsigned 5 bit immediate. */ - -int -unsigned5_operand (op, mode_int) - rtx op; - int mode_int; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), 0, 31); - - return FALSE; -} - -/* Return true if operand is an unsigned 6 bit immediate. */ - -int -unsigned6_operand (op, mode_int) - rtx op; - int mode_int; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), 0, 63); - - return FALSE; -} - -/* Return true if operand is a constant with a single bit set. */ - -int -bitset_operand (op, mode_int) - rtx op; - int mode_int; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (exact_log2 (INTVAL (op)), 0, 31); - - return FALSE; -} - -/* Return true if the operator is a ==/!= test against f0 or f1 that can be - used in conditional execution. */ - -int -condexec_test_operator (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != EQ && GET_CODE (op) != NE) - return FALSE; - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG || !BR_FLAG_OR_PSEUDO_P (REGNO (x0))) - return FALSE; - - x1 = XEXP (op, 1); - if (GET_CODE (x1) != CONST_INT || INTVAL (x1) != 0) - return FALSE; - - return TRUE; -} - -/* Return true if the operator is a ==/!= test against f0, f1, or a general - register that can be used in a branch instruction. */ - -int -condexec_branch_operator (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx x0, x1; - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != EQ && GET_CODE (op) != NE) - return FALSE; - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG) - return FALSE; - - regno = REGNO (x0); - if (!GPR_OR_PSEUDO_P (regno) && !BR_FLAG_P (regno)) - return FALSE; - - x1 = XEXP (op, 1); - if (GET_CODE (x1) != CONST_INT || INTVAL (x1) != 0) - return FALSE; - - return TRUE; -} - -/* Return true if the unary operator can be executed with conditional - execution. */ - -int -condexec_unary_operator (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx op0; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '1') - return FALSE; - - op0 = XEXP (op, 0); - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - switch (GET_CODE (op)) - { - default: - break; - - case ABS: - case NEG: - case NOT: - if (GET_MODE (op) == SImode && GET_CODE (op0) == REG && GPR_P (REGNO (op0))) - return TRUE; - - break; - } - - return FALSE; -} - -/* Return true if the add or subtraction can be executed with conditional - execution. */ - -int -condexec_addsub_operator (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx op0, op1; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '2' && GET_RTX_CLASS (GET_CODE (op)) != 'c') - return FALSE; - - op0 = XEXP (op, 0); - op1 = XEXP (op, 1); - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - - if (GET_CODE (op0) != REG) - return FALSE; - - switch (GET_CODE (op)) - { - default: - break; - - case PLUS: - case MINUS: - return (GET_MODE (op) == SImode && GPR_P (REGNO (op0)) - && gpr_or_constant_operand (op1, SImode)); - } - - return FALSE; -} - -/* Return true if the binary operator can be executed with conditional - execution. We don't include add/sub here, since they have extra - clobbers for the flags registers. */ - -int -condexec_binary_operator (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx op0, op1; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '2' && GET_RTX_CLASS (GET_CODE (op)) != 'c') - return FALSE; - - op0 = XEXP (op, 0); - op1 = XEXP (op, 1); - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - - if (GET_CODE (op0) != REG) - return FALSE; - - /* MULT is not included here, because it is an IU only instruction. */ - switch (GET_CODE (op)) - { - case AND: - case IOR: - case XOR: - case ASHIFTRT: - case LSHIFTRT: - case ROTATERT: - return (GET_MODE (op) == SImode && GPR_P (REGNO (op0)) - && gpr_or_constant_operand (op1, SImode)); - - case ASHIFT: - case ROTATE: - return (GET_MODE (op) == SImode && GPR_P (REGNO (op0)) - && GET_CODE (op1) == CONST_INT); - } - - return FALSE; -} - -/* Return true if the shift/rotate left operator can be executed with - conditional execution. */ - -int -condexec_shiftl_operator (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx op0, op1; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '2' && GET_RTX_CLASS (GET_CODE (op)) != 'c') - return FALSE; - - op0 = XEXP (op, 0); - op1 = XEXP (op, 1); - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - - if (GET_CODE (op0) != REG) - return FALSE; - - switch (GET_CODE (op)) - { - case ASHIFT: - case ROTATE: - return (GET_MODE (op) == SImode && GPR_P (REGNO (op0)) - && GET_CODE (op1) == NEG - && GET_CODE (XEXP (op1, 0)) == REG - && GPR_P (REGNO (XEXP (op1, 0)))); - } - - return FALSE; -} - -/* Return true if the {sign,zero} extend operator from memory can be - conditionally executed. */ - -int -condexec_extend_operator (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '1') - return FALSE; - - switch (GET_CODE (op)) - { - default: - break; - - case SIGN_EXTEND: - case ZERO_EXTEND: - if ((GET_MODE (op) == SImode && GET_MODE (XEXP (op, 0)) == QImode) - || (GET_MODE (op) == SImode && GET_MODE (XEXP (op, 0)) == HImode) - || (GET_MODE (op) == HImode && GET_MODE (XEXP (op, 0)) == QImode)) - return TRUE; - - break; - } - - return FALSE; -} - -/* Return true for comparisons against 0 that can be turned into a - bratnz/bratzr instruction. */ - -int -branch_zero_operator (op, mode_int) - rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != EQ && GET_CODE (op) != NE) - return FALSE; - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG || !GPR_OR_PSEUDO_P (REGNO (x0))) - return FALSE; - - x1 = XEXP (op, 1); - if (GET_CODE (x1) != CONST_INT || INTVAL (x1) != 0) - return FALSE; - - return TRUE; -} - -/* Return true if an operand is simple, suitable for use in a conditional move */ - -int -cond_move_operand (op, mode_int) - register rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx addr; - - if (mode != QImode && mode != HImode && mode != SImode && mode != SFmode) - return FALSE; - - switch (GET_CODE (op)) - { - case REG: - case SUBREG: - return gpr_operand (op, mode); - - case CONST_DOUBLE: - return GET_MODE (op) == SFmode; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - /* Don't allow post dec/inc, since we might not get the side effects correct. */ - case MEM: - addr = XEXP (op, 0); - return GET_CODE (addr) != POST_DEC && GET_CODE (addr) != POST_INC; - } - - return FALSE; -} - -/* Return true if an operand is simple, suitable for use in conditional execution. - Unlike cond_move, we can allow auto inc/dec. */ - -int -cond_exec_operand (op, mode_int) - register rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx addr; - - if (mode != QImode && mode != HImode && mode != SImode && mode != SFmode) - return FALSE; - - switch (GET_CODE (op)) - { - case REG: - case SUBREG: - return gpr_operand (op, mode); - - case CONST_DOUBLE: - return GET_MODE (op) == SFmode; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - case MEM: - return memory_operand (op, mode); - } - - return FALSE; -} - -/* Return true if operand is a SI mode signed relational test. */ - -int -srelational_si_operator (op, mode_int) - register rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case EQ: - case NE: - case LT: - case LE: - case GT: - case GE: - break; - } - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG && GET_CODE (x0) != SUBREG) - return FALSE; - - if (GET_MODE (x0) != SImode) - return FALSE; - - x1 = XEXP (op, 1); - switch (GET_CODE (x1)) - { - default: - return FALSE; - - case REG: - case SUBREG: - case CONST_INT: - case LABEL_REF: - case SYMBOL_REF: - case CONST: - break; - } - - return TRUE; -} - -/* Return true if operand is a SI mode unsigned relational test. */ - -int -urelational_si_operator (op, mode_int) - register rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case LTU: - case LEU: - case GTU: - case GEU: - break; - } - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG && GET_CODE (x0) != SUBREG) - return FALSE; - - if (GET_MODE (x0) != SImode) - return FALSE; - - x1 = XEXP (op, 1); - switch (GET_CODE (x1)) - { - default: - return FALSE; - - case REG: - case SUBREG: - case CONST_INT: - case LABEL_REF: - case SYMBOL_REF: - case CONST: - break; - } - - return TRUE; -} - -/* Return true if operand is a DI mode relational test. */ - -int -relational_di_operator (op, mode_int) - register rtx op; - int mode_int; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '<') - return FALSE; - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG && GET_CODE (x0) != SUBREG) - return FALSE; - - if (GET_MODE (x0) != DImode) - return FALSE; - - x1 = XEXP (op, 1); - if (GET_CODE (x1) != REG && GET_CODE (x1) != SUBREG - && GET_CODE (x1) != CONST_INT && GET_CODE (x1) != CONST_DOUBLE) - return FALSE; - - return TRUE; -} - - -/* Calculate the stack information for the current function. - - D30V stack frames look like: - - high | .... | - +-------------------------------+ - | Argument word #19 | - +-------------------------------+ - | Argument word #18 | - +-------------------------------+ - | Argument word #17 | - +-------------------------------+ - | Argument word #16 | - Prev sp +-------------------------------+ - | | - | Save for arguments 1..16 if | - | the func. uses stdarg/varargs | - | | - +-------------------------------+ - | | - | Save area for GPR registers | - | | - +-------------------------------+ - | | - | Save area for accumulators | - | | - +-------------------------------+ - | | - | Local variables | - | | - +-------------------------------+ - | | - | alloca space if used | - | | - +-------------------------------+ - | | - | Space for outgoing arguments | - | | - low SP----> +-------------------------------+ -*/ - -d30v_stack_t * -d30v_stack_info () -{ - static d30v_stack_t info, zero_info; - d30v_stack_t *info_ptr = &info; - tree fndecl = current_function_decl; - tree fntype = TREE_TYPE (fndecl); - int varargs_p = 0; - tree cur_arg; - tree next_arg; - int saved_gprs; - int saved_accs; - int memrefs_2words; - int memrefs_1word; - unsigned char save_gpr_p[GPR_LAST]; - int i; - - /* If we've already calculated the values and reload is complete, just return now */ - if (d30v_stack_cache) - return d30v_stack_cache; - - /* Zero all fields */ - info = zero_info; - - if (profile_flag) - regs_ever_live[GPR_LINK] = 1; - - /* Determine if this is a stdarg function */ - if (TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node)) - varargs_p = 1; - else - { - /* Find the last argument, and see if it is __builtin_va_alist. */ - for (cur_arg = DECL_ARGUMENTS (fndecl); cur_arg != (tree)0; cur_arg = next_arg) - { - next_arg = TREE_CHAIN (cur_arg); - if (next_arg == (tree)0) - { - if (DECL_NAME (cur_arg) - && !strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)), "__builtin_va_alist")) - varargs_p = 1; - - break; - } - } - } - - /* Calculate which registers need to be saved & save area size */ - saved_accs = 0; - memrefs_2words = 0; - memrefs_1word = 0; - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) - { - if (regs_ever_live[i] && !call_used_regs[i]) - { - info_ptr->save_p[i] = 2; - saved_accs++; - memrefs_2words++; - } - } - - saved_gprs = 0; - for (i = GPR_FIRST; i <= GPR_LAST; i++) - { - if (regs_ever_live[i] && (!call_used_regs[i] || i == GPR_LINK)) - { - save_gpr_p[i] = 1; - saved_gprs++; - } - else - save_gpr_p[i] = 0; - } - - /* Determine which register pairs can be saved together with ld2w/st2w */ - for (i = GPR_FIRST; i <= GPR_LAST; i++) - { - if (((i - GPR_FIRST) & 1) == 0 && save_gpr_p[i] && save_gpr_p[i+1]) - { - memrefs_2words++; - info_ptr->save_p[i++] = 2; - } - else if (save_gpr_p[i]) - { - memrefs_1word++; - info_ptr->save_p[i] = 1; - } - } - - /* Determine various sizes */ - info_ptr->varargs_p = varargs_p; - info_ptr->varargs_size = ((varargs_p) - ? (GPR_ARG_LAST + 1 - GPR_ARG_FIRST) * UNITS_PER_WORD - : 0); - - info_ptr->accum_size = 2 * UNITS_PER_WORD * saved_accs; - info_ptr->gpr_size = D30V_ALIGN (UNITS_PER_WORD * saved_gprs, - 2 * UNITS_PER_WORD); - info_ptr->vars_size = D30V_ALIGN (get_frame_size (), 2 * UNITS_PER_WORD); - info_ptr->parm_size = D30V_ALIGN (current_function_outgoing_args_size, - 2 * UNITS_PER_WORD); - - info_ptr->total_size = D30V_ALIGN ((info_ptr->gpr_size - + info_ptr->accum_size - + info_ptr->vars_size - + info_ptr->parm_size - + info_ptr->varargs_size), - (STACK_BOUNDARY / BITS_PER_UNIT)); - - info_ptr->save_offset = (info_ptr->total_size - - (info_ptr->varargs_size - + info_ptr->gpr_size - + info_ptr->accum_size)); - - /* The link register is the last GPR saved, but there might be some padding - bytes after it, so account for that. */ - info_ptr->link_offset = (info_ptr->total_size - - (info_ptr->varargs_size - + (info_ptr->gpr_size - - UNITS_PER_WORD * saved_gprs) - + UNITS_PER_WORD)); - - info_ptr->memrefs_varargs = info_ptr->varargs_size / (2 * UNITS_PER_WORD); - info_ptr->memrefs_2words = memrefs_2words; - info_ptr->memrefs_1word = memrefs_1word; - - if (reload_completed) - d30v_stack_cache = info_ptr; - - return info_ptr; -} - - -/* Internal function to print all of the information about the stack */ - -void -debug_stack_info (info) - d30v_stack_t *info; -{ - int i; - - if (!info) - info = d30v_stack_info (); - - fprintf (stderr, "\nStack information for function %s:\n", - ((current_function_decl && DECL_NAME (current_function_decl)) - ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl)) - : "")); - - fprintf (stderr, "\tsave_offset = %d\n", info->save_offset); - fprintf (stderr, "\tmemrefs_varargs = %d\n", info->memrefs_varargs); - fprintf (stderr, "\tmemrefs_2words = %d\n", info->memrefs_2words); - fprintf (stderr, "\tmemrefs_1word = %d\n", info->memrefs_1word); - fprintf (stderr, "\tvarargs_p = %d\n", info->varargs_p); - fprintf (stderr, "\tvarargs_size = %d\n", info->varargs_size); - fprintf (stderr, "\tvars_size = %d\n", info->vars_size); - fprintf (stderr, "\tparm_size = %d\n", info->parm_size); - fprintf (stderr, "\tgpr_size = %d\n", info->gpr_size); - fprintf (stderr, "\taccum_size = %d\n", info->accum_size); - fprintf (stderr, "\ttotal_size = %d\n", info->total_size); - fprintf (stderr, "\tsaved registers ="); - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - { - if (info->save_p[i] == 2) - { - fprintf (stderr, " %s-%s", reg_names[i], reg_names[i+1]); - i++; - } - else if (info->save_p[i]) - fprintf (stderr, " %s", reg_names[i]); - } - - putc ('\n', stderr); - fflush (stderr); -} - - -/* Return non-zero if this function is known to have a null or 1 instruction epilogue. */ - -int -direct_return () -{ - if (reload_completed) - { - d30v_stack_t *info = d30v_stack_info (); - - /* If no epilogue code is needed, can use just a simple jump */ - if (info->total_size == 0) - return 1; - -#if 0 - /* If just a small amount of local stack was allocated and no registers - saved, skip forward branch */ - if (info->total_size == info->vars_size - && IN_RANGE_P (info->total_size, 1, 31)) - return 1; -#endif - } - - return 0; -} - - -/* A C statement (sans semicolon) for initializing the variable CUM for the - state at the beginning of the argument list. The variable has type - `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node for the data type - of the function which will receive the args, or 0 if the args are to a - compiler support library function. The value of INDIRECT is nonzero when - processing an indirect call, for example a call through a function pointer. - The value of INDIRECT is zero for a call to an explicitly named function, a - library function call, or when `INIT_CUMULATIVE_ARGS' is used to find - arguments for the function being compiled. - - When processing a call to a compiler support library function, LIBNAME - identifies which one. It is a `symbol_ref' rtx which contains the name of - the function, as a string. LIBNAME is 0 when an ordinary C function call is - being processed. Thus, each time this macro is called, either LIBNAME or - FNTYPE is nonzero, but never both of them at once. */ - -void -d30v_init_cumulative_args (cum, fntype, libname, indirect, incoming) - CUMULATIVE_ARGS *cum; - tree fntype; - rtx libname; - int indirect; - int incoming; -{ - *cum = GPR_ARG_FIRST; - - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "\ninit_cumulative_args:"); - if (indirect) - fputs (" indirect", stderr); - - if (incoming) - fputs (" incoming", stderr); - - if (fntype) - { - tree ret_type = TREE_TYPE (fntype); - fprintf (stderr, " return=%s,", - tree_code_name[ (int)TREE_CODE (ret_type) ]); - } - - if (libname && GET_CODE (libname) == SYMBOL_REF) - fprintf (stderr, " libname=%s", XSTR (libname, 0)); - - putc ('\n', stderr); - } -} - - -/* If defined, a C expression that gives the alignment boundary, in bits, of an - argument with the specified mode and type. If it is not defined, - `PARM_BOUNDARY' is used for all arguments. */ - -int -d30v_function_arg_boundary (mode_int, type) - int mode_int; - tree type; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - int size = ((mode == BLKmode && type) - ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)); - - return (size > UNITS_PER_WORD) ? 2*UNITS_PER_WORD : UNITS_PER_WORD; -} - - -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The arguments are CUM, which summarizes all the previous arguments; MODE, - the machine mode of the argument; TYPE, the data type of the argument as a - tree node or 0 if that is not known (which happens for C support library - functions); and NAMED, which is 1 for an ordinary argument and 0 for - nameless arguments that correspond to `...' in the called function's - prototype. - - The value of the expression should either be a `reg' RTX for the hard - register in which to pass the argument, or zero to pass the argument on the - stack. - - For machines like the Vax and 68000, where normally all arguments are - pushed, zero suffices as a definition. - - The usual way to make the ANSI library `stdarg.h' work on a machine where - some arguments are usually passed in registers, is to cause nameless - arguments to be passed on the stack instead. This is done by making - `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of - this macro to determine if this argument is of a type that must be passed in - the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' - returns non-zero for such an argument, the compiler will abort. If - `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the - stack and then loaded into a register. */ - -Rtx -d30v_function_arg (cum, mode_int, type, named, incoming) - CUMULATIVE_ARGS *cum; - int mode_int; - tree type; - int named; - int incoming; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - int size = ((mode == BLKmode && type) - ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)); - int adjust = (size > UNITS_PER_WORD && (*cum & 1) != 0); - rtx ret; - - /* Return a marker for use in the call instruction. */ - if (mode == VOIDmode) - ret = const0_rtx; - - else if (*cum + adjust <= GPR_ARG_LAST) - ret = gen_rtx (REG, mode, *cum + adjust); - - else - ret = NULL_RTX; - - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "function_arg: words = %2d, mode = %4s, named = %d, size = %3d, adjust = %1d, arg = %s\n", - *cum, GET_MODE_NAME (mode), named, size, adjust, - (ret) ? ((ret == const0_rtx) ? "<0>" : reg_names[ REGNO (ret) ]) : "memory"); - - return ret; -} - - -/* A C expression for the number of words, at the beginning of an argument, - must be put in registers. The value must be zero for arguments that are - passed entirely in registers or that are entirely pushed on the stack. - - On some machines, certain arguments must be passed partially in registers - and partially in memory. On these machines, typically the first N words of - arguments are passed in registers, and the rest on the stack. If a - multi-word argument (a `double' or a structure) crosses that boundary, its - first few words must be passed in registers and the rest must be pushed. - This macro tells the compiler when this occurs, and how many of the words - should go in registers. - - `FUNCTION_ARG' for these arguments should return the first register to be - used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for - the called function. */ - -int -d30v_function_arg_partial_nregs (cum, mode_int, type, named) - CUMULATIVE_ARGS *cum; - int mode_int; - tree type; - int named; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - int bytes = ((mode == BLKmode) - ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)); - int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - int adjust = (bytes > UNITS_PER_WORD && (*cum & 1) != 0); - int arg_num = *cum + adjust; - int ret; - - ret = ((arg_num <= GPR_ARG_LAST && arg_num + words > GPR_ARG_LAST+1) - ? GPR_ARG_LAST - arg_num + 1 - : 0); - - if (TARGET_DEBUG_ARG && ret) - fprintf (stderr, "function_arg_partial_nregs: %d\n", ret); - - return ret; -} - - -/* A C expression that indicates when an argument must be passed by reference. - If nonzero for an argument, a copy of that argument is made in memory and a - pointer to the argument is passed instead of the argument itself. The - pointer is passed in whatever way is appropriate for passing a pointer to - that type. - - On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable - definition of this macro might be - #define FUNCTION_ARG_PASS_BY_REFERENCE\ - (CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) */ - -int -d30v_function_arg_pass_by_reference (cum, mode_int, type, named) - CUMULATIVE_ARGS *cum; - int mode_int; - tree type; - int named; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - int ret = MUST_PASS_IN_STACK (mode, type); - - if (TARGET_DEBUG_ARG && ret) - fprintf (stderr, "function_arg_pass_by_reference: %d\n", ret); - - return ret; -} - - -/* A C statement (sans semicolon) to update the summarizer variable CUM to - advance past an argument in the argument list. The values MODE, TYPE and - NAMED describe that argument. Once this is done, the variable CUM is - suitable for analyzing the *following* argument with `FUNCTION_ARG', etc. - - This macro need not do anything if the argument in question was passed on - the stack. The compiler knows how to track the amount of stack space used - for arguments without any special help. */ - -void -d30v_function_arg_advance (cum, mode_int, type, named) - CUMULATIVE_ARGS *cum; - int mode_int; - tree type; - int named; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - int bytes = ((mode == BLKmode) - ? int_size_in_bytes (type) - : GET_MODE_SIZE (mode)); - int words = D30V_ALIGN (bytes, UNITS_PER_WORD) / UNITS_PER_WORD; - int adjust = (bytes > UNITS_PER_WORD && (*cum & 1) != 0); - - *cum += words + adjust; - - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "function_adv: words = %2d, mode = %4s, named = %d, size = %3d, adjust = %1d\n", - *cum, GET_MODE_NAME (mode), named, words * UNITS_PER_WORD, adjust); -} - - -/* If defined, is a C expression that produces the machine-specific code for a - call to `__builtin_saveregs'. This code will be moved to the very beginning - of the function, before any parameter access are made. The return value of - this function should be an RTX that contains the value to use as the return - of `__builtin_saveregs'. - - The argument ARGS is a `tree_list' containing the arguments that were passed - to `__builtin_saveregs'. - - If this macro is not defined, the compiler will output an ordinary call to - the library function `__builtin_saveregs'. */ - -Rtx -d30v_expand_builtin_saveregs (args) - tree args; -{ - int offset = UNITS_PER_WORD * (GPR_ARG_LAST + 1 - GPR_ARG_FIRST); - - if (TARGET_DEBUG_ARG) - fprintf (stderr, "expand_builtin_saveregs: offset from ap = %d\n", - offset); - - return gen_rtx (PLUS, Pmode, virtual_incoming_args_rtx, GEN_INT (- offset)); -} - - -/* This macro offers an alternative to using `__builtin_saveregs' and defining - the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register - arguments into the stack so that all the arguments appear to have been - passed consecutively on the stack. Once this is done, you can use the - standard implementation of varargs that works for machines that pass all - their arguments on the stack. - - The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, containing - the values that obtain after processing of the named arguments. The - arguments MODE and TYPE describe the last named argument--its machine mode - and its data type as a tree node. - - The macro implementation should do two things: first, push onto the stack - all the argument registers *not* used for the named arguments, and second, - store the size of the data thus pushed into the `int'-valued variable whose - name is supplied as the argument PRETEND_ARGS_SIZE. The value that you - store here will serve as additional offset for setting up the stack frame. - - Because you must generate code to push the anonymous arguments at compile - time without knowing their data types, `SETUP_INCOMING_VARARGS' is only - useful on machines that have just a single category of argument register and - use it uniformly for all data types. - - If the argument SECOND_TIME is nonzero, it means that the arguments of the - function are being analyzed for the second time. This happens for an inline - function, which is not actually compiled until the end of the source file. - The macro `SETUP_INCOMING_VARARGS' should not generate any instructions in - this case. */ - -void -d30v_setup_incoming_varargs (cum, mode_int, type, pretend_size, second_time) - CUMULATIVE_ARGS *cum; - int mode_int; - tree type; - int *pretend_size; - int second_time; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "setup_vararg: words = %2d, mode = %4s, second_time = %d\n", - *cum, GET_MODE_NAME (mode), second_time); -} - - - -/* A C compound statement that outputs the assembler code for entry to a - function. The prologue is responsible for setting up the stack frame, - initializing the frame pointer register, saving registers that must be - saved, and allocating SIZE additional bytes of storage for the local - variables. SIZE is an integer. FILE is a stdio stream to which the - assembler code should be output. - - The label for the beginning of the function need not be output by this - macro. That has already been done when the macro is run. - - To determine which registers to save, the macro can refer to the array - `regs_ever_live': element R is nonzero if hard register R is used anywhere - within the function. This implies the function prologue should save - register R, provided it is not one of the call-used registers. - (`FUNCTION_EPILOGUE' must likewise use `regs_ever_live'.) - - On machines that have "register windows", the function entry code does not - save on the stack the registers that are in the windows, even if they are - supposed to be preserved by function calls; instead it takes appropriate - steps to "push" the register stack, if any non-call-used registers are used - in the function. - - On machines where functions may or may not have frame-pointers, the function - entry code must vary accordingly; it must set up the frame pointer if one is - wanted, and not otherwise. To determine whether a frame pointer is in - wanted, the macro can refer to the variable `frame_pointer_needed'. The - variable's value will be 1 at run time in a function that needs a frame - pointer. *Note Elimination::. - - The function entry code is responsible for allocating any stack space - required for the function. This stack space consists of the regions listed - below. In most cases, these regions are allocated in the order listed, with - the last listed region closest to the top of the stack (the lowest address - if `STACK_GROWS_DOWNWARD' is defined, and the highest address if it is not - defined). You can use a different order for a machine if doing so is more - convenient or required for compatibility reasons. Except in cases where - required by standard or by a debugger, there is no reason why the stack - layout used by GCC need agree with that used by other compilers for a - machine. - - * A region of `current_function_pretend_args_size' bytes of - uninitialized space just underneath the first argument - arriving on the stack. (This may not be at the very start of - the allocated stack region if the calling sequence has pushed - anything else since pushing the stack arguments. But - usually, on such machines, nothing else has been pushed yet, - because the function prologue itself does all the pushing.) - This region is used on machines where an argument may be - passed partly in registers and partly in memory, and, in some - cases to support the features in `varargs.h' and `stdargs.h'. - - * An area of memory used to save certain registers used by the - function. The size of this area, which may also include - space for such things as the return address and pointers to - previous stack frames, is machine-specific and usually - depends on which registers have been used in the function. - Machines with register windows often do not require a save - area. - - * A region of at least SIZE bytes, possibly rounded up to an - allocation boundary, to contain the local variables of the - function. On some machines, this region and the save area - may occur in the opposite order, with the save area closer to - the top of the stack. - - * Optionally, when `ACCUMULATE_OUTGOING_ARGS' is defined, a - region of `current_function_outgoing_args_size' bytes to be - used for outgoing argument lists of the function. *Note - Stack Arguments::. - - Normally, it is necessary for the macros `FUNCTION_PROLOGUE' and - `FUNCTION_EPILOGUE' to treat leaf functions specially. The C variable - `leaf_function' is nonzero for such a function. */ - -/* For the d30v, move all of the prologue processing into separate insns. */ -void -d30v_function_prologue (stream, size) - FILE *stream; - int size; -{ -} - - -/* Called after register allocation to add any instructions needed for the - prologue. Using a prologue insn is favored compared to putting all of the - instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler - to intermix instructions with the saves of the caller saved registers. In - some cases, it might be necessary to emit a barrier instruction as the last - insn to prevent such scheduling. */ - -void -d30v_expand_prologue () -{ - rtx sp = stack_pointer_rtx; - d30v_stack_t *info = d30v_stack_info (); - int i; - rtx mem_di = NULL_RTX; - rtx mem_si = NULL_RTX; - int num_memrefs = (info->memrefs_2words - + info->memrefs_1word - + info->memrefs_varargs); - - if (TARGET_DEBUG_STACK) - debug_stack_info (info); - - /* Grow the stack. */ - if (info->total_size) - emit_insn (gen_addsi3 (sp, sp, GEN_INT (- info->total_size))); - - /* If there is more than one save, use post-increment addressing which will - result in smaller code, than would the normal references. If there is - only one save, just do the store as normal. */ - - if (num_memrefs > 1) - { - rtx save_tmp = gen_rtx (REG, Pmode, GPR_STACK_TMP); - rtx post_inc = gen_rtx (POST_INC, Pmode, save_tmp); - mem_di = gen_rtx (MEM, DImode, post_inc); - mem_si = gen_rtx (MEM, SImode, post_inc); - emit_insn (gen_addsi3 (save_tmp, sp, GEN_INT (info->save_offset))); - } - else if (num_memrefs == 1) - { - rtx addr = plus_constant (sp, info->save_offset); - mem_di = gen_rtx (MEM, DImode, addr); - mem_si = gen_rtx (MEM, SImode, addr); - } - - /* Save the accumulators. */ - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) - if (info->save_p[i]) - { - rtx acc_tmp = gen_rtx (REG, DImode, GPR_ATMP_FIRST); - emit_insn (gen_movdi (acc_tmp, gen_rtx (REG, DImode, i))); - emit_insn (gen_movdi (mem_di, acc_tmp)); - } - - /* Save the GPR registers that are adjacent to each other with st2w. */ - for (i = GPR_FIRST; i <= GPR_LAST; i += 2) - if (info->save_p[i] == 2) - emit_insn (gen_movdi (mem_di, gen_rtx (REG, DImode, i))); - - /* Save the GPR registers that need to be saved with a single word store. */ - for (i = GPR_FIRST; i <= GPR_LAST; i++) - if (info->save_p[i] == 1) - emit_insn (gen_movsi (mem_si, gen_rtx (REG, SImode, i))); - - /* Save the argument registers if this function accepts variable args. */ - if (info->varargs_p) - { - /* Realign r22 if an odd # of GPRs were saved. */ - if ((info->memrefs_1word & 1) != 0) - { - rtx save_tmp = XEXP (XEXP (mem_si, 0), 0); - emit_insn (gen_addsi3 (save_tmp, save_tmp, GEN_INT (UNITS_PER_WORD))); - } - - for (i = GPR_ARG_FIRST; i <= GPR_ARG_LAST; i += 2) - emit_insn (gen_movdi (mem_di, gen_rtx (REG, DImode, i))); - } - - /* Update the frame pointer. */ - if (frame_pointer_needed) - emit_move_insn (frame_pointer_rtx, sp); - - /* Hack for now, to prevent scheduler from being too cleaver */ - emit_insn (gen_blockage ()); -} - - -/* A C compound statement that outputs the assembler code for exit from a - function. The epilogue is responsible for restoring the saved registers and - stack pointer to their values when the function was called, and returning - control to the caller. This macro takes the same arguments as the macro - `FUNCTION_PROLOGUE', and the registers to restore are determined from - `regs_ever_live' and `CALL_USED_REGISTERS' in the same way. - - On some machines, there is a single instruction that does all the work of - returning from the function. On these machines, give that instruction the - name `return' and do not define the macro `FUNCTION_EPILOGUE' at all. - - Do not define a pattern named `return' if you want the `FUNCTION_EPILOGUE' - to be used. If you want the target switches to control whether return - instructions or epilogues are used, define a `return' pattern with a - validity condition that tests the target switches appropriately. If the - `return' pattern's validity condition is false, epilogues will be used. - - On machines where functions may or may not have frame-pointers, the function - exit code must vary accordingly. Sometimes the code for these two cases is - completely different. To determine whether a frame pointer is wanted, the - macro can refer to the variable `frame_pointer_needed'. The variable's - value will be 1 when compiling a function that needs a frame pointer. - - Normally, `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' must treat leaf - functions specially. The C variable `leaf_function' is nonzero for such a - function. *Note Leaf Functions::. - - On some machines, some functions pop their arguments on exit while others - leave that for the caller to do. For example, the 68020 when given `-mrtd' - pops arguments in functions that take a fixed number of arguments. - - Your definition of the macro `RETURN_POPS_ARGS' decides which functions pop - their own arguments. `FUNCTION_EPILOGUE' needs to know what was decided. - The variable that is called `current_function_pops_args' is the number of - bytes of its arguments that a function should pop. *Note Scalar Return::. */ - -/* For the d30v, move all processing to be as insns, but do any cleanup - here, since it is done after handling all of the insns. */ -void -d30v_function_epilogue (stream, size) - FILE *stream; - int size; -{ - d30v_stack_cache = (d30v_stack_t *)0; /* reset stack cache */ -} - - - -/* Called after register allocation to add any instructions needed for the - epilogue. Using a epilogue insn is favored compared to putting all of the - instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler - to intermix instructions with the saves of the caller saved registers. In - some cases, it might be necessary to emit a barrier instruction as the last - insn to prevent such scheduling. */ - -void -d30v_expand_epilogue () -{ - rtx sp = stack_pointer_rtx; - d30v_stack_t *info = d30v_stack_info (); - int i; - rtx mem_di = NULL_RTX; - rtx mem_si = NULL_RTX; - int num_memrefs = info->memrefs_2words + info->memrefs_1word; - rtx post_inc; - int extra_stack; - - /* Hack for now, to prevent scheduler from being too cleaver */ - emit_insn (gen_blockage ()); - - /* Restore sp from fp. */ - if (frame_pointer_needed) - emit_move_insn (sp, frame_pointer_rtx); - - /* For the epilogue, use post-increment addressing all of the time. First - adjust the sp, to eliminate all of the stack, except for the save area. */ - - if (info->save_offset) - emit_insn (gen_addsi3 (sp, sp, GEN_INT (info->save_offset))); - - post_inc = gen_rtx (POST_INC, Pmode, sp); - mem_di = gen_rtx (MEM, DImode, post_inc); - mem_si = gen_rtx (MEM, SImode, post_inc); - - /* Restore the accumulators. */ - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) - if (info->save_p[i]) - { - rtx acc_tmp = gen_rtx (REG, DImode, GPR_ATMP_FIRST); - emit_insn (gen_movdi (acc_tmp, mem_di)); - emit_insn (gen_movdi (gen_rtx (REG, DImode, i), acc_tmp)); - } - - /* Restore the GPR registers that are adjacent to each other with ld2w. */ - for (i = GPR_FIRST; i <= GPR_LAST; i += 2) - if (info->save_p[i] == 2) - emit_insn (gen_movdi (gen_rtx (REG, DImode, i), mem_di)); - - /* Save the GPR registers that need to be saved with a single word store. */ - for (i = GPR_FIRST; i <= GPR_LAST; i++) - if (info->save_p[i] == 1 - && ! (d30v_eh_epilogue_sp_ofs && i == GPR_LINK)) - emit_insn (gen_movsi (gen_rtx (REG, SImode, i), mem_si)); - - /* Release any remaining stack that was allocated for saving the - varargs registers or because an odd # of registers were stored. */ - extra_stack = info->varargs_size; - if ((info->memrefs_1word & 1) != 0) - extra_stack += UNITS_PER_WORD; - - if (extra_stack) - emit_insn (gen_addsi3 (sp, sp, GEN_INT (extra_stack))); - - /* ??? Should try to combine this with the above add? */ - if (d30v_eh_epilogue_sp_ofs) - emit_insn (gen_addsi3 (sp, sp, d30v_eh_epilogue_sp_ofs)); - - /* Hack for now, to prevent scheduler from being too cleaver */ - emit_insn (gen_blockage ()); - - /* Now emit the return instruction. */ - emit_jump_insn (gen_indirect_jump (gen_rtx (REG, Pmode, GPR_LINK))); -} - - -/* A C statement or compound statement to output to FILE some assembler code to - call the profiling subroutine `mcount'. Before calling, the assembler code - must load the address of a counter variable into a register where `mcount' - expects to find the address. The name of this variable is `LP' followed by - the number LABELNO, so you would generate the name using `LP%d' in a - `fprintf'. - - The details of how the address should be passed to `mcount' are determined - by your operating system environment, not by GNU CC. To figure them out, - compile a small program for profiling using the system's installed C - compiler and look at the assembler code that results. */ - -void -d30v_function_profiler (stream, labelno) - FILE *stream; - int labelno; -{ - fprintf (stream, "# profile\n"); -} - - -/* Split a 64 bit item into an upper and a lower part. We specifically do not - want to call gen_highpart/gen_lowpart on CONST_DOUBLEs since it will give us - the wrong part for floating point in cross compilers, and split_double does - not handle registers. Also abort if the register is not a general purpose - register. */ - -void -d30v_split_double (value, p_high, p_low) - rtx value; - rtx *p_high; - rtx *p_low; -{ - int offset = 0; - int regno; - - if (!reload_completed) - abort (); - - switch (GET_CODE (value)) - { - case SUBREG: - offset = SUBREG_WORD (value); - value = SUBREG_REG (value); - if (GET_CODE (value) != REG) - abort (); - - /* fall through */ - - case REG: - regno = REGNO (value) + offset; - if (!GPR_P (regno)) - abort (); - - *p_high = gen_rtx (REG, SImode, regno); - *p_low = gen_rtx (REG, SImode, regno+1); - break; - - case CONST_INT: - case CONST_DOUBLE: - split_double (value, p_high, p_low); - break; - - default: - abort (); - } -} - - -/* A C compound statement to output to stdio stream STREAM the assembler syntax - for an instruction operand that is a memory reference whose address is X. X - is an RTL expression. - - On some machines, the syntax for a symbolic address depends on the section - that the address refers to. On these machines, define the macro - `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and - then check for it here. *Note Assembler Format::. */ - -void -d30v_print_operand_address (stream, x) - FILE *stream; - rtx x; -{ - if (GET_CODE (x) == MEM) - x = XEXP (x, 0); - - switch (GET_CODE (x)) - { - default: - break; - - case REG: - fputs (reg_names[ REGNO (x) ], stream); - return; - - case CONST_INT: - fprintf (stream, "%ld", (long) INTVAL (x)); - return; - - /* We wrap simple symbol refs inside a parenthesis, so that a name - like `r2' is not taken for a register name. */ - case SYMBOL_REF: - fputs ("(", stream); - assemble_name (stream, XSTR (x, 0)); - fputs (")", stream); - return; - - case LABEL_REF: - case CONST: - output_addr_const (stream, x); - return; - } - - fatal_insn ("Bad insn to d30v_print_operand_address:", x); -} - - -/* Print a memory reference suitable for the ld/st instructions. */ - -static void -d30v_print_operand_memory_reference (stream, x) - FILE *stream; - rtx x; -{ - rtx x0 = NULL_RTX; - rtx x1 = NULL_RTX; - - switch (GET_CODE (x)) - { - default: - fatal_insn ("Bad insn to d30v_print_operand_memory_reference:", x); - break; - - case SUBREG: - case REG: - case POST_DEC: - case POST_INC: - x0 = x; - break; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - x1 = x; - break; - - case PLUS: - x0 = XEXP (x, 0); - x1 = XEXP (x, 1); - if (GET_CODE (x0) == CONST_INT || GET_CODE (x0) == SYMBOL_REF - || GET_CODE (x0) == CONST || GET_CODE (x0) == LABEL_REF) - { - x0 = XEXP (x, 1); - x1 = XEXP (x, 0); - } - break; - } - - fputs ("@(", stream); - if (!x0) - fputs (reg_names[GPR_R0], stream); - - else - { - char *suffix = ""; - int offset0 = 0; - - if (GET_CODE (x0) == SUBREG) - { - offset0 = SUBREG_WORD (x0); - x0 = SUBREG_REG (x0); - } - - if (GET_CODE (x0) == POST_INC) - { - x0 = XEXP (x0, 0); - suffix = "+"; - } - else if (GET_CODE (x0) == POST_DEC) - { - x0 = XEXP (x0, 0); - suffix = "-"; - } - - if (GET_CODE (x0) == REG && GPR_P (REGNO (x0))) - fprintf (stream, "%s%s", reg_names[REGNO (x0) + offset0], suffix); - else - fatal_insn ("Bad insn to d30v_print_operand_memory_reference:", x); - } - - fputs (",", stream); - - if (!x1) - fputs (reg_names[GPR_R0], stream); - - else - { - int offset1 = 0; - - switch (GET_CODE (x1)) - { - case SUBREG: - offset1 = SUBREG_WORD (x1); - x1 = SUBREG_REG (x1); - if (GET_CODE (x1) != REG) - fatal_insn ("Bad insn to d30v_print_operand_memory_reference:", x); - - /* fall through */ - case REG: - fputs (reg_names[REGNO (x1) + offset1], stream); - break; - - case CONST_INT: - fprintf (stream, "%ld", (long) INTVAL (x1)); - break; - - case SYMBOL_REF: - case LABEL_REF: - case CONST: - d30v_print_operand_address (stream, x1); - break; - - default: - fatal_insn ("Bad insn to d30v_print_operand_memory_reference:", x); - } - } - - fputs (")", stream); -} - - -/* A C compound statement to output to stdio stream STREAM the assembler syntax - for an instruction operand X. X is an RTL expression. - - LETTER is a value that can be used to specify one of several ways of - printing the operand. It is used when identical operands must be printed - differently depending on the context. LETTER comes from the `%' - specification that was used to request printing of the operand. If the - specification was just `%DIGIT' then LETTER is 0; if the specification was - `%LTR DIGIT' then LETTER is the ASCII code for LTR. - - If X is a register, this macro should print the register's name. The names - can be found in an array `reg_names' whose type is `char *[]'. `reg_names' - is initialized from `REGISTER_NAMES'. - - When the machine description has a specification `%PUNCT' (a `%' followed by - a punctuation character), this macro is called with a null pointer for X and - the punctuation character for LETTER. - - Standard operand flags that are handled elsewhere: - `=' Output a number unique to each instruction in the compilation. - `a' Substitute an operand as if it were a memory reference. - `c' Omit the syntax that indicates an immediate operand. - `l' Substitute a LABEL_REF into a jump instruction. - `n' Like %cDIGIT, except negate the value before printing. - - The d30v specific operand flags are: - `.' Print r0. - `f' Print a SF constant as an int. - `s' Subtract 32 and negate. - `A' Print accumulator number without an `a' in front of it. - `B' Print bit offset for BSET, etc. instructions. - `E' Print u if this is zero extend, nothing if this is sign extend. - `F' Emit /{f,t,x}{f,t,x} for executing a false condition. - `L' Print the lower half of a 64 bit item. - `M' Print a memory reference for ld/st instructions. - `R' Return appropriate cmp instruction for relational test. - `S' Subtract 32. - `T' Emit /{f,t,x}{f,t,x} for executing a true condition. - `U' Print the upper half of a 64 bit item. */ - -void -d30v_print_operand (stream, x, letter) - FILE *stream; - rtx x; - int letter; -{ - enum rtx_code code = (x) ? GET_CODE (x) : NIL; - rtx split_values[2]; - REAL_VALUE_TYPE rv; - long num; - int log; - - switch (letter) - { - case '.': /* Output r0 */ - fputs (reg_names[GPR_R0], stream); - break; - - case 'f': /* Print a SF floating constant as an int */ - if (GET_CODE (x) != CONST_DOUBLE) - fatal_insn ("Bad insn to d30v_print_operand, 'f' modifier:", x); - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, num); - fprintf (stream, "%ld", num); - break; - - case 'A': /* Print accumulator number without an `a' in front of it. */ - if (GET_CODE (x) != REG || !ACCUM_P (REGNO (x))) - fatal_insn ("Bad insn to d30v_print_operand, 'A' modifier:", x); - - putc ('0' + REGNO (x) - ACCUM_FIRST, stream); - break; - - case 'M': /* Print a memory reference for ld/st */ - if (GET_CODE (x) != MEM) - fatal_insn ("Bad insn to d30v_print_operand, 'M' modifier:", x); - - d30v_print_operand_memory_reference (stream, XEXP (x, 0)); - break; - - case 'L': /* print lower part of 64 bit item. */ - case 'U': /* print upper part of 64 bit item. */ - d30v_split_double (x, &split_values[0], &split_values[1]); - d30v_print_operand (stream, split_values[ letter == 'L' ], '\0'); - break; - - case 'F': /* Print an appropriate suffix for a false comparision. */ - case 'T': /* Print an appropriate suffix for a true comparision. */ - /* Note that the sense of appropriate suffix is for conditional execution - and opposite of what branches want. Branches just use the inverse - operation. */ - if ((GET_CODE (x) == NE || GET_CODE (x) == EQ) - && GET_MODE (x) == CCmode - && GET_CODE (XEXP (x, 0)) == REG - && (GPR_P (REGNO (XEXP (x, 0))) || BR_FLAG_P (REGNO (XEXP (x, 0)))) - && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 0) - { - int true_false = (letter == 'T'); - - if (GET_CODE (x) == EQ) - true_false = !true_false; - - if (REGNO (XEXP (x, 0)) == FLAG_F0) - fprintf (stream, "/%cx", (true_false) ? 'f' : 't'); - - else if (REGNO (XEXP (x, 0)) == FLAG_F1) - fprintf (stream, "/x%c", (true_false) ? 'f' : 't'); - - else - fputs ((true_false) ? "tnz" : "tzr", stream); - } - - else if (GET_CODE (x) == REG && REGNO (x) == FLAG_F0) - fprintf (stream, "/%cx", (letter == 'T') ? 't' : 'f'); - - else if (GET_CODE (x) == REG && REGNO (x) == FLAG_F1) - fprintf (stream, "/x%c", (letter == 'T') ? 't' : 'f'); - - else if (GET_CODE (x) == REG && GPR_P (REGNO (x))) - fputs ((letter == 'T') ? "tnz" : "tzr", stream); - - else - fatal_insn ("Bad insn to print_operand, 'F' or 'T' modifier:", x); - break; - - case 'B': /* emit offset single bit to change */ - if (GET_CODE (x) == CONST_INT && (log = exact_log2 (INTVAL (x))) >= 0) - fprintf (stream, "%d", 31 - log); - - else if (GET_CODE (x) == CONST_INT && (log = exact_log2 (~ INTVAL (x))) >= 0) - fprintf (stream, "%d", 31 - log); - - else - fatal_insn ("Bad insn to print_operand, 'B' modifier:", x); - break; - - case 'E': /* Print u if this is zero extend, nothing if sign extend. */ - if (GET_CODE (x) == ZERO_EXTEND) - putc ('u', stream); - else if (GET_CODE (x) != SIGN_EXTEND) - fatal_insn ("Bad insn to print_operand, 'E' modifier:", x); - break; - - case 'R': /* Return appropriate cmp instruction for relational test. */ - switch (GET_CODE (x)) - { - case EQ: fputs ("cmpeq", stream); break; - case NE: fputs ("cmpne", stream); break; - case LT: fputs ("cmplt", stream); break; - case LE: fputs ("cmple", stream); break; - case GT: fputs ("cmpgt", stream); break; - case GE: fputs ("cmpge", stream); break; - case LTU: fputs ("cmpult", stream); break; - case LEU: fputs ("cmpule", stream); break; - case GTU: fputs ("cmpugt", stream); break; - case GEU: fputs ("cmpuge", stream); break; - - default: - fatal_insn ("Bad insn to print_operand, 'R' modifier:", x); - } - break; - - case 's': /* Subtract 32 and negate (for 64 bit shifts). */ - if (GET_CODE (x) == CONST_INT) - fprintf (stream, "%d", (int) (32 - INTVAL (x))); - - else - fatal_insn ("Bad insn to print_operand, 's' modifier:", x); - break; - - case 'S': /* Subtract 32. */ - if (GET_CODE (x) == CONST_INT) - fprintf (stream, "%d", (int)(INTVAL (x) - 32)); - - else - fatal_insn ("Bad insn to print_operand, 's' modifier:", x); - break; - - - case '\0': - if (code == REG) - fputs (reg_names[ REGNO (x) ], stream); - - else if (code == CONST_INT) - fprintf (stream, "%d", (int)INTVAL (x)); - - else if (code == MEM) - d30v_print_operand_address (stream, XEXP (x, 0)); - - else if (CONSTANT_ADDRESS_P (x)) - d30v_print_operand_address (stream, x); - - else - fatal_insn ("Bad insn in d30v_print_operand, 0 case", x); - - return; - - default: - { - char buf[80]; - - sprintf (buf, "Invalid asm template character '%%%c'", letter); - fatal_insn (buf, x); - } - } -} - - -/* A C expression for the size in bytes of the trampoline, as an integer. */ - -int -d30v_trampoline_size () -{ - return 16; -} - - -/* Create a long instruction for building up a trampoline. */ - -static void -d30v_build_long_insn (high_bits, low_bits, imm, mem) - HOST_WIDE_INT high_bits; - HOST_WIDE_INT low_bits; - rtx imm; - rtx mem; -{ - rtx reg = gen_reg_rtx (DImode); - rtx high_word = gen_highpart (SImode, reg); - rtx low_word = gen_lowpart (SImode, reg); - rtx tmp1 = gen_reg_rtx (SImode); - rtx tmp2 = gen_reg_rtx (SImode); - rtx tmp3 = gen_reg_rtx (SImode); - rtx tmp4 = gen_reg_rtx (SImode); - rtx tmp5 = gen_reg_rtx (SImode); - rtx tmp6 = gen_reg_rtx (SImode); - - imm = force_reg (SImode, imm); - - /* Stuff top 6 bits of immediate value into high word */ - emit_insn (gen_lshrsi3 (tmp1, imm, GEN_INT (26))); - emit_insn (gen_andsi3 (tmp2, tmp1, GEN_INT (0x3F))); - emit_insn (gen_iorsi3 (high_word, tmp2, GEN_INT (high_bits))); - - /* Now get the next 8 bits for building the low word */ - emit_insn (gen_andsi3 (tmp3, imm, GEN_INT (0x03FC0000))); - emit_insn (gen_ashlsi3 (tmp4, tmp3, GEN_INT (2))); - - /* And the bottom 18 bits */ - emit_insn (gen_andsi3 (tmp5, imm, GEN_INT (0x0003FFFF))); - emit_insn (gen_iorsi3 (tmp6, tmp4, tmp5)); - emit_insn (gen_iorsi3 (low_word, tmp6, GEN_INT (low_bits))); - - /* Store the instruction */ - emit_insn (gen_movdi (mem, reg)); -} - - -/* A C statement to initialize the variable parts of a trampoline. ADDR is an - RTX for the address of the trampoline; FNADDR is an RTX for the address of - the nested function; STATIC_CHAIN is an RTX for the static chain value that - should be passed to the function when it is called. */ - -void -d30v_initialize_trampoline (addr, fnaddr, static_chain) - rtx addr; - rtx fnaddr; - rtx static_chain; -{ - /* The instruction space can only be accessed by ld2w/st2w. - Generate on the fly: - or r18,r0, - jmp */ - d30v_build_long_insn (0x83A80000 | ((STATIC_CHAIN_REGNUM - GPR_FIRST) << 12), - 0x80000000, static_chain, - gen_rtx (MEM, DImode, addr)); - - d30v_build_long_insn (0x80180000, 0x80000000, fnaddr, - gen_rtx (MEM, DImode, plus_constant (addr, 8))); -} - - -/* A C compound statement with a conditional `goto LABEL;' executed if X (an - RTX) is a legitimate memory address on the target machine for a memory - operand of mode MODE. - - It usually pays to define several simpler macros to serve as subroutines for - this one. Otherwise it may be too complicated to understand. - - This macro must exist in two variants: a strict variant and a non-strict - one. The strict variant is used in the reload pass. It must be defined so - that any pseudo-register that has not been allocated a hard register is - considered a memory reference. In contexts where some kind of register is - required, a pseudo-register with no hard register must be rejected. - - The non-strict variant is used in other passes. It must be defined to - accept all pseudo-registers in every context where some kind of register is - required. - - Compiler source files that want to use the strict variant of this macro - define the macro `REG_OK_STRICT'. You should use an `#ifdef REG_OK_STRICT' - conditional to define the strict variant in that case and the non-strict - variant otherwise. - - Subroutines to check for acceptable registers for various purposes (one for - base registers, one for index registers, and so on) are typically among the - subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'. Then only these - subroutine macros need have two variants; the higher levels of macros may be - the same whether strict or not. - - Normally, constant addresses which are the sum of a `symbol_ref' and an - integer are stored inside a `const' RTX to mark them as constant. - Therefore, there is no need to recognize such sums specifically as - legitimate addresses. Normally you would simply recognize any `const' as - legitimate. - - Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that - are not marked with `const'. It assumes that a naked `plus' indicates - indexing. If so, then you *must* reject such naked constant sums as - illegitimate addresses, so that none of them will be given to - `PRINT_OPERAND_ADDRESS'. - - On some machines, whether a symbolic address is legitimate depends on the - section that the address refers to. On these machines, define the macro - `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and - then check for it here. When you see a `const', you will have to look - inside it to find the `symbol_ref' in order to determine the section. *Note - Assembler Format::. - - The best way to modify the name string is by adding text to the beginning, - with suitable punctuation to prevent any ambiguity. Allocate the new name - in `saveable_obstack'. You will have to modify `ASM_OUTPUT_LABELREF' to - remove and decode the added text and output the name accordingly, and define - `STRIP_NAME_ENCODING' to access the original name string. - - You can check the information stored here into the `symbol_ref' in the - definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and - `PRINT_OPERAND_ADDRESS'. - - Return 0 if the address is not legitimate, 1 if the address would fit - in a short instruction, or 2 if the address would fit in a long - instruction. */ - -#define XREGNO_OK_FOR_BASE_P(REGNO, STRICT_P) \ -((STRICT_P) \ - ? REGNO_OK_FOR_BASE_P (REGNO) \ - : GPR_OR_PSEUDO_P (REGNO)) - -int -d30v_legitimate_address_p (mode_int, x, strict_p) - int mode_int; - rtx x; - int strict_p; -{ - enum machine_mode mode = (enum machine_mode) mode_int; - rtx x0, x1; - int ret = 0; - - switch (GET_CODE (x)) - { - default: - break; - - case SUBREG: - x = SUBREG_REG (x); - if (GET_CODE (x) != REG) - break; - - /* fall through */ - - case REG: - ret = XREGNO_OK_FOR_BASE_P (REGNO (x), strict_p); - break; - - case PLUS: - x0 = XEXP (x, 0); - x1 = XEXP (x, 1); - - if (GET_CODE (x0) == SUBREG) - x0 = SUBREG_REG (x0); - - if (GET_CODE (x0) == POST_INC || GET_CODE (x0) == POST_DEC) - x0 = XEXP (x0, 0); - - if (GET_CODE (x0) != REG || !XREGNO_OK_FOR_BASE_P (REGNO (x0), strict_p)) - break; - - switch (GET_CODE (x1)) - { - default: - break; - - case SUBREG: - x1 = SUBREG_REG (x1); - if (GET_CODE (x1) != REG) - break; - - /* fall through */ - - case REG: - ret = XREGNO_OK_FOR_BASE_P (REGNO (x1), strict_p); - break; - - case CONST_INT: - ret = (IN_RANGE_P (INTVAL (x1), -32, 31)) ? 1 : 2; - break; - - case SYMBOL_REF: - case LABEL_REF: - case CONST: - ret = 2; - break; - } - break; - - case CONST_INT: - ret = (IN_RANGE_P (INTVAL (x), -32, 31)) ? 1 : 2; - break; - - case SYMBOL_REF: - case LABEL_REF: - case CONST: - ret = 2; - break; - - case POST_INC: - case POST_DEC: - x0 = XEXP (x, 0); - if (GET_CODE (x0) == REG && XREGNO_OK_FOR_BASE_P (REGNO (x0), strict_p)) - ret = 1; - break; - } - - if (TARGET_DEBUG_ADDR) - { - fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, mode = %s, result = %d, addresses are %sstrict\n", - GET_MODE_NAME (mode), ret, (strict_p) ? "" : "not "); - debug_rtx (x); - } - - return ret; -} - - -/* A C compound statement that attempts to replace X with a valid memory - address for an operand of mode MODE. WIN will be a C statement label - elsewhere in the code; the macro definition may use - - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); - - to avoid further processing if the address has become legitimate. - - X will always be the result of a call to `break_out_memory_refs', and OLDX - will be the operand that was given to that function to produce X. - - The code generated by this macro should not alter the substructure of X. If - it transforms X into a more legitimate form, it should assign X (which will - always be a C variable) a new value. - - It is not necessary for this macro to come up with a legitimate address. - The compiler has standard ways of doing so in all cases. In fact, it is - safe for this macro to do nothing. But often a machine-dependent strategy - can generate better code. */ - -Rtx -d30v_legitimize_address (x, oldx, mode_int, strict_p) - rtx x; - rtx oldx; - int mode_int; - int strict_p; -{ - enum machine_mode mode = (enum machine_mode)mode_int; - rtx ret = NULL_RTX; - - if (TARGET_DEBUG_ADDR) - { - if (ret) - { - fprintf (stderr, "\n========== LEGITIMIZE_ADDRESS, transformed:\n"); - debug_rtx (x); - fprintf (stderr, "\ninto:\n"); - debug_rtx (ret); - } - else - { - fprintf (stderr, "\n========== LEGITIMIZE_ADDRESS, did nothing with:\n"); - debug_rtx (x); - } - } - - return ret; -} - - -/* A C statement or compound statement with a conditional `goto LABEL;' - executed if memory address X (an RTX) can have different meanings depending - on the machine mode of the memory reference it is used for or if the address - is valid for some modes but not others. - - Autoincrement and autodecrement addresses typically have mode-dependent - effects because the amount of the increment or decrement is the size of the - operand being addressed. Some machines have other mode-dependent addresses. - Many RISC machines have no mode-dependent addresses. - - You may assume that ADDR is a valid address for the machine. */ - -int -d30v_mode_dependent_address_p (addr) - rtx addr; -{ - switch (GET_CODE (addr)) - { - default: - break; - - case POST_INC: - case POST_DEC: - return TRUE; - } - - return FALSE; -} - - -/* Generate the appropriate comparison code for a test. */ - -rtx -d30v_emit_comparison (test_int, result, arg1, arg2) - int test_int; - rtx result; - rtx arg1; - rtx arg2; -{ - enum rtx_code test = (enum rtx_code) test_int; - enum machine_mode mode = GET_MODE (arg1); - rtx rtx_test = gen_rtx (SET, VOIDmode, result, gen_rtx (test, CCmode, arg1, arg2)); - - if (mode == SImode - || (mode == DImode && (test == EQ || test == NE)) - || (mode == DImode && (test == LT || test == GE) - && GET_CODE (arg2) == CONST_INT && INTVAL (arg2) == 0)) - return rtx_test; - - else if (mode == DImode) - return gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, - rtx_test, - gen_rtx (CLOBBER, VOIDmode, - gen_reg_rtx (CCmode)))); - - else - fatal_insn ("d30v_emit_comparison", rtx_test); -} - - -/* Return appropriate code to move 2 words. Since DImode registers must start - on even register numbers, there is no possibility of overlap. */ - -char * -d30v_move_2words (operands, insn) - rtx operands[]; - rtx insn; -{ - if (GET_CODE (operands[0]) == REG && GPR_P (REGNO (operands[0]))) - { - if (GET_CODE (operands[1]) == REG && GPR_P (REGNO (operands[1]))) - return "or %U0,%.,%U1\n\tor %L0,%.,%L1"; - - else if (GET_CODE (operands[1]) == REG && ACCUM_P (REGNO (operands[1]))) - return "mvfacc %L0,%1,%.\n\tmvfacc %U0,%1,32"; - - else if (GET_CODE (operands[1]) == MEM) - return "ld2w %0,%M1"; - - else if (GET_CODE (operands[1]) == CONST_INT - || GET_CODE (operands[1]) == CONST_DOUBLE) - return "or %U0,%.,%U1\n\tor %L0,%.,%L1"; - } - - else if (GET_CODE (operands[0]) == REG && ACCUM_P (REGNO (operands[0]))) - { - if (GET_CODE (operands[1]) == REG - && GPR_P (REGNO (operands[1]))) - return "mvtacc %0,%U1,%L1"; - - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) == 0) - return "mvtacc %0,%.,%."; - } - - else if (GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == REG - && GPR_P (REGNO (operands[1]))) - return "st2w %1,%M0"; - - fatal_insn ("Bad call to d30v_move_2words", insn); -} - - -/* Emit the code to do a conditional move instruction. Return FALSE - if the conditional move could not be executed. */ - -int -d30v_emit_cond_move (dest, test, true_value, false_value) - rtx dest; - rtx test; - rtx true_value; - rtx false_value; -{ - rtx br_reg; - enum machine_mode mode = GET_MODE (dest); - - if (GET_CODE (dest) == MEM) - { - if (!reg_or_0_operand (true_value, mode)) - return FALSE; - - if (!reg_or_0_operand (false_value, mode)) - return FALSE; - } - - br_reg = gen_reg_rtx (CCmode); - - /* Recognize simple sequences better done with mvfsys. */ - if ((true_value == const1_rtx && false_value == const0_rtx) - || (true_value == const0_rtx && false_value == const1_rtx - && GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)) - { - enum rtx_code code = GET_CODE (test); - - if (true_value == const0_rtx) - code = reverse_condition (code); - - emit_insn (d30v_emit_comparison (code, br_reg, - d30v_compare_op0, d30v_compare_op1)); - - if (mode != SImode) - dest = gen_rtx (SUBREG, SImode, dest, 0); - - emit_insn (gen_rtx (SET, SImode, dest, - gen_rtx (EQ, SImode, br_reg, const1_rtx))); - return TRUE; - } - - emit_insn (d30v_emit_comparison (GET_CODE (test), br_reg, - d30v_compare_op0, d30v_compare_op1)); - - emit_insn (gen_rtx (SET, VOIDmode, - dest, - gen_rtx (IF_THEN_ELSE, mode, - gen_rtx (NE, CCmode, br_reg, const0_rtx), - true_value, - false_value))); - return TRUE; -} - - -/* Output a conditional move instruction - operands[0] is the destination - operands[1] is the NE test - operands[2] is f0 or f1 - operands[3] is the value to move if the test was true - operands[4] is the value to move if the test was false */ - -char * -d30v_cond_move (operands, insn, load, store) - rtx operands[]; - rtx insn; - char *load; - char *store; -{ - rtx dest = operands[0]; - enum machine_mode mode = GET_MODE (dest); - char buffer[80]; - - if (GET_CODE (dest) == REG) - { - /* Move value into register for false condition */ - switch (GET_CODE (operands[4])) - { - case REG: - if (REGNO (operands[4]) != REGNO (operands[0])) - output_asm_insn ("or%T1 %0,%.,%4", operands); - break; - - case MEM: - sprintf (buffer, "%s%%T1 %%0,%%M4", load); - output_asm_insn (buffer, operands); - break; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - output_asm_insn ("or%T1 %0,%.,%4", operands); - break; - - case CONST_DOUBLE: - output_asm_insn ("or%T1 %0,%.,%f4", operands); - break; - - default: - fatal_insn ("d30v_cond_move", insn); - } - - /* Move value into register for true condition */ - switch (GET_CODE (operands[3])) - { - case REG: - if (REGNO (operands[3]) != REGNO (operands[0])) - output_asm_insn ("or%F1 %0,%.,%3", operands); - break; - - case MEM: - sprintf (buffer, "%s%%F1 %%0,%%M3", load); - output_asm_insn (buffer, operands); - break; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - output_asm_insn ("or%F1 %0,%.,%3", operands); - break; - - case CONST_DOUBLE: - output_asm_insn ("or%F1 %0,%.,%f3", operands); - break; - - default: - fatal_insn ("d30v_cond_move", insn); - } - } - - else if (GET_CODE (dest) == MEM) - { - sprintf (buffer, "%s%%T1 %s,%M0", store, - (GET_CODE (operands[4]) == CONST_INT ? "%." : "%4")); - output_asm_insn (buffer, operands); - - sprintf (buffer, "%s%%F1 %s,%M0", store, - (GET_CODE (operands[3]) == CONST_INT ? "%." : "%3")); - output_asm_insn (buffer, operands); - } - - else - fatal_insn ("d30v_cond_move", insn); - - return ""; -} - - -/* In rare cases, correct code generation requires extra machine dependent - processing between the second jump optimization pass and delayed branch - scheduling. On those machines, define this macro as a C statement to act on - the code starting at INSN. */ - -void -d30v_machine_dependent_reorg (insn) - rtx insn; -{ -} - - -/* A C statement (sans semicolon) to update the integer variable COST based on - the relationship between INSN that is dependent on DEP_INSN through the - dependence LINK. The default is to make no adjustment to COST. This can be - used for example to specify to the scheduler that an output- or - anti-dependence does not incur the same cost as a data-dependence. */ - -/* For the d30v, try to insure that the source operands for a load/store are - set 2 cycles before the memory reference. */ - -int -d30v_adjust_cost (insn, link, dep_insn, cost) - rtx insn; - rtx link; - rtx dep_insn; - int cost; -{ - rtx set_dep = single_set (dep_insn); - rtx set_insn = single_set (insn); - - if (set_dep != NULL_RTX && set_insn != NULL_RTX - && GET_CODE (SET_DEST (set_dep)) == REG) - { - rtx reg = SET_DEST (set_dep); - rtx mem; - - if ((GET_CODE (mem = SET_SRC (set_insn)) == MEM - && reg_mentioned_p (reg, XEXP (mem, 0))) - || (GET_CODE (mem = SET_DEST (set_insn)) == MEM - && reg_mentioned_p (reg, XEXP (mem, 0)))) - { - return cost + ((HAIFA_P) ? 2 : 4); - } - } - - return cost; -} - - -/* Functions to save and restore d30v_return_addr_rtx. */ - -struct machine_function -{ - rtx ra_rtx; -}; - -static void -d30v_save_machine_status (p) - struct function *p; -{ - struct machine_function *machine = - (struct machine_function *) xmalloc (sizeof (struct machine_function)); - - p->machine = machine; - machine->ra_rtx = d30v_return_addr_rtx; -} - -static void -d30v_restore_machine_status (p) - struct function *p; -{ - struct machine_function *machine = p->machine; - - d30v_return_addr_rtx = machine->ra_rtx; - - free (machine); - p->machine = (struct machine_function *)0; -} - -/* Do anything needed before RTL is emitted for each function. */ - -void -d30v_init_expanders () -{ - d30v_return_addr_rtx = NULL_RTX; - d30v_eh_epilogue_sp_ofs = NULL_RTX; - - /* Arrange to save and restore machine status around nested functions. */ - save_machine_status = d30v_save_machine_status; - restore_machine_status = d30v_restore_machine_status; -} - -/* Find the current function's return address. - - ??? It would be better to arrange things such that if we would ordinarily - have been a leaf function and we didn't spill the hard reg that we - wouldn't have to save the register in the prolog. But it's not clear - how to get the right information at the right time. */ - -rtx -d30v_return_addr () -{ - rtx ret; - - if ((ret = d30v_return_addr_rtx) == NULL) - { - rtx init; - - d30v_return_addr_rtx = ret = gen_reg_rtx (Pmode); - - init = gen_rtx (SET, VOIDmode, ret, gen_rtx (REG, Pmode, GPR_LINK)); - push_topmost_sequence (); - emit_insn_after (init, get_insns ()); - pop_topmost_sequence (); - } - - return ret; -} - -/* END CYGNUS LOCAL -- meissner/d30v */ diff --git a/gcc/config/d30v/d30v.h b/gcc/config/d30v/d30v.h deleted file mode 100755 index af55b04..0000000 --- a/gcc/config/d30v/d30v.h +++ /dev/null @@ -1,6245 +0,0 @@ -/* CYGNUS LOCAL -- meissner/d30v */ -/* Definitions of target machine for use as an example. - Hack to fit. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. - Contributed by Cygnus Solutions. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* D30V specific macros */ - -/* Align an address */ -#define D30V_ALIGN(addr,align) (((addr) + (align) - 1) & ~((align) - 1)) - - -/* Set up System V.4 (aka ELF) defaults. */ -#include "svr4.h" - -/* Set up System V.3 (aka COFF) defaults. */ -/* #include "svr3.h" */ - -/* Set up a.out defaults. */ -/* #include "aoutos.h" */ - -/* Set up GNU defaults for the Hurd. */ -/* #include "gnu.h" */ - -/* Set up Linux defaults. */ -/* #include "linux.h" */ - -/* Set up Netbsd defaults. */ -/* #include "netbsd.h" */ - - - -/* Driver configuration */ - -/* A C expression which determines whether the option `-CHAR' takes arguments. - The value should be the number of arguments that option takes-zero, for many - options. - - By default, this macro is defined to handle the standard options properly. - You need not define it unless you wish to add additional options which take - arguments. - - Defined in svr4.h. */ -/* #define SWITCH_TAKES_ARG(CHAR) */ - -/* A C expression which determines whether the option `-NAME' takes arguments. - The value should be the number of arguments that option takes-zero, for many - options. This macro rather than `SWITCH_TAKES_ARG' is used for - multi-character option names. - - By default, this macro is defined as `DEFAULT_WORD_SWITCH_TAKES_ARG', which - handles the standard options properly. You need not define - `WORD_SWITCH_TAKES_ARG' unless you wish to add additional options which take - arguments. Any redefinition should call `DEFAULT_WORD_SWITCH_TAKES_ARG' and - then check for additional options. - - Defined in svr4.h. */ -/* #define WORD_SWITCH_TAKES_ARG(NAME) */ - -/* A string-valued C expression which is nonempty if the linker needs a space - between the `-L' or `-o' option and its argument. - - If this macro is not defined, the default value is 0. */ -/* #define SWITCHES_NEED_SPACES "" */ - -/* A C string constant that tells the GNU CC driver program options to pass to - CPP. It can also specify how to translate options you give to GNU CC into - options for GNU CC to pass to the CPP. - - Do not define this macro if it does not need to do anything. */ -/* #define CPP_SPEC "" */ - -/* If this macro is defined, the preprocessor will not define the builtin macro - `__SIZE_TYPE__'. The macro `__SIZE_TYPE__' must then be defined by - `CPP_SPEC' instead. - - This should be defined if `SIZE_TYPE' depends on target dependent flags - which are not accessible to the preprocessor. Otherwise, it should not be - defined. */ -/* #define NO_BUILTIN_SIZE_TYPE */ - -/* If this macro is defined, the preprocessor will not define the builtin macro - `__PTRDIFF_TYPE__'. The macro `__PTRDIFF_TYPE__' must then be defined by - `CPP_SPEC' instead. - - This should be defined if `PTRDIFF_TYPE' depends on target dependent flags - which are not accessible to the preprocessor. Otherwise, it should not be - defined. */ -/* #define NO_BUILTIN_PTRDIFF_TYPE */ - -/* A C string constant that tells the GNU CC driver program options to pass to - CPP. By default, this macro is defined to pass the option - `-D__CHAR_UNSIGNED__' to CPP if `char' will be treated as `unsigned char' by - `cc1'. - - Do not define this macro unless you need to override the default definition. */ -/* #if DEFAULT_SIGNED_CHAR - #define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" - #else - #define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}" - #endif */ - -/* A C string constant that tells the GNU CC driver program options to pass to - `cc1'. It can also specify how to translate options you give to GNU CC into - options for GNU CC to pass to the `cc1'. - - Do not define this macro if it does not need to do anything. */ -/* #define CC1_SPEC "" */ - -/* A C string constant that tells the GNU CC driver program options to pass to - `cc1plus'. It can also specify how to translate options you give to GNU CC - into options for GNU CC to pass to the `cc1plus'. - - Do not define this macro if it does not need to do anything. */ -/* #define CC1PLUS_SPEC "" */ - -/* A C string constant that tells the GNU CC driver program options to pass to - the assembler. It can also specify how to translate options you give to GNU - CC into options for GNU CC to pass to the assembler. See the file `sun3.h' - for an example of this. - - Do not define this macro if it does not need to do anything. - - Defined in svr4.h. */ -#undef ASM_SPEC -#define ASM_SPEC "\ -%{!mno-asm-optimize: %{O*: %{!O0: -O} %{O0: %{masm-optimize: -O}}}} \ -%{v} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}" - -/* A C string constant that tells the GNU CC driver program how to run any - programs which cleanup after the normal assembler. Normally, this is not - needed. See the file `mips.h' for an example of this. - - Do not define this macro if it does not need to do anything. - - Defined in svr4.h. */ -/* #define ASM_FINAL_SPEC "" */ - -/* A C string constant that tells the GNU CC driver program options to pass to - the linker. It can also specify how to translate options you give to GNU CC - into options for GNU CC to pass to the linker. - - Do not define this macro if it does not need to do anything. - - Defined in svr4.h. */ -#undef LINK_SPEC -#define LINK_SPEC "\ -%{h*} %{v:-V} \ -%{b} %{Wl,*:%*} \ -%{static:-dn -Bstatic} \ -%{shared:-G -dy -z text} \ -%{symbolic:-Bsymbolic -G -dy -z text} \ -%{G:-G} \ -%{YP,*} \ -%{Qy:} %{!Qn:-Qy} \ -%{mextmem: -m d30v_e} %{mextmemory: -m d30v_e} %{monchip: -m d30v_o}" - -/* Another C string constant used much like `LINK_SPEC'. The difference - between the two is that `LIB_SPEC' is used at the end of the command given - to the linker. - - If this macro is not defined, a default is provided that loads the standard - C library from the usual place. See `gcc.c'. - - Defined in svr4.h. */ -#undef LIB_SPEC -#define LIB_SPEC "--start-group -lsim -lc --end-group" - -/* Another C string constant that tells the GNU CC driver program how and when - to place a reference to `libgcc.a' into the linker command line. This - constant is placed both before and after the value of `LIB_SPEC'. - - If this macro is not defined, the GNU CC driver provides a default that - passes the string `-lgcc' to the linker unless the `-shared' option is - specified. */ -/* #define LIBGCC_SPEC "" */ - -/* Another C string constant used much like `LINK_SPEC'. The difference - between the two is that `STARTFILE_SPEC' is used at the very beginning of - the command given to the linker. - - If this macro is not defined, a default is provided that loads the standard - C startup file from the usual place. See `gcc.c'. - - Defined in svr4.h. */ - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "crt0%O%s crtbegin%O%s" - -/* Another C string constant used much like `LINK_SPEC'. The difference - between the two is that `ENDFILE_SPEC' is used at the very end of the - command given to the linker. - - Do not define this macro if it does not need to do anything. - - Defined in svr4.h. */ - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend%O%s" - -/* Define this macro if the driver program should find the library `libgcc.a' - itself and should not pass `-L' options to the linker. If you do not define - this macro, the driver program will pass the argument `-lgcc' to tell the - linker to do the search and will pass `-L' options to it. */ -/* #define LINK_LIBGCC_SPECIAL */ - -/* Define this macro if the driver program should find the library `libgcc.a'. - If you do not define this macro, the driver program will pass the argument - `-lgcc' to tell the linker to do the search. This macro is similar to - `LINK_LIBGCC_SPECIAL', except that it does not affect `-L' options. */ -/* #define LINK_LIBGCC_SPECIAL_1 */ - -/* Define this macro to provide additional specifications to put in the `specs' - file that can be used in various specifications like `CC1_SPEC'. - - The definition should be an initializer for an array of structures, - containing a string constant, that defines the specification name, and a - string constant that provides the specification. - - Do not define this macro if it does not need to do anything. */ -/* #define EXTRA_SPECS {{}} */ - -/* Define this macro as a C expression for the initializer of an array of - string to tell the driver program which options are defaults for this target - and thus do not need to be handled specially when using `MULTILIB_OPTIONS'. - - Do not define this macro if `MULTILIB_OPTIONS' is not defined in the target - makefile fragment or if none of the options listed in `MULTILIB_OPTIONS' are - set by default. *Note Target Fragment::. */ -/* #define MULTILIB_DEFAULTS {} */ - -/* Define this macro to tell `gcc' that it should only translate a `-B' prefix - into a `-L' linker option if the prefix indicates an absolute file name. */ -/* #define RELATIVE_PREFIX_NOT_LINKDIR */ - -/* Define this macro as a C string constant if you wish to override the - standard choice of `/usr/local/lib/gcc-lib/' as the default prefix to try - when searching for the executable files of the compiler. */ -/* #define STANDARD_EXEC_PREFIX "" */ - -/* If defined, this macro is an additional prefix to try after - `STANDARD_EXEC_PREFIX'. `MD_EXEC_PREFIX' is not searched when the `-b' - option is used, or the compiler is built as a cross compiler. - - Defined in svr4.h for host compilers. */ -/* #define MD_EXEC_PREFIX "" */ - -/* Define this macro as a C string constant if you wish to override the - standard choice of `/usr/local/lib/' as the default prefix to try when - searching for startup files such as `crt0.o'. */ -/* #define STANDARD_STARTFILE_PREFIX "" */ - -/* If defined, this macro supplies an additional prefix to try after the - standard prefixes. `MD_EXEC_PREFIX' is not searched when the `-b' option is - used, or when the compiler is built as a cross compiler. - - Defined in svr4.h for host compilers. */ -/* #define MD_STARTFILE_PREFIX "" */ - -/* If defined, this macro supplies yet another prefix to try after the standard - prefixes. It is not searched when the `-b' option is used, or when the - compiler is built as a cross compiler. */ -/* #define MD_STARTFILE_PREFIX_1 "" */ - -/* Define this macro as a C string constant if you with to set environment - variables for programs called by the driver, such as the assembler and - loader. The driver passes the value of this macro to `putenv' to initialize - the necessary environment variables. */ -/* #define INIT_ENVIRONMENT "" */ - -/* Define this macro as a C string constant if you wish to override the - standard choice of `/usr/local/include' as the default prefix to try when - searching for local header files. `LOCAL_INCLUDE_DIR' comes before - `SYSTEM_INCLUDE_DIR' in the search order. - - Cross compilers do not use this macro and do not search either - `/usr/local/include' or its replacement. */ -/* #define LOCAL_INCLUDE_DIR "" */ - -/* Define this macro as a C string constant if you wish to specify a - system-specific directory to search for header files before the standard - directory. `SYSTEM_INCLUDE_DIR' comes before `STANDARD_INCLUDE_DIR' in the - search order. - - Cross compilers do not use this macro and do not search the directory - specified. */ -/* #define SYSTEM_INCLUDE_DIR "" */ - -/* Define this macro as a C string constant if you wish to override the - standard choice of `/usr/include' as the default prefix to try when - searching for header files. - - Cross compilers do not use this macro and do not search either - `/usr/include' or its replacement. */ -/* #define STANDARD_INCLUDE_DIR "" */ - -/* Define this macro if you wish to override the entire default search path for - include files. The default search path includes `GCC_INCLUDE_DIR', - `LOCAL_INCLUDE_DIR', `SYSTEM_INCLUDE_DIR', `GPLUSPLUS_INCLUDE_DIR', and - `STANDARD_INCLUDE_DIR'. In addition, `GPLUSPLUS_INCLUDE_DIR' and - `GCC_INCLUDE_DIR' are defined automatically by `Makefile', and specify - private search areas for GCC. The directory `GPLUSPLUS_INCLUDE_DIR' is used - only for C++ programs. - - The definition should be an initializer for an array of structures. Each - array element should have two elements: the directory name (a string - constant) and a flag for C++-only directories. Mark the end of the array - with a null element. For example, here is the definition used for VMS: - - #define INCLUDE_DEFAULTS \ - { \ - { "GNU_GXX_INCLUDE:", 1}, \ - { "GNU_CC_INCLUDE:", 0}, \ - { "SYS$SYSROOT:[SYSLIB.]", 0}, \ - { ".", 0}, \ - { 0, 0} \ - } - - Here is the order of prefixes tried for exec files: - - 1. Any prefixes specified by the user with `-B'. - - 2. The environment variable `GCC_EXEC_PREFIX', if any. - - 3. The directories specified by the environment variable - `COMPILER_PATH'. - - 4. The macro `STANDARD_EXEC_PREFIX'. - - 5. `/usr/lib/gcc/'. - - 6. The macro `MD_EXEC_PREFIX', if any. - - Here is the order of prefixes tried for startfiles: - - 1. Any prefixes specified by the user with `-B'. - - 2. The environment variable `GCC_EXEC_PREFIX', if any. - - 3. The directories specified by the environment variable - `LIBRARY_PATH' (native only, cross compilers do not use this). - - 4. The macro `STANDARD_EXEC_PREFIX'. - - 5. `/usr/lib/gcc/'. - - 6. The macro `MD_EXEC_PREFIX', if any. - - 7. The macro `MD_STARTFILE_PREFIX', if any. - - 8. The macro `STANDARD_STARTFILE_PREFIX'. - - 9. `/lib/'. - - 10. `/usr/lib/'. */ -/* #define INCLUDE_DEFAULTS {{ }} */ - - -/* Run-time target specifications */ - -/* Define this to be a string constant containing `-D' options to define the - predefined macros that identify this machine and system. These macros will - be predefined unless the `-ansi' option is specified. - - In addition, a parallel set of macros are predefined, whose names are made - by appending `__' at the beginning and at the end. These `__' macros are - permitted by the ANSI standard, so they are predefined regardless of whether - `-ansi' is specified. - - For example, on the Sun, one can use the following value: - - "-Dmc68000 -Dsun -Dunix" - - The result is to define the macros `__mc68000__', `__sun__' and `__unix__' - unconditionally, and the macros `mc68000', `sun' and `unix' provided `-ansi' - is not specified. */ -#define CPP_PREDEFINES "-D__D30V__ -Amachine(d30v)" - -/* 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. For example, - one machine description serves both the 68000 and the 68020; a command - argument tells the compiler whether it should use 68020-only instructions or - not. This command argument works by means of a macro `TARGET_68020' that - tests a bit in `target_flags'. - - Define a macro `TARGET_FEATURENAME' for each such option. Its definition - should test a bit in `target_flags'; for example: - - #define TARGET_68020 (target_flags & 1) - - One place where these macros are used is in the condition-expressions of - instruction patterns. Note how `TARGET_68020' appears frequently in the - 68000 machine description file, `m68k.md'. Another place they are used is - in the definitions of the other macros in the `MACHINE.h' file. */ - -#define MASK_NO_COND_MOVE 0x00000001 /* disable conditional moves */ - -#define MASK_DEBUG_ARG 0x10000000 /* debug argument handling */ -#define MASK_DEBUG_STACK 0x20000000 /* debug stack allocations */ -#define MASK_DEBUG_ADDR 0x40000000 /* debug GO_IF_LEGITIMATE_ADDRESS */ - -#define TARGET_NO_COND_MOVE (target_flags & MASK_NO_COND_MOVE) -#define TARGET_DEBUG_ARG (target_flags & MASK_DEBUG_ARG) -#define TARGET_DEBUG_STACK (target_flags & MASK_DEBUG_STACK) -#define TARGET_DEBUG_ADDR (target_flags & MASK_DEBUG_ADDR) - -#define TARGET_COND_MOVE (! TARGET_NO_COND_MOVE) - -/* Default switches used. */ -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT 0 -#endif - -/* 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. - - Each subgrouping contains a string constant, that defines the option name, - and a number, which contains the bits to set in `target_flags'. A negative - number says to clear bits instead; the negative of the number is which bits - to clear. The actual option name is made by appending `-m' to the specified - name. - - One of the subgroupings should have a null string. The number in this - grouping is the default value for `target_flags'. Any target options act - starting with that value. - - Here is an example which defines `-m68000' and `-m68020' with opposite - meanings, and picks the latter as the default: - - #define TARGET_SWITCHES \ - { { "68020", 1}, \ - { "68000", -1}, \ - { "", 1}} */ - -#define TARGET_SWITCHES \ -{ \ - { "cond-move", -MASK_NO_COND_MOVE }, \ - { "no-cond-move", MASK_NO_COND_MOVE }, \ - { "debug-arg", MASK_DEBUG_ARG }, \ - { "debug-stack", MASK_DEBUG_STACK }, \ - { "debug-addr", MASK_DEBUG_ADDR }, \ - { "asm-optimize", 0 }, \ - { "no-asm-optimize", 0 }, \ - { "extmem", 0 }, \ - { "extmemory", 0 }, \ - { "onchip", 0 }, \ - { "", TARGET_DEFAULT }, \ -} - -/* 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. - - Each subgrouping contains a string constant, that defines the fixed part of - the option name, and the address of a variable. The variable, type `char - *', is set to the variable part of the given option if the fixed part - matches. The actual option name is made by appending `-m' to the specified - name. - - Here is an example which defines `-mshort-data-NUMBER'. If the given option - is `-mshort-data-512', the variable `m88k_short_data' will be set to the - string `"512"'. - - extern char *m88k_short_data; - #define TARGET_OPTIONS \ - { { "short-data-", &m88k_short_data } } */ - -#define TARGET_OPTIONS \ -{ \ - {"branch-cost=", &d30v_branch_cost_string}, \ - {"cond-exec=", &d30v_cond_exec_string}, \ -} - -/* This macro is a C statement to print on `stderr' a string describing the - particular machine description choice. Every machine description should - define `TARGET_VERSION'. For example: - - #ifdef MOTOROLA - #define TARGET_VERSION \ - fprintf (stderr, " (68k, Motorola syntax)"); - #else - #define TARGET_VERSION \ - fprintf (stderr, " (68k, MIT syntax)"); - #endif */ -#define TARGET_VERSION fprintf (stderr, " d30v") - -/* Sometimes certain combinations of command options do not make sense on a - particular target machine. You can define a macro `OVERRIDE_OPTIONS' to - take account of this. This macro, if defined, is executed once just after - all the command options have been parsed. - - Don't use this macro to turn on various extra optimizations for `-O'. That - is what `OPTIMIZATION_OPTIONS' is for. */ - -#define OVERRIDE_OPTIONS override_options () - -/* Some machines may desire to change what optimizations are performed for - various optimization levels. This macro, if defined, is executed once just - after the optimization level is determined and before the remainder of the - command options have been parsed. Values set in this macro are used as the - default values for the other command line options. - - LEVEL is the optimization level specified; 2 if `-O2' is specified, 1 if - `-O' is specified, and 0 if neither is specified. - - SIZE is non-zero if `-Os' is specified, 0 otherwise. - - You should not use this macro to change options that are not - machine-specific. These should uniformly selected by the same optimization - level on all supported machines. Use this macro to enable machbine-specific - optimizations. - - *Do not examine `write_symbols' in this macro!* The debugging options are - *not supposed to alter the generated code. */ -/* #define OPTIMIZATION_OPTIONS(LEVEL,SIZE) */ - -/* Define this macro if debugging can be performed even without a frame - pointer. If this macro is defined, GNU CC will turn on the - `-fomit-frame-pointer' option whenever `-O' is specified. */ -#define CAN_DEBUG_WITHOUT_FP - - -/* Storage Layout */ - -/* Define this macro to have the value 1 if the most significant bit in a byte - has the lowest number; otherwise define it to have the value zero. This - means that bit-field instructions count from the most significant bit. If - the machine has no bit-field instructions, then this must still be defined, - but it doesn't matter which value it is defined to. This macro need not be - a constant. - - This macro does not affect the way structure fields are packed into bytes or - words; that is controlled by `BYTES_BIG_ENDIAN'. */ -#define BITS_BIG_ENDIAN 1 - -/* Define this macro to have the value 1 if the most significant byte in a word - has the lowest number. This macro need not be a constant. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this macro to have the value 1 if, in a multiword object, the most - significant word has the lowest number. This applies to both memory - locations and registers; GNU CC fundamentally assumes that the order of - words in memory is the same as the order in registers. This macro need not - be a constant. */ -#define WORDS_BIG_ENDIAN 1 - -/* Define this macro if WORDS_BIG_ENDIAN is not constant. This must be a - constant value with the same meaning as WORDS_BIG_ENDIAN, which will be used - only when compiling libgcc2.c. Typically the value will be set based on - preprocessor defines. */ -/* #define LIBGCC2_WORDS_BIG_ENDIAN */ - -/* Define this macro to have the value 1 if `DFmode', `XFmode' or `TFmode' - floating point numbers are stored in memory with the word containing the - sign bit at the lowest address; otherwise define it to have the value 0. - This macro need not be a constant. - - You need not define this macro if the ordering is the same as for multi-word - integers. */ -/* #define FLOAT_WORDS_BIG_EnNDIAN */ - -/* Define this macro to be the number of bits in an addressable storage unit - (byte); normally 8. */ -#define BITS_PER_UNIT 8 - -/* Number of bits in a word; normally 32. */ -#define BITS_PER_WORD 32 - -/* Maximum number of bits in a word. If this is undefined, the default is - `BITS_PER_WORD'. Otherwise, it is the constant value that is the largest - value that `BITS_PER_WORD' can have at run-time. */ -/* #define MAX_BITS_PER_WORD */ - -/* Number of storage units in a word; normally 4. */ -#define UNITS_PER_WORD 4 - -/* Minimum number of units in a word. If this is undefined, the default is - `UNITS_PER_WORD'. Otherwise, it is the constant value that is the smallest - value that `UNITS_PER_WORD' can have at run-time. */ -/* #define MIN_UNITS_PER_WORD */ - -/* Width of a pointer, in bits. You must specify a value no wider than the - width of `Pmode'. If it is not equal to the width of `Pmode', you must - define `POINTERS_EXTEND_UNSIGNED'. */ -#define POINTER_SIZE 32 - -/* A C expression whose value is nonzero if pointers that need to be extended - from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and zero if - they are zero-extended. - - You need not define this macro if the `POINTER_SIZE' is equal to the width - of `Pmode'. */ -/* #define POINTERS_EXTEND_UNSIGNED */ - -/* A macro to update M 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. - - On most RISC machines, which only have operations that operate on a full - register, define this macro to set M to `word_mode' if M is an integer mode - narrower than `BITS_PER_WORD'. In most cases, only integer modes should be - widened because wider-precision floating-point operations are usually more - expensive than their narrower counterparts. - - For most machines, the macro definition does not change UNSIGNEDP. However, - some machines, have instructions that preferentially handle either signed or - unsigned quantities of certain modes. For example, on the DEC Alpha, 32-bit - loads from memory and 32-bit add instructions sign-extend the result to 64 - bits. On such machines, set UNSIGNEDP according to which kind of extension - is more efficient. - - Do not define this macro if it would never modify M. */ -#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ -do { \ - if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < 4) \ - (MODE) = SImode; \ -} while (0) - -/* Define this macro if the promotion described by `PROMOTE_MODE' should also - be done for outgoing function arguments. */ -/* #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'. */ -/* #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. */ -/* #define PROMOTE_FOR_CALL_ONLY */ - -/* Normal alignment required for function parameters on the stack, in bits. - All stack parameters receive at least this much alignment regardless of data - type. On most machines, this is the same as the size of an integer. */ - -#define PARM_BOUNDARY 32 - -/* Define this macro if you wish to preserve a certain alignment for the stack - pointer. The definition is a C expression for the desired alignment - (measured in bits). - - If `PUSH_ROUNDING' is not defined, the stack will always be aligned to the - specified boundary. If `PUSH_ROUNDING' is defined and specifies a less - strict alignment than `STACK_BOUNDARY', the stack may be momentarily - unaligned while pushing arguments. */ - -#define STACK_BOUNDARY 64 - -/* Alignment required for a function entry point, in bits. */ - -#define FUNCTION_BOUNDARY 64 - -/* Biggest alignment that any data type can require on this machine, - in bits. */ - -#define BIGGEST_ALIGNMENT 64 - -/* Biggest alignment that any structure field can require on this machine, in - bits. If defined, this overrides `BIGGEST_ALIGNMENT' for structure fields - only. */ -/* #define BIGGEST_FIELD_ALIGNMENT */ - -/* 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'. - - Defined in svr4.h. */ -/* #define MAX_OFILE_ALIGNMENT */ - -/* If defined, a C expression to compute the alignment for a static variable. - 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. - - 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. */ - -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -/* If defined, a C expression to compute the alignment given to a constant that - is being placed in memory. CONSTANT is the constant 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. - - 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 \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -/* Alignment in bits to be given to a structure bit field that follows an empty - field such as `int : 0;'. - - Note that `PCC_BITFIELD_TYPE_MATTERS' also affects the alignment that - results from an empty field. */ -/* #define EMPTY_FIELD_BOUNDARY */ - -/* Number of bits which any structure or union's size must be a multiple of. - Each structure or union's size is rounded up to a multiple of this. - - If you do not define this macro, the default is the same as `BITS_PER_UNIT'. */ -/* #define STRUCTURE_SIZE_BOUNDARY */ - -/* Define this macro to be the value 1 if instructions will fail to work if - given data not on the nominal alignment. If instructions will merely go - slower in that case, define this macro as 0. */ - -#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 bitfield (`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 bitfield 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 bitfield 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. - - Note that if this macro is not defined, or its value is zero, some bitfields - may cross more than one alignment boundary. The compiler can support such - references if there are `insv', `extv', and `extzv' insns that can directly - reference memory. - - The other known way of making bitfields work is to define - `STRUCTURE_SIZE_BOUNDARY' as large as `BIGGEST_ALIGNMENT'. Then every - structure can be accessed with fullwords. - - Unless the machine has bitfield instructions or you define - `STRUCTURE_SIZE_BOUNDARY' that way, you must define - `PCC_BITFIELD_TYPE_MATTERS' to have a nonzero value. - - If your aim is to make GNU CC use the same conventions for laying out - bitfields as are used by another compiler, here is how to investigate what - the other compiler does. Compile and run this program: - - struct foo1 - { - char x; - char :0; - char y; - }; - - struct foo2 - { - char x; - int :0; - char y; - }; - - main () - { - printf ("Size of foo1 is %d\n", - sizeof (struct foo1)); - printf ("Size of foo2 is %d\n", - sizeof (struct foo2)); - exit (0); - } - - If this prints 2 and 5, then the compiler's behavior is what you would get - from `PCC_BITFIELD_TYPE_MATTERS'. - - Defined in svr4.h. */ - -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* Like PCC_BITFIELD_TYPE_MATTERS except that its effect is limited to aligning - a bitfield within the structure. */ -/* #define BITFIELD_NBYTES_LIMITED */ - -/* Define this macro as an expression for the overall size of a structure - (given by STRUCT as a tree node) when the size computed from the fields is - SIZE and the alignment is ALIGN. - - The default is to round SIZE up to a multiple of ALIGN. */ -/* #define ROUND_TYPE_SIZE(STRUCT, SIZE, ALIGN) */ - -/* Define this macro as an expression for the alignment of a structure (given - by STRUCT as a tree node) if the alignment computed in the usual way is - COMPUTED and the alignment explicitly specified was SPECIFIED. - - The default is to use SPECIFIED if it is larger; otherwise, use the smaller - of COMPUTED and `BIGGEST_ALIGNMENT' */ -/* #define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) */ - -/* An integer expression for the size in bits of the largest integer machine - mode that should actually be used. All integer machine modes of this size - or smaller can be used for structures and unions with the appropriate sizes. - If this macro is undefined, `GET_MODE_BITSIZE (DImode)' is assumed. */ -/* #define MAX_FIXED_MODE_SIZE */ - -/* A C statement to validate the value VALUE (of type `double') for mode MODE. - This means that you check whether VALUE fits within the possible range of - values for mode MODE on this target machine. The mode MODE is always a mode - of class `MODE_FLOAT'. OVERFLOW is nonzero if the value is already known to - be out of range. - - If VALUE is not valid or if OVERFLOW is nonzero, you should set OVERFLOW to - 1 and then assign some valid value to VALUE. Allowing an invalid value to - go through the compiler can produce incorrect assembler code which may even - cause Unix assemblers to crash. - - This macro need not be defined if there is no work for it to do. */ -/* #define CHECK_FLOAT_VALUE(MODE, VALUE, OVERFLOW) */ - -/* A code distinguishing the floating point format of the target machine. - There are three defined values: - - IEEE_FLOAT_FORMAT' - This code indicates IEEE floating point. It is the default; - there is no need to define this macro when the format is IEEE. - - VAX_FLOAT_FORMAT' - This code indicates the peculiar format used on the Vax. - - UNKNOWN_FLOAT_FORMAT' - This code indicates any other format. - - The value of this macro is compared with `HOST_FLOAT_FORMAT' (*note - Config::.) to determine whether the target machine has the same format as - the host machine. If any other formats are actually in use on supported - machines, new codes should be defined for them. - - The ordering of the component words of floating point values stored in - memory is controlled by `FLOAT_WORDS_BIG_ENDIAN' for the target machine and - `HOST_FLOAT_WORDS_BIG_ENDIAN' for the host. */ -#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT - -/* GNU CC supports two ways of implementing C++ vtables: traditional or with - so-called "thunks". The flag `-fvtable-thunk' chooses between them. Define - this macro to be a C expression for the default value of that flag. If - `DEFAULT_VTABLE_THUNKS' is 0, GNU CC uses the traditional implementation by - default. The "thunk" implementation is more efficient (especially if you - have provided an implementation of `ASM_OUTPUT_MI_THUNK', see *Note Function - Entry::), but is not binary compatible with code compiled using the - traditional implementation. If you are writing a new ports, define - `DEFAULT_VTABLE_THUNKS' to 1. - - If you do not define this macro, the default for `-fvtable-thunk' is 0. */ -#define DEFAULT_VTABLE_THUNKS 1 - - -/* Layout of Source Language Data Types */ - -/* A C expression for the size in bits of the type `int' on the target machine. - If you don't define this, the default is one word. */ -#define INT_TYPE_SIZE 32 - -/* Maximum number for the size in bits of the type `int' on the target machine. - If this is undefined, the default is `INT_TYPE_SIZE'. Otherwise, it is the - constant value that is the largest value that `INT_TYPE_SIZE' can have at - run-time. This is used in `cpp'. */ -/* #define MAX_INT_TYPE_SIZE */ - -/* A C expression for the size in bits of the type `short' on the target - machine. If you don't define this, the default is half a word. (If this - would be less than one storage unit, it is rounded up to one unit.) */ -#define SHORT_TYPE_SIZE 16 - -/* A C expression for the size in bits of the type `long' on the target - machine. If you don't define this, the default is one word. */ -#define LONG_TYPE_SIZE 32 - -/* Maximum number for the size in bits of the type `long' on the target - machine. If this is undefined, the default is `LONG_TYPE_SIZE'. Otherwise, - it is the constant value that is the largest value that `LONG_TYPE_SIZE' can - have at run-time. This is used in `cpp'. */ -/* #define MAX_LONG_TYPE_SIZE */ - -/* A C expression for the size in bits of the type `long long' on the target - machine. If you don't define this, the default is two words. If you want - to support GNU Ada on your machine, the value of macro must be at least 64. */ -#define LONG_LONG_TYPE_SIZE 64 - -/* A C expression for the size in bits of the type `char' on the target - machine. If you don't define this, the default is one quarter of a word. - (If this would be less than one storage unit, it is rounded up to one unit.) */ -#define CHAR_TYPE_SIZE 8 - -/* Maximum number for the size in bits of the type `char' on the target - machine. If this is undefined, the default is `CHAR_TYPE_SIZE'. Otherwise, - it is the constant value that is the largest value that `CHAR_TYPE_SIZE' can - have at run-time. This is used in `cpp'. */ -/* #define MAX_CHAR_TYPE_SIZE */ - -/* A C expression for the size in bits of the type `float' on the target - machine. If you don't define this, the default is one word. */ -#define FLOAT_TYPE_SIZE 32 - -/* A C expression for the size in bits of the type `double' on the target - machine. If you don't define this, the default is two words. */ -#define DOUBLE_TYPE_SIZE 64 - -/* A C expression for the size in bits of the type `long double' on the target - machine. If you don't define this, the default is two words. */ -#define LONG_DOUBLE_TYPE_SIZE 64 - -/* An expression whose value is 1 or 0, according to whether the type `char' - should be signed or unsigned by default. The user can always override this - default with the options `-fsigned-char' and `-funsigned-char'. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* A C expression to determine whether to give an `enum' type only as many - bytes as it takes to represent the range of possible values of that type. A - nonzero value means to do that; a zero value means all `enum' types should - be allocated like `int'. - - If you don't define the macro, the default is 0. */ -/* #define DEFAULT_SHORT_ENUMS */ - -/* A C expression for a string describing the name of the data type to use for - size values. The typedef name `size_t' is defined using the contents of the - string. - - The string can contain more than one keyword. If so, separate them with - spaces, and write first any length keyword, then `unsigned' if appropriate, - and finally `int'. The string must exactly match one of the data type names - defined in the function `init_decl_processing' in the file `c-decl.c'. You - may not omit `int' or change the order--that would cause the compiler to - crash on startup. - - If you don't define this macro, the default is `"long unsigned int"'. - - Defined in svr4.h. */ -/* #define SIZE_TYPE */ - -/* A C expression for a string describing the name of the data type to use for - the result of subtracting two pointers. The typedef name `ptrdiff_t' is - defined using the contents of the string. See `SIZE_TYPE' above for more - information. - - If you don't define this macro, the default is `"long int"'. - - Defined in svr4.h. */ -/* #define PTRDIFF_TYPE */ - -/* A C expression for a string describing the name of the data type to use for - wide characters. The typedef name `wchar_t' is defined using the contents - of the string. See `SIZE_TYPE' above for more information. - - If you don't define this macro, the default is `"int"'. - - Defined in svr4.h. */ -/* #define WCHAR_TYPE */ - -/* A C expression for the size in bits of the data type for wide characters. - This is used in `cpp', which cannot make use of `WCHAR_TYPE'. - - Defined in svr4.h. */ -/* #define WCHAR_TYPE_SIZE */ - -/* Maximum number for the size in bits of the data type for wide characters. - If this is undefined, the default is `WCHAR_TYPE_SIZE'. Otherwise, it is - the constant value that is the largest value that `WCHAR_TYPE_SIZE' can have - at run-time. This is used in `cpp'. */ -/* #define MAX_WCHAR_TYPE_SIZE */ - -/* Define this macro if the type of Objective C selectors should be `int'. - - If this macro is not defined, then selectors should have the type `struct - objc_selector *'. */ -/* #define OBJC_INT_SELECTORS */ - -/* Define this macro if the compiler can group all the selectors together into - a vector and use just one label at the beginning of the vector. Otherwise, - the compiler must give each selector its own assembler label. - - On certain machines, it is important to have a separate label for each - selector because this enables the linker to eliminate duplicate selectors. */ -/* #define OBJC_SELECTORS_WITHOUT_LABELS */ - -/* A C constant expression for the integer value for escape sequence - `\a'. */ -#define TARGET_BELL 0x7 - -/* C constant expressions for the integer values for escape sequences - `\b', `\t' and `\n'. */ -#define TARGET_BS 0x8 -#define TARGET_TAB 0x9 -#define TARGET_NEWLINE 0xa - -/* C constant expressions for the integer values for escape sequences - `\v', `\f' and `\r'. */ -#define TARGET_VT 0xb -#define TARGET_FF 0xc -#define TARGET_CR 0xd - - -/* D30V register layout. */ - -/* Return true if a value is inside a range */ -#define IN_RANGE_P(VALUE, LOW, HIGH) \ - (((unsigned)((VALUE) - (LOW))) <= ((unsigned)((HIGH) - (LOW)))) - -/* General purpose registers. */ -#define GPR_FIRST 0 /* First gpr */ -#define GPR_LAST (GPR_FIRST + 63) /* Last gpr */ -#define GPR_R0 GPR_FIRST /* R0, constant 0 */ -#define GPR_ARG_FIRST (GPR_FIRST + 2) /* R2, first argument reg */ -#define GPR_ARG_LAST (GPR_FIRST + 17) /* R17, last argument reg */ -#define GPR_RET_VALUE GPR_ARG_FIRST /* R2, function return reg */ -#define GPR_ATMP_FIRST (GPR_FIRST + 20) /* R20, tmp to save accs */ -#define GPR_ATMP_LAST (GPR_FIRST + 21) /* R21, tmp to save accs */ -#define GPR_STACK_TMP (GPR_FIRST + 22) /* R22, tmp for saving stack */ -#define GPR_RES_FIRST (GPR_FIRST + 32) /* R32, first reserved reg */ -#define GPR_RES_LAST (GPR_FIRST + 35) /* R35, last reserved reg */ -#define GPR_FP (GPR_FIRST + 61) /* Frame pointer */ -#define GPR_LINK (GPR_FIRST + 62) /* Return address register */ -#define GPR_SP (GPR_FIRST + 63) /* Stack pointer */ - -/* Argument register that is eliminated in favor of the frame and/or stack - pointer. Also add register to point to where the return address is - stored. */ -#define SPECIAL_REG_FIRST (GPR_LAST + 1) -#define SPECIAL_REG_LAST (SPECIAL_REG_FIRST) -#define ARG_POINTER_REGNUM (SPECIAL_REG_FIRST + 0) -#define SPECIAL_REG_P(R) ((R) == SPECIAL_REG_FIRST) - -#define GPR_OR_SPECIAL_REG_P(R) IN_RANGE_P (R, GPR_FIRST, SPECIAL_REG_LAST) -#define GPR_P(R) IN_RANGE_P (R, GPR_FIRST, GPR_LAST) -#define GPR_OR_PSEUDO_P(R) (GPR_OR_SPECIAL_REG_P (R) \ - || (R) >= FIRST_PSEUDO_REGISTER) - -/* Flag bits. */ -#define FLAG_FIRST (SPECIAL_REG_LAST + 1) /* First flag */ -#define FLAG_LAST (FLAG_FIRST + 7) /* Last flag */ -#define FLAG_F0 (FLAG_FIRST) /* F0, used in prediction */ -#define FLAG_F1 (FLAG_FIRST + 1) /* F1, used in prediction */ -#define FLAG_F2 (FLAG_FIRST + 2) /* F2, general flag */ -#define FLAG_F3 (FLAG_FIRST + 3) /* F3, general flag */ -#define FLAG_SAT (FLAG_FIRST + 4) /* F4, saturation flag */ -#define FLAG_OVERFLOW (FLAG_FIRST + 5) /* F5, overflow flag */ -#define FLAG_ACC_OVER (FLAG_FIRST + 6) /* F6, accumulated overflow */ -#define FLAG_CARRY (FLAG_FIRST + 7) /* F7, carry/borrow flag */ -#define FLAG_BORROW FLAG_CARRY - -#define FLAG_P(R) IN_RANGE_P (R, FLAG_FIRST, FLAG_LAST) -#define FLAG_OR_PSEUDO_P(R) (FLAG_P (R) || (R) >= FIRST_PSEUDO_REGISTER) - -#define BR_FLAG_P(R) IN_RANGE_P (R, FLAG_F0, FLAG_F1) -#define BR_FLAG_OR_PSEUDO_P(R) (BR_FLAG_P (R) || (R) >= FIRST_PSEUDO_REGISTER) - -/* Accumulators */ -#define ACCUM_FIRST (FLAG_LAST + 1) /* First accumulator */ -#define ACCUM_A0 ACCUM_FIRST /* Register A0 */ -#define ACCUM_A1 (ACCUM_FIRST + 1) /* Register A1 */ -#define ACCUM_LAST (ACCUM_FIRST + 1) /* Last accumulator */ - -#define ACCUM_P(R) IN_RANGE_P (R, ACCUM_FIRST, ACCUM_LAST) -#define ACCUM_OR_PSEUDO_P(R) (ACCUM_P (R) || (R) >= FIRST_PSEUDO_REGISTER) - -/* Special registers. Note, we only define the registers that can actually - be used. */ -#define CR_FIRST (ACCUM_LAST + 1) /* First CR */ -#define CR_LAST (CR_FIRST + 14) /* Last CR */ -#define CR_PSW (CR_FIRST + 0) /* CR0, Program status word */ -#define CR_BPSW (CR_FIRST + 1) /* CR1, Backup PSW */ -#define CR_PC (CR_FIRST + 2) /* CR2, Program counter */ -#define CR_BPC (CR_FIRST + 3) /* CR3, Backup PC */ -#define CR_DPSW (CR_FIRST + 4) /* CR4, Debug PSW */ -#define CR_DPC (CR_FIRST + 5) /* CR5, Debug PC */ -#define CR_RPT_C (CR_FIRST + 6) /* CR7, loop count register */ -#define CR_RPT_S (CR_FIRST + 7) /* CR8, loop start address */ -#define CR_RPT_E (CR_FIRST + 8) /* CR9, loop end address */ -#define CR_MOD_S (CR_FIRST + 9) /* CR10, modulo address start*/ -#define CR_MOD_E (CR_FIRST + 10) /* CR11, modulo address */ -#define CR_IBA (CR_FIRST + 11) /* CR14, Interrupt break addr */ -#define CR_EIT_VB (CR_FIRST + 12) /* CR15, EIT vector address */ -#define CR_INT_S (CR_FIRST + 13) /* CR16, Interrupt status */ -#define CR_INT_M (CR_FIRST + 14) /* CR17, Interrupt mask */ - -#define CR_P(R) IN_RANGE_P (R, CR_FIRST, CR_LAST) -#define CR_OR_PSEUDO_P(R) (CR_P (R) || (R) >= FIRST_PSEUDO_REGISTER) - - -/* Register Basics */ - -/* Number of hardware registers known to the compiler. They receive numbers 0 - through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number - really is assigned the number `FIRST_PSEUDO_REGISTER'. */ -#define FIRST_PSEUDO_REGISTER (CR_LAST + 1) - -/* An initializer that says which registers are used for fixed purposes all - throughout the compiled code and are therefore not available for general - allocation. These would include the stack pointer, the frame pointer - (except on machines where that can be used as a general register when no - frame pointer is needed), the program counter on machines where that is - considered one of the addressable registers, and any other numbered register - with a standard use. - - This information is expressed as a sequence of numbers, separated by commas - and surrounded by braces. The Nth number is 1 if register N is fixed, 0 - otherwise. - - The table initialized from this macro, and the table initialized by the - following one, may be overridden at run time either automatically, by the - actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the - command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'. */ -#define FIXED_REGISTERS \ -{ \ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* R0 - R15 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* R16 - R31 */ \ - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* R32 - R47 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* R48 - R63 */ \ - 1, /* ARG ptr */ \ - 0, 0, 0, 0, 1, 1, 1, 1, /* F0 - F7 */ \ - 0, 0, /* A0 - A1 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* CRs */ \ -} - -/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in - general) by function calls as well as for fixed registers. This macro - therefore identifies the registers that are not available for general - allocation of values that must live across function calls. - - If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically - saves it on function entry and restores it on function exit, if the register - is used within the function. */ -#define CALL_USED_REGISTERS \ -{ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* R0 - R15 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* R16 - R31 */ \ - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* R32 - R47 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* R48 - R63 */ \ - 1, /* ARG ptr */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - F7 */ \ - 1, 0, /* A0 - A1 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* CRs */ \ -} - -/* Zero or more C statements that may conditionally modify two variables - `fixed_regs' and `call_used_regs' (both of type `char []') after they have - been initialized from the two preceding macros. - - This is necessary in case the fixed or call-clobbered registers depend on - target flags. - - You need not define this macro if it has no work to do. - - If the usage of an entire class of registers depends on the target flags, - you may indicate this to GCC by using this macro to modify `fixed_regs' and - `call_used_regs' to 1 for each of the registers in the classes which should - not be used by GCC. Also define the macro `REG_CLASS_FROM_LETTER' to return - `NO_REGS' if it is called with a letter for a class that shouldn't be used. - - (However, if this class is not included in `GENERAL_REGS' and all of the - insn patterns whose constraints permit this class are controlled by target - switches, then GCC will automatically avoid using these registers when the - target switches are opposed to them.) */ -/* #define CONDITIONAL_REGISTER_USAGE */ - -/* If this macro is defined and has a nonzero value, it means that `setjmp' and - related functions fail to save the registers, or that `longjmp' fails to - restore them. To compensate, the compiler avoids putting variables in - registers in functions that use `setjmp'. */ -/* #define NON_SAVING_SETJMP */ - -/* 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 the register number OUT as seen by the calling function. - Return OUT if register number OUT is not an outbound register. */ -/* #define INCOMING_REGNO(OUT) */ - -/* Define this macro if the target machine has register windows. This C - expression returns the register number as seen by the calling function - corresponding to the register number IN as seen by the called function. - Return IN if register number IN is not an inbound register. */ -/* #define OUTGOING_REGNO(IN) */ - - -/* Order of allocation of registers */ - -/* If defined, an initializer for a vector of integers, containing the numbers - of hard registers in the order in which GNU CC should prefer to use them - (from most preferred to least). - - If this macro is not defined, registers are used lowest numbered first (all - else being equal). - - One use of this macro is on machines where the highest numbered registers - must always be saved and the save-multiple-registers instruction supports - only sequences of consecutive registers. On such machines, define - `REG_ALLOC_ORDER' to be an initializer that lists the highest numbered - allocatable register first. */ - -#define REG_ALLOC_ORDER \ -{ \ - /* volatile registers */ \ - GPR_FIRST + 2, GPR_FIRST + 3, GPR_FIRST + 4, GPR_FIRST + 5, \ - GPR_FIRST + 6, GPR_FIRST + 7, GPR_FIRST + 8, GPR_FIRST + 9, \ - GPR_FIRST + 10, GPR_FIRST + 11, GPR_FIRST + 12, GPR_FIRST + 13, \ - GPR_FIRST + 14, GPR_FIRST + 15, GPR_FIRST + 16, GPR_FIRST + 17, \ - GPR_FIRST + 18, GPR_FIRST + 19, GPR_FIRST + 20, GPR_FIRST + 21, \ - GPR_FIRST + 22, GPR_FIRST + 23, GPR_FIRST + 24, GPR_FIRST + 25, \ - GPR_FIRST + 1, \ - \ - /* saved registers */ \ - GPR_FIRST + 34, GPR_FIRST + 35, GPR_FIRST + 36, GPR_FIRST + 37, \ - GPR_FIRST + 38, GPR_FIRST + 39, GPR_FIRST + 40, GPR_FIRST + 41, \ - GPR_FIRST + 42, GPR_FIRST + 43, GPR_FIRST + 44, GPR_FIRST + 45, \ - GPR_FIRST + 46, GPR_FIRST + 47, GPR_FIRST + 48, GPR_FIRST + 49, \ - GPR_FIRST + 50, GPR_FIRST + 51, GPR_FIRST + 52, GPR_FIRST + 53, \ - GPR_FIRST + 54, GPR_FIRST + 55, GPR_FIRST + 56, GPR_FIRST + 57, \ - GPR_FIRST + 58, GPR_FIRST + 59, GPR_FIRST + 60, GPR_FIRST + 61, \ - GPR_FIRST + 62, \ - \ - /* flags */ \ - FLAG_F2, FLAG_F3, FLAG_F0, FLAG_F1, \ - FLAG_SAT, FLAG_OVERFLOW, FLAG_ACC_OVER, FLAG_CARRY, \ - \ - /* accumultors */ \ - ACCUM_FIRST + 0, ACCUM_FIRST + 1, \ - \ - /* fixed registers */ \ - GPR_FIRST + 0, GPR_FIRST + 26, GPR_FIRST + 27, GPR_FIRST + 28, \ - GPR_FIRST + 29, GPR_FIRST + 30, GPR_FIRST + 31, GPR_FIRST + 32, \ - GPR_FIRST + 33, GPR_FIRST + 63, \ - CR_PSW, CR_BPSW, CR_PC, CR_BPC, \ - CR_DPSW, CR_DPC, CR_RPT_C, CR_RPT_S, \ - CR_RPT_E, CR_MOD_S, CR_MOD_E, CR_IBA, \ - CR_EIT_VB, CR_INT_S, CR_INT_M, \ - ARG_POINTER_REGNUM, \ -} - -/* A C statement (sans semicolon) to choose the order in which to allocate hard - registers for pseudo-registers local to a basic block. - - Store the desired register order in the array `reg_alloc_order'. Element 0 - should be the register to allocate first; element 1, the next register; and - so on. - - The macro body should not assume anything about the contents of - `reg_alloc_order' before execution of the macro. - - On most machines, it is not necessary to define this macro. */ -/* #define ORDER_REGS_FOR_LOCAL_ALLOC */ - - -/* How Values Fit in Registers */ - -/* A C expression for the number of consecutive hard registers, starting at - register number REGNO, required to hold a value of mode MODE. - - On a machine where all registers are exactly one word, a suitable definition - of this macro is - - #define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \ - / UNITS_PER_WORD)) */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ -(ACCUM_P (REGNO) ? ((GET_MODE_SIZE (MODE) + 2*UNITS_PER_WORD - 1) \ - / (2*UNITS_PER_WORD)) \ - : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \ - / UNITS_PER_WORD)) - -/* A C expression that is nonzero if it is permissible to store a value of mode - MODE in hard register number REGNO (or in several registers starting with - that one). For a machine where all registers are equivalent, a suitable - definition is - - #define HARD_REGNO_MODE_OK(REGNO, MODE) 1 - - It is not necessary for this macro to check for the numbers of fixed - registers, because the allocation mechanism considers them to be always - occupied. - - On some machines, double-precision values must be kept in even/odd register - pairs. The way to implement that is to define this macro to reject odd - register numbers for such modes. - - The minimum requirement for a mode to be OK in a register is that the - `movMODE' instruction pattern support moves between the register and any - other hard register for which the mode is OK; and that moving a value into - the register and back out not alter it. - - Since the same instruction used to move `SImode' will work for all narrower - integer modes, it is not necessary on any machine for `HARD_REGNO_MODE_OK' - to distinguish between these modes, provided you define patterns `movhi', - etc., to take advantage of this. This is useful because of the interaction - between `HARD_REGNO_MODE_OK' and `MODES_TIEABLE_P'; it is very desirable for - all integer modes to be tieable. - - Many machines have special registers for floating point arithmetic. Often - people assume that floating point machine modes are allowed only in floating - point registers. This is not true. Any registers that can hold integers - can safely *hold* a floating point machine mode, whether or not floating - arithmetic can be done on it in those registers. Integer move instructions - can be used to move the values. - - On some machines, though, the converse is true: fixed-point machine modes - may not go in floating registers. This is true if the floating registers - normalize any value stored in them, because storing a non-floating value - there would garble it. In this case, `HARD_REGNO_MODE_OK' should reject - fixed-point machine modes in floating registers. But if the floating - registers do not automatically normalize, if you can store any bit pattern - in one and retrieve it unchanged without a trap, then any machine mode may - go in a floating register, so you can define this macro to say so. - - The primary significance of special floating registers is rather that they - are the registers acceptable in floating point arithmetic instructions. - However, this is of no concern to `HARD_REGNO_MODE_OK'. You handle it by - writing the proper constraints for those instructions. - - On some machines, the floating registers are especially slow to access, so - that it is better to store a value in a stack frame than in such a register - if floating point arithmetic is not being done. As long as the floating - registers are not in class `GENERAL_REGS', they will not be used unless some - pattern's constraint asks for one. */ - -extern unsigned char hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; -#define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok[ (int)MODE ][ REGNO ] - -/* A C expression that is nonzero if it is desirable to choose register - allocation so as to avoid move instructions between a value of mode MODE1 - and a value of mode MODE2. - - If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are - ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be - zero. */ - -extern unsigned char modes_tieable_p[]; -#define MODES_TIEABLE_P(MODE1, MODE2) \ - modes_tieable_p[ (((int)(MODE1)) * (NUM_MACHINE_MODES)) + (int)(MODE2) ] - -/* Define this macro if the compiler should avoid copies to/from CCmode - registers. You should only define this macro if support fo copying to/from - CCmode is incomplete. */ - -/* On the D30V, copying to/from CCmode is complete, but since there are only - two CC registers usable for conditional tests, this helps gcse not compound - the reload problem. */ -#define AVOID_CCMODE_COPIES - - -/* Handling Leaf Functions */ - -/* A C initializer for a vector, indexed by hard register number, which - contains 1 for a register that is allowable in a candidate for leaf function - treatment. - - If leaf function treatment involves renumbering the registers, then the - registers marked here should be the ones before renumbering--those that GNU - CC would ordinarily allocate. The registers which will actually be used in - the assembler code, after renumbering, should not be marked with 1 in this - vector. - - Define this macro only if the target machine offers a way to optimize the - treatment of leaf functions. */ -/* #define LEAF_REGISTERS */ - -/* A C expression whose value is the register number to which REGNO should be - renumbered, when a function is treated as a leaf function. - - If REGNO is a register number which should not appear in a leaf function - before renumbering, then the expression should yield -1, which will cause - the compiler to abort. - - Define this macro only if the target machine offers a way to optimize the - treatment of leaf functions, and registers need to be renumbered to do this. */ -/* #define LEAF_REG_REMAP(REGNO) */ - - -/* Registers That Form a Stack. */ - -/* Define this if the machine has any stack-like registers. */ -/* #define STACK_REGS */ - -/* The number of the first stack-like register. This one is the top - of the stack. */ -/* #define FIRST_STACK_REG */ - -/* The number of the last stack-like register. This one is the - bottom of the stack. */ -/* #define LAST_STACK_REG */ - - -/* Register Classes */ - -/* An enumeral type that must be defined with all the register class names as - enumeral values. `NO_REGS' must be first. `ALL_REGS' must be the last - register class, followed by one more enumeral value, `LIM_REG_CLASSES', - which is not a register class but rather tells how many classes there are. - - Each register class has a number, which is the value of casting the class - name to type `int'. The number serves as an index in many of the tables - described below. */ -enum reg_class -{ - NO_REGS, - REPEAT_REGS, - CR_REGS, - ACCUM_REGS, - OTHER_FLAG_REGS, - F0_REGS, - F1_REGS, - BR_FLAG_REGS, - FLAG_REGS, - EVEN_REGS, - GPR_REGS, - ALL_REGS, - LIM_REG_CLASSES -}; - -#define GENERAL_REGS GPR_REGS - -/* The number of distinct register classes, defined as follows: - - #define N_REG_CLASSES (int) LIM_REG_CLASSES */ -#define N_REG_CLASSES ((int) LIM_REG_CLASSES) - -/* An initializer containing the names of the register classes as C string - constants. These names are used in writing some of the debugging dumps. */ -#define REG_CLASS_NAMES \ -{ \ - "NO_REGS", \ - "REPEAT_REGS", \ - "CR_REGS", \ - "ACCUM_REGS", \ - "OTHER_FLAG_REGS", \ - "F0_REGS", \ - "F1_REGS", \ - "BR_FLAG_REGS", \ - "FLAG_REGS", \ - "EVEN_REGS", \ - "GPR_REGS", \ - "ALL_REGS", \ -} - -/* Create mask bits for 3rd word of REG_CLASS_CONTENTS */ -#define MASK_WORD3(REG) ((long)1 << ((REG) - 64)) - -#define NO_MASK 0 -#define REPEAT_MASK MASK_WORD3 (CR_RPT_C) -#define CR_MASK (MASK_WORD3 (CR_PSW) | MASK_WORD3 (CR_BPSW) \ - | MASK_WORD3 (CR_PC) | MASK_WORD3 (CR_BPC) \ - | MASK_WORD3 (CR_DPSW) | MASK_WORD3 (CR_DPC) \ - | MASK_WORD3 (CR_RPT_C) | MASK_WORD3 (CR_RPT_S) \ - | MASK_WORD3 (CR_RPT_E) | MASK_WORD3 (CR_MOD_S) \ - | MASK_WORD3 (CR_MOD_E) | MASK_WORD3 (CR_IBA) \ - | MASK_WORD3 (CR_EIT_VB) | MASK_WORD3 (CR_INT_S) \ - | MASK_WORD3 (CR_INT_M)) - -#define ACCUM_MASK (MASK_WORD3 (ACCUM_A0) | MASK_WORD3 (ACCUM_A1)) -#define OTHER_FLAG_MASK (MASK_WORD3 (FLAG_F2) | MASK_WORD3 (FLAG_F3) \ - | MASK_WORD3 (FLAG_SAT) | MASK_WORD3 (FLAG_OVERFLOW) \ - | MASK_WORD3 (FLAG_ACC_OVER) | MASK_WORD3 (FLAG_CARRY)) - -#define F0_MASK MASK_WORD3 (FLAG_F0) -#define F1_MASK MASK_WORD3 (FLAG_F1) -#define BR_FLAG_MASK (F0_MASK | F1_MASK) -#define FLAG_MASK (BR_FLAG_MASK | OTHER_FLAG_MASK) -#define SPECIAL_MASK MASK_WORD3 (ARG_POINTER_REGNUM) - -#define ALL_MASK (CR_MASK | ACCUM_MASK | FLAG_MASK | SPECIAL_MASK) - -/* An initializer containing the contents of the register classes, as integers - which are bit masks. The Nth integer specifies the contents of class N. - The way the integer MASK is interpreted is that register R is in the class - if `MASK & (1 << R)' is 1. - - When the machine has more than 32 registers, an integer does not suffice. - Then the integers are replaced by sub-initializers, braced groupings - containing several integers. Each sub-initializer must be suitable as an - initializer for the type `HARD_REG_SET' which is defined in - `hard-reg-set.h'. */ -#define REG_CLASS_CONTENTS \ -{ \ - { 0x00000000, 0x00000000, NO_MASK }, /* NO_REGS */ \ - { 0x00000000, 0x00000000, REPEAT_MASK }, /* REPEAT_REGS */ \ - { 0x00000000, 0x00000000, CR_MASK }, /* CR_REGS */ \ - { 0x00000000, 0x00000000, ACCUM_MASK }, /* ACCUM_REGS */ \ - { 0x00000000, 0x00000000, OTHER_FLAG_MASK }, /* OTHER_FLAG_REGS */ \ - { 0x00000000, 0x00000000, F0_MASK }, /* F0_REGS */ \ - { 0x00000000, 0x00000000, F1_MASK }, /* F1_REGS */ \ - { 0x00000000, 0x00000000, BR_FLAG_MASK }, /* BR_FLAG_REGS */ \ - { 0x00000000, 0x00000000, FLAG_MASK }, /* FLAG_REGS */ \ - { 0xfffffffc, 0x3fffffff, NO_MASK }, /* EVEN_REGS */ \ - { 0xffffffff, 0xffffffff, SPECIAL_MASK }, /* GPR_REGS */ \ - { 0xffffffff, 0xffffffff, ALL_MASK }, /* ALL_REGS */ \ -} - -/* A C expression whose value is a register class containing hard register - REGNO. In general there is more than one such class; choose a class which - is "minimal", meaning that no smaller class also contains the register. */ - -extern enum reg_class regno_reg_class[]; -#define REGNO_REG_CLASS(REGNO) regno_reg_class[ (REGNO) ] - -/* A macro whose definition is the name of the class to which a valid base - register must belong. A base register is one used in an address which is - the register value plus a displacement. */ -#define BASE_REG_CLASS GPR_REGS - -/* A macro whose definition is the name of the class to which a valid index - register must belong. An index register is one used in an address where its - value is either multiplied by a scale factor or added to another register - (as well as added to a displacement). */ -#define INDEX_REG_CLASS GPR_REGS - -/* A C expression which defines the machine-dependent operand constraint - letters for register classes. If CHAR is such a letter, the value should be - the register class corresponding to it. Otherwise, the value should be - `NO_REGS'. The register letter `r', corresponding to class `GENERAL_REGS', - will not be passed to this macro; you do not need to handle it. - - The following letters are unavailable, due to being used as - constraints: - '0'..'9' - '<', '>' - 'E', 'F', 'G', 'H' - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' - 'Q', 'R', 'S', 'T', 'U' - 'V', 'X' - 'g', 'i', 'm', 'n', 'o', 'p', 'r', 's' */ - -extern enum reg_class reg_class_from_letter[]; -#define REG_CLASS_FROM_LETTER(CHAR) reg_class_from_letter[ CHAR ] - -/* A C expression which is nonzero if register number NUM is suitable for use - as a base register in operand addresses. It may be either a suitable hard - register or a pseudo register that has been allocated such a hard register. */ - -#define REGNO_OK_FOR_BASE_P(NUM) \ -((NUM) < FIRST_PSEUDO_REGISTER \ - ? GPR_P (NUM) \ - : (reg_renumber[NUM] >= 0 && GPR_P (reg_renumber[NUM]))) - - -/* A C expression which is nonzero if register number NUM is suitable for use - as an index register in operand addresses. It may be either a suitable hard - register or a pseudo register that has been allocated such a hard register. - - The difference between an index register and a base register is that the - index register may be scaled. If an address involves the sum of two - registers, neither one of them scaled, then either one may be labeled the - "base" and the other the "index"; but whichever labeling is used must fit - the machine's constraints of which registers may serve in each capacity. - The compiler will try both labelings, looking for one that is valid, and - will reload one or both registers only if neither labeling works. */ - -#define REGNO_OK_FOR_INDEX_P(NUM) \ -((NUM) < FIRST_PSEUDO_REGISTER \ - ? GPR_P (NUM) \ - : (reg_renumber[NUM] >= 0 && GPR_P (reg_renumber[NUM]))) - -/* A C expression that places additional restrictions on the register class to - use when it is necessary to copy value X into a register in class CLASS. - The value is a register class; perhaps CLASS, or perhaps another, smaller - class. On many machines, the following definition is safe: - - #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS - - Sometimes returning a more restrictive class makes better code. For - example, on the 68000, when X is an integer constant that is in range for a - `moveq' instruction, the value of this macro is always `DATA_REGS' as long - as CLASS includes the data registers. Requiring a data register guarantees - that a `moveq' will be used. - - If X is a `const_double', by returning `NO_REGS' you can force X into a - memory constant. This is useful on certain machines where immediate - floating values cannot be loaded into certain kinds of registers. */ -#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS - -/* Like `PREFERRED_RELOAD_CLASS', but for output reloads instead of input - reloads. If you don't define this macro, the default is to use CLASS, - unchanged. */ -/* #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) */ - -/* A C expression that places additional restrictions on the register class to - use when it is necessary to be able to hold a value of mode MODE in a reload - register for which class CLASS would ordinarily be used. - - Unlike `PREFERRED_RELOAD_CLASS', this macro should be used when there are - certain modes that simply can't go in certain reload classes. - - The value is a register class; perhaps CLASS, or perhaps another, smaller - class. - - Don't define this macro unless the target machine has limitations which - require the macro to do something nontrivial. */ -/* #define LIMIT_RELOAD_CLASS(MODE, CLASS) */ - -/* Many machines have some registers that cannot be copied directly to or from - memory or even from other types of registers. An example is the `MQ' - register, which on most machines, can only be copied to or from general - registers, but not memory. Some machines allow copying all registers to and - from memory, but require a scratch register for stores to some memory - locations (e.g., those with symbolic address on the RT, and those with - certain symbolic address on the Sparc when compiling PIC). In some cases, - both an intermediate and a scratch register are required. - - You should define these macros to indicate to the reload phase that it may - need to allocate at least one register for a reload in addition to the - register to contain the data. Specifically, if copying X to a register - CLASS in MODE requires an intermediate register, you should define - `SECONDARY_INPUT_RELOAD_CLASS' to return the largest register class all of - whose registers can be used as intermediate registers or scratch registers. - - If copying a register CLASS in MODE to X requires an intermediate or scratch - register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be defined to return the - largest register class required. If the requirements for input and output - reloads are the same, the macro `SECONDARY_RELOAD_CLASS' should be used - instead of defining both macros identically. - - The values returned by these macros are often `GENERAL_REGS'. Return - `NO_REGS' if no spare register is needed; i.e., if X can be directly copied - to or from a register of CLASS in MODE without requiring a scratch register. - Do not define this macro if it would always return `NO_REGS'. - - If a scratch register is required (either with or without an intermediate - register), you should define patterns for `reload_inM' or `reload_outM', as - required (*note Standard Names::.. These patterns, which will normally be - implemented with a `define_expand', should be similar to the `movM' - patterns, except that operand 2 is the scratch register. - - Define constraints for the reload register and scratch register that contain - a single register class. If the original reload register (whose class is - CLASS) can meet the constraint given in the pattern, the value returned by - these macros is used for the class of the scratch register. Otherwise, two - additional reload registers are required. Their classes are obtained from - the constraints in the insn pattern. - - X might be a pseudo-register or a `subreg' of a pseudo-register, which could - either be in a hard register or in memory. Use `true_regnum' to find out; - it will return -1 if the pseudo is in memory and the hard register number if - it is in a register. - - These macros should not be used in the case where a particular class of - registers can only be copied to memory and not to another class of - registers. In that case, secondary reload registers are not needed and - would not be helpful. Instead, a stack location must be used to perform the - copy and the `movM' pattern should use memory as a intermediate storage. - This case often occurs between floating-point and general registers. */ - -#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \ -((CLASS) == GPR_REGS ? NO_REGS \ - : (CLASS) == EVEN_REGS ? NO_REGS \ - : (CLASS) == ACCUM_REGS ? EVEN_REGS \ - : GPR_REGS) - -/* #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) */ -/* #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) */ - -/* 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 non-zero if objects of mode M 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. */ -/* #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, M) */ - -/* Normally when `SECONDARY_MEMORY_NEEDED' is defined, the compiler allocates a - stack slot for a memory location needed for register copies. If this macro - is defined, the compiler instead uses the memory location defined by this - macro. - - Do not define this macro if you do not define - `SECONDARY_MEMORY_NEEDED'. */ -/* #define SECONDARY_MEMORY_NEEDED_RTX(MODE) */ - -/* When the compiler needs a secondary memory location to copy between two - registers of mode MODE, it normally allocates sufficient memory to hold a - quantity of `BITS_PER_WORD' bits and performs the store and load operations - in a mode that many bits wide and whose class is the same as that of MODE. - - This is right thing to do on most machines because it ensures that all bits - of the register are copied and prevents accesses to the registers in a - narrower mode, which some machines prohibit for floating-point registers. - - However, this default behavior is not correct on some machines, such as the - DEC Alpha, that store short integers in floating-point registers differently - than in integer registers. On those machines, the default widening will not - work correctly and you must define this macro to suppress that widening in - some cases. See the file `alpha.h' for details. - - Do not define this macro if you do not define `SECONDARY_MEMORY_NEEDED' or - if widening MODE to a mode that is `BITS_PER_WORD' bits wide is correct for - your machine. */ -/* #define SECONDARY_MEMORY_NEEDED_MODE(MODE) */ - -/* Normally the compiler avoids choosing registers that have been explicitly - mentioned in the rtl as spill registers (these registers are normally those - used to pass parameters and return values). However, some machines have so - few registers of certain classes that there would not be enough registers to - use as spill registers if this were done. - - Define `SMALL_REGISTER_CLASSES' to be an expression with a non-zero value on - these machines. When this macro has a non-zero value, the compiler allows - registers explicitly used in the rtl to be used as spill registers but - avoids extending the lifetime of these registers. - - It is always safe to define this macro with a non-zero value, but if you - unnecessarily define it, you will reduce the amount of optimizations that - can be performed in some cases. If you do not define this macro with a - non-zero value when it is required, the compiler will run out of spill - registers and print a fatal error message. For most machines, you should - not define this macro at all. */ -/* #define SMALL_REGISTER_CLASSES */ - -/* A C expression whose value is nonzero if pseudos that have been assigned to - registers of class CLASS would likely be spilled because registers of CLASS - are needed for spill registers. - - The default value of this macro returns 1 if CLASS has exactly one register - and zero otherwise. On most machines, this default should be used. Only - define this macro to some other expression if pseudo allocated by - `local-alloc.c' end up in memory because their hard registers were needed - for spill registers. If this macro returns nonzero for those classes, those - pseudos will only be allocated by `global.c', which knows how to reallocate - the pseudo to another register. If there would not be another register - available for reallocation, you should not change the definition of this - macro since the only effect of such a definition would be to slow down - register allocation. */ -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - ((CLASS) != GPR_REGS && (CLASS) != EVEN_REGS) - -/* A C expression for the maximum number of consecutive registers of - class CLASS needed to hold a value of mode MODE. - - This is closely related to the macro `HARD_REGNO_NREGS'. In fact, the value - of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be the maximum value of - `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO values in the class CLASS. - - This macro helps control the handling of multiple-word values in - the reload pass. */ - -#define CLASS_MAX_NREGS(CLASS, MODE) \ -(((CLASS) == ACCUM_REGS) \ - ? ((GET_MODE_SIZE (MODE) + 8 - 1) / 8) \ - : ((GET_MODE_SIZE (MODE) + 4 - 1) / 4)) - -/* If defined, a C expression for a class that contains registers which the - compiler must always access in a mode that is the same size as the mode in - which it loaded the register. - - For the example, loading 32-bit integer or floating-point objects into - floating-point registers on the Alpha extends them to 64-bits. Therefore - loading a 64-bit object and then storing it as a 32-bit object does not - store the low-order 32-bits, as would be the case for a normal register. - Therefore, `alpha.h' defines this macro as `FLOAT_REGS'. */ -/* #define CLASS_CANNOT_CHANGE_SIZE */ - -/* A C expression that defines the machine-dependent operand constraint letters - (`I', `J', `K', .. 'P') that specify particular ranges of integer values. - If C is one of those letters, the expression should check that VALUE, an - integer, is in the appropriate range and return 1 if so, 0 otherwise. If C - is not one of those letters, the value should be 0 regardless of VALUE. */ -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'I' ? IN_RANGE_P (VALUE, -32, 31) \ - : (C) == 'J' ? IN_RANGE_P (VALUE, 0, 31) \ - : (C) == 'K' ? IN_RANGE_P (exact_log2 (VALUE), 0, 31) \ - : (C) == 'L' ? IN_RANGE_P (exact_log2 (~ (VALUE)), 0, 31) \ - : (C) == 'M' ? ((VALUE) == 32) \ - : (C) == 'N' ? ((VALUE) == 1) \ - : (C) == 'O' ? ((VALUE) == 0) \ - : (C) == 'P' ? IN_RANGE_P (VALUE, 32, 63) \ - : FALSE) - -/* A C expression that defines the machine-dependent operand constraint letters - (`G', `H') that specify particular ranges of `const_double' values. - - If C is one of those letters, the expression should check that VALUE, an RTX - of code `const_double', is in the appropriate range and return 1 if so, 0 - otherwise. If C is not one of those letters, the value should be 0 - regardless of VALUE. - - `const_double' is used for all floating-point constants and for `DImode' - fixed-point constants. A given letter can accept either or both kinds of - values. It can use `GET_MODE' to distinguish between these kinds. */ -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'G' ? (CONST_DOUBLE_LOW (VALUE) == 0 \ - && CONST_DOUBLE_HIGH (VALUE) == 0) \ - : (C) == 'H' ? FALSE \ - : FALSE) - -/* A C expression that defines the optional machine-dependent constraint - letters (`Q', `R', `S', `T', `U') that can be used to segregate specific - types of operands, usually memory references, for the target machine. - Normally this macro will not be defined. If it is required for a particular - target machine, it should return 1 if VALUE corresponds to the operand type - represented by the constraint letter C. If C is not defined as an extra - constraint, the value returned should be 0 regardless of VALUE. - - For example, on the ROMP, load instructions cannot have their output in r0 - if the memory reference contains a symbolic address. Constraint letter `Q' - is defined as representing a memory address that does *not* contain a - symbolic address. An alternative is specified with a `Q' constraint on the - input and `r' on the output. The next alternative specifies `m' on the - input and a register class that does not include r0 on the output. */ - -#define EXTRA_CONSTRAINT(VALUE, C) \ -(((C) == 'Q') ? short_memory_operand ((VALUE), GET_MODE (VALUE)) \ - : ((C) == 'R') ? single_reg_memory_operand ((VALUE), GET_MODE (VALUE)) \ - : ((C) == 'S') ? const_addr_memory_operand ((VALUE), GET_MODE (VALUE)) \ - : ((C) == 'T') ? long_memory_operand ((VALUE), GET_MODE (VALUE)) \ - : ((C) == 'U') ? FALSE \ - : FALSE) - - -/* Basic Stack Layout */ - -/* Stack layout */ - -/* Structure used to define the d30v stack */ -typedef struct d30v_stack { - int varargs_p; /* whether this is a varargs function */ - int varargs_size; /* size to hold varargs args passed in regs */ - int vars_size; /* variable save area size */ - int parm_size; /* outgoing parameter size */ - int gpr_size; /* size of saved GPR registers */ - int accum_size; /* size of saved ACCUM registers */ - int total_size; /* total bytes allocated for stack */ - /* which registers are to be saved */ - int save_offset; /* offset from new sp to start saving vars at */ - int link_offset; /* offset r62 is saved at */ - int memrefs_varargs; /* # of 2 word memory references for varargs */ - int memrefs_2words; /* # of 2 word memory references */ - int memrefs_1word; /* # of 1 word memory references */ - /* 1 for ldw/stw ops; 2 for ld2w/st2w ops */ - unsigned char save_p[FIRST_PSEUDO_REGISTER]; -} d30v_stack_t; - -/* Define this macro if pushing a word onto the stack moves the stack pointer - to a smaller address. - - When we say, "define this macro if ...," it means that the compiler checks - this macro only with `#ifdef' so the precise definition used does not - matter. */ -#define STACK_GROWS_DOWNWARD 1 - -/* 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 if successive arguments to a function occupy decreasing - addresses on the stack. */ -/* #define ARGS_GROW_DOWNWARD */ - -/* Offset from the frame pointer to the first local variable slot to be - allocated. - - If `FRAME_GROWS_DOWNWARD', find the next slot's offset by subtracting the - first slot's length from `STARTING_FRAME_OFFSET'. Otherwise, it is found by - adding the length of the first slot to the value `STARTING_FRAME_OFFSET'. */ - -#define STARTING_FRAME_OFFSET \ - (D30V_ALIGN (current_function_outgoing_args_size, \ - (STACK_BOUNDARY / BITS_PER_UNIT))) - -/* Offset from the stack pointer register to the first location at which - outgoing arguments are placed. If not specified, the default value of zero - is used. This is the proper value for most machines. - - If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first - location at which outgoing arguments are placed. */ -/* #define STACK_POINTER_OFFSET */ - -/* Offset from the argument pointer register to the first argument's address. - On some machines it may depend on the data type of the function. - - If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first - argument's address. */ -#define FIRST_PARM_OFFSET(FUNDECL) 0 - -/* Offset from the stack pointer register to an item dynamically allocated on - the stack, e.g., by `alloca'. - - The default value for this macro is `STACK_POINTER_OFFSET' plus the length - of the outgoing arguments. The default is correct for most machines. See - `function.c' for details. */ -/* #define STACK_DYNAMIC_OFFSET(FUNDECL) */ - -/* A C expression whose value is RTL representing the address in a stack frame - where the pointer to the caller's frame is stored. Assume that FRAMEADDR is - an RTL expression for the address of the stack frame itself. - - If you don't define this macro, the default is to return the value of - FRAMEADDR--that is, the stack frame address is also the address of the stack - word that points to the previous frame. */ -/* #define DYNAMIC_CHAIN_ADDRESS(FRAMEADDR) */ - -/* If defined, a C expression that produces the machine-specific code to setup - the stack so that arbitrary frames can be accessed. For example, on the - Sparc, we must flush all of the register windows to the stack before we can - access arbitrary stack frames. This macro will seldom need to be defined. */ -/* #define SETUP_FRAME_ADDRESSES() */ - -/* A C expression whose value is RTL representing the value of the return - address for the frame COUNT steps up from the current frame, after the - prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame - pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is - defined. - - The value of the expression must always be the correct address when COUNT is - zero, but may be `NULL_RTX' if there is not way to determine the return - address of other frames. */ - -/* ??? This definition fails for leaf functions. There is currently no - general solution for this problem. */ - -/* ??? There appears to be no way to get the return address of any previous - frame except by disassembling instructions in the prologue/epilogue. - So currently we support only the current frame. */ - -#define RETURN_ADDR_RTX(COUNT, FRAME) \ - ((COUNT) == 0 ? d30v_return_addr() : const0_rtx) - -/* Define this if the return address of a particular stack frame is - accessed from the frame pointer of the previous stack frame. */ -/* #define RETURN_ADDR_IN_PREVIOUS_FRAME */ - -/* A C expression whose value is RTL representing the location of the incoming - return address at the beginning of any function, before the prologue. This - RTL is either a `REG', indicating that the return value is saved in `REG', - or a `MEM' representing a location in the stack. - - You only need to define this macro if you want to support call frame - debugging information like that provided by DWARF 2. */ - -/* Before the prologue, RA lives in r62. */ -#define INCOMING_RETURN_ADDR_RTX gen_rtx (REG, Pmode, GPR_LINK) - -/* A C expression whose value is an integer giving the offset, in bytes, from - the value of the stack pointer register to the top of the stack frame at the - beginning of any function, before the prologue. The top of the frame is - defined to be the value of the stack pointer in the previous frame, just - before the call instruction. - - You only need to define this macro if you want to support call frame - debugging information like that provided by DWARF 2. */ -#define INCOMING_FRAME_SP_OFFSET 0 - -/* Initialize data used by insn expanders. This is called from insn_emit, - once for every function before code is generated. */ - -#define INIT_EXPANDERS d30v_init_expanders () -extern void d30v_init_expanders (); - -/* Stack Checking. */ - -/* A nonzero value if stack checking is done by the configuration files in a - machine-dependent manner. You should define this macro if stack checking is - require by the ABI of your machine or if you would like to have to stack - checking in some more efficient way than GNU CC's portable approach. The - default value of this macro is zero. */ -/* #define STACK_CHECK_BUILTIN */ - -/* An integer representing the interval at which GNU CC must generate stack - probe instructions. You will normally define this macro to be no larger - than the size of the "guard pages" at the end of a stack area. The default - value of 4096 is suitable for most systems. */ -/* #define STACK_CHECK_PROBE_INTERVAL */ - -/* A integer which is nonzero if GNU CC should perform the stack probe as a - load instruction and zero if GNU CC should use a store instruction. The - default is zero, which is the most efficient choice on most systems. */ -/* #define STACK_CHECK_PROBE_LOAD */ - -/* The number of bytes of stack needed to recover from a stack overflow, for - languages where such a recovery is supported. The default value of 75 words - should be adequate for most machines. */ -/* #define STACK_CHECK_PROTECT */ - -/* The maximum size of a stack frame, in bytes. GNU CC will generate probe - instructions in non-leaf functions to ensure at least this many bytes of - stack are available. If a stack frame is larger than this size, stack - checking will not be reliable and GNU CC will issue a warning. The default - is chosen so that GNU CC only generates one instruction on most systems. - You should normally not change the default value of this macro. */ -/* #define STACK_CHECK_MAX_FRAME_SIZE */ - -/* GNU CC uses this value to generate the above warning message. It represents - the amount of fixed frame used by a function, not including space for any - callee-saved registers, temporaries and user variables. You need only - specify an upper bound for this amount and will normally use the default of - four words. */ -/* #define STACK_CHECK_FIXED_FRAME_SIZE */ - -/* The maximum size, in bytes, of an object that GNU CC will place in the fixed - area of the stack frame when the user specifies `-fstack-check'. GNU CC - computed the default from the values of the above macros and you will - normally not need to override that default. */ -/* #define STACK_CHECK_MAX_VAR_SIZE */ - - -/* Register That Address the Stack Frame. */ - -/* The register number of the stack pointer register, which must also be a - fixed register according to `FIXED_REGISTERS'. On most machines, the - hardware determines which register this is. */ -#define STACK_POINTER_REGNUM GPR_SP - -/* The register number of the frame pointer register, which is used to access - automatic variables in the stack frame. On some machines, the hardware - determines which register this is. On other machines, you can choose any - register you wish for this purpose. */ -#define FRAME_POINTER_REGNUM GPR_FP - -/* On some machines the offset between the frame pointer and starting offset of - the automatic variables is not known until after register allocation has - been done (for example, because the saved registers are between these two - locations). On those machines, define `FRAME_POINTER_REGNUM' the number of - a special, fixed register to be used internally until the offset is known, - and define `HARD_FRAME_POINTER_REGNUM' to be actual the hard register number - used for the frame pointer. - - You should define this macro only in the very rare circumstances when it is - not possible to calculate the offset between the frame pointer and the - automatic variables until after register allocation has been completed. - When this macro is defined, you must also indicate in your definition of - `ELIMINABLE_REGS' how to eliminate `FRAME_POINTER_REGNUM' into either - `HARD_FRAME_POINTER_REGNUM' or `STACK_POINTER_REGNUM'. - - Do not define this macro if it would be the same as `FRAME_POINTER_REGNUM'. */ -/* #define HARD_FRAME_POINTER_REGNUM */ - -/* The register number of the arg pointer register, which is used to access the - function's argument list. On some machines, this is the same as the frame - pointer register. On some machines, the hardware determines which register - this is. On other machines, you can choose any register you wish for this - purpose. If this is not the same register as the frame pointer register, - then you must mark it as a fixed register according to `FIXED_REGISTERS', or - arrange to be able to eliminate it (*note Elimination::.). */ -/* #define ARG_POINTER_REGNUM */ - -/* The register number of the return address pointer register, which is used to - access the current function's return address from the stack. On some - machines, the return address is not at a fixed offset from the frame pointer - or stack pointer or argument pointer. This register can be defined to point - to the return address on the stack, and then be converted by - `ELIMINABLE_REGS' into either the frame pointer or stack pointer. - - Do not define this macro unless there is no other way to get the return - address from the stack. */ -/* #define RETURN_ADDRESS_POINTER_REGNUM */ - -/* Register numbers used for passing a function's static chain pointer. If - register windows are used, the register number as seen by the called - function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as - seen by the calling function is `STATIC_CHAIN_REGNUM'. If these registers - are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined. - - The static chain register need not be a fixed register. - - If the static chain is passed in memory, these macros should not be defined; - instead, the next two macros should be defined. */ - -#define STATIC_CHAIN_REGNUM (GPR_FIRST + 18) -/* #define STATIC_CHAIN_INCOMING_REGNUM */ - -/* If the static chain is passed in memory, these macros provide rtx giving - `mem' expressions that denote where they are stored. `STATIC_CHAIN' and - `STATIC_CHAIN_INCOMING' give the locations as seen by the calling and called - functions, respectively. Often the former will be at an offset from the - stack pointer and the latter at an offset from the frame pointer. - - The variables `stack_pointer_rtx', `frame_pointer_rtx', and - `arg_pointer_rtx' will have been initialized prior to the use of these - macros and should be used to refer to those items. - - If the static chain is passed in a register, the two previous - macros should be defined instead. */ -/* #define STATIC_CHAIN */ -/* #define STATIC_CHAIN_INCOMING */ - - -/* Eliminating the Frame Pointer and the Arg Pointer */ - -/* A C expression which is nonzero if a function must have and use a frame - pointer. This expression is evaluated in the reload pass. If its value is - nonzero the function will have a frame pointer. - - The expression can in principle examine the current function and decide - according to the facts, but on most machines the constant 0 or the constant - 1 suffices. Use 0 when the machine allows code to be generated with no - frame pointer, and doing so saves some time or space. Use 1 when there is - no possible advantage to avoiding a frame pointer. - - In certain cases, the compiler does not know how to produce valid code - without a frame pointer. The compiler recognizes those cases and - automatically gives the function a frame pointer regardless of what - `FRAME_POINTER_REQUIRED' says. You don't need to worry about them. - - In a function that does not require a frame pointer, the frame pointer - register can be allocated for ordinary usage, unless you mark it as a fixed - register. See `FIXED_REGISTERS' for more information. */ -#define FRAME_POINTER_REQUIRED 0 - -/* A C statement to store in the variable DEPTH-VAR the difference between the - frame pointer and the stack pointer values immediately after the function - prologue. The value would be computed from information such as the result - of `get_frame_size ()' and the tables of registers `regs_ever_live' and - `call_used_regs'. - - If `ELIMINABLE_REGS' is defined, this macro will be not be used and need not - be defined. Otherwise, it must be defined even if `FRAME_POINTER_REQUIRED' - is defined to always be true; in that case, you may set DEPTH-VAR to - anything. */ -/* #define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR) */ - -/* If defined, this macro specifies a table of register pairs used to eliminate - unneeded registers that point into the stack frame. If it is not defined, - the only elimination attempted by the compiler is to replace references to - the frame pointer with references to the stack pointer. - - The definition of this macro is a list of structure initializations, each of - which specifies an original and replacement register. - - On some machines, the position of the argument pointer is not known until - the compilation is completed. In such a case, a separate hard register must - be used for the argument pointer. This register can be eliminated by - replacing it with either the frame pointer or the argument pointer, - depending on whether or not the frame pointer has been eliminated. - - In this case, you might specify: - #define ELIMINABLE_REGS \ - {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} - - Note that the elimination of the argument pointer with the stack pointer is - specified first since that is the preferred elimination. */ -#define ELIMINABLE_REGS \ -{ \ - { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM } \ -} - -/* A C expression that returns non-zero if the compiler is allowed to try to - replace register number FROM-REG with register number TO-REG. This macro - need only be defined if `ELIMINABLE_REGS' is defined, and will usually be - the constant 1, since most of the cases preventing register elimination are - things that the compiler already knows about. */ - -#define CAN_ELIMINATE(FROM, TO) \ - ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \ - ? ! frame_pointer_needed \ - : 1) - -/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the - initial difference between the specified pair of registers. This macro must - be defined if `ELIMINABLE_REGS' is defined. */ - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ \ - d30v_stack_t *info = d30v_stack_info (); \ - \ - if ((FROM) == FRAME_POINTER_REGNUM) \ - (OFFSET) = 0; \ - else if ((FROM) == ARG_POINTER_REGNUM) \ - (OFFSET) = info->total_size; \ - else \ - abort (); \ -} - -/* Define this macro if the `longjmp' function restores registers from the - stack frames, rather than from those saved specifically by `setjmp'. - Certain quantities must not be kept in registers across a call to `setjmp' - on such machines. */ -/* #define LONGJMP_RESTORE_FROM_STACK */ - - -/* 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. */ -/* #define PROMOTE_PROTOTYPES */ - -/* A C expression that is the number of bytes actually pushed onto the stack - when an instruction attempts to push NPUSHED bytes. - - If the target machine does not have a push instruction, do not define this - macro. That directs GNU CC to use an alternate strategy: to allocate the - entire argument block and then store the arguments into it. - - On some machines, the definition - - #define PUSH_ROUNDING(BYTES) (BYTES) - - will suffice. But on other machines, instructions that appear to push one - byte actually push two bytes in an attempt to maintain alignment. Then the - definition should be - - #define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1) */ -/* #define PUSH_ROUNDING(NPUSHED) */ - -/* If defined, the maximum amount of space required for outgoing arguments will - be computed and placed into the variable - `current_function_outgoing_args_size'. No space will be pushed onto the - stack for each call; instead, the function prologue should increase the - stack frame size by this amount. - - Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not - proper. */ -#define ACCUMULATE_OUTGOING_ARGS - -/* Define this macro if functions should assume that stack space has been - allocated for arguments even when their values are passed in registers. - - The value of this macro is the size, in bytes, of the area reserved for - arguments passed in registers for the function represented by FNDECL. - - This space can be allocated by the caller, or be a part of the - machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says - which. */ -/* #define REG_PARM_STACK_SPACE(FNDECL) */ - -/* Define these macros in addition to the one above if functions might allocate - stack space for arguments even when their values are passed in registers. - These should be used when the stack space allocated for arguments in - registers is not a simple constant independent of the function declaration. - - The value of the first macro is the size, in bytes, of the area that we - should initially assume would be reserved for arguments passed in registers. - - The value of the second macro is the actual size, in bytes, of the area that - will be reserved for arguments passed in registers. This takes two - arguments: an integer representing the number of bytes of fixed sized - arguments on the stack, and a tree representing the number of bytes of - variable sized arguments on the stack. - - When these macros are defined, `REG_PARM_STACK_SPACE' will only be called - for libcall functions, the current function, or for a function being called - when it is known that such stack space must be allocated. In each case this - value can be easily computed. - - When deciding whether a called function needs such stack space, and how much - space to reserve, GNU CC uses these two macros instead of - `REG_PARM_STACK_SPACE'. */ -/* #define MAYBE_REG_PARM_STACK_SPACE */ -/* #define FINAL_REG_PARM_STACK_SPACE(CONST_SIZE, VAR_SIZE) */ - -/* 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 defined, this macro controls whether the - space for these arguments counts in the value of - `current_function_outgoing_args_size'. */ -/* #define OUTGOING_REG_PARM_STACK_SPACE */ - -/* Define this macro if `REG_PARM_STACK_SPACE' is defined, but the stack - parameters don't skip the area specified by it. - - Normally, when a parameter is not passed in registers, it is placed on the - stack beyond the `REG_PARM_STACK_SPACE' area. Defining this macro - suppresses this behavior and causes the parameter to be passed on the stack - in its natural location. */ -/* #define STACK_PARMS_IN_REG_PARM_AREA */ - -/* A C expression that should indicate the number of bytes of its own arguments - that a function pops on returning, or 0 if the function pops no arguments - and the caller must therefore pop them all after the function returns. - - FUNDECL is a C variable whose value is a tree node that describes the - function in question. Normally it is a node of type `FUNCTION_DECL' that - describes the declaration of the function. From this it is possible to - obtain the DECL_MACHINE_ATTRIBUTES of the function. - - FUNTYPE is a C variable whose value is a tree node that describes the - function in question. Normally it is a node of type `FUNCTION_TYPE' that - describes the data type of the function. From this it is possible to obtain - the data types of the value and arguments (if known). - - When a call to a library function is being considered, FUNTYPE will contain - an identifier node for the library function. Thus, if you need to - distinguish among various library functions, you can do so by their names. - Note that "library function" in this context means a function used to - perform arithmetic, whose name is known specially in the compiler and was - not mentioned in the C code being compiled. - - STACK-SIZE is the number of bytes of arguments passed on the stack. If a - variable number of bytes is passed, it is zero, and argument popping will - always be the responsibility of the calling function. - - On the Vax, all functions always pop their arguments, so the definition of - this macro is STACK-SIZE. On the 68000, using the standard calling - convention, no functions pop their arguments, so the value of the macro is - always 0 in this case. But an alternative calling convention is available - in which functions that take a fixed number of arguments pop them but other - functions (such as `printf') pop nothing (the caller pops all). When this - convention is in use, FUNTYPE is examined to determine whether a function - takes a fixed number of arguments. */ -#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 - - -/* Function Arguments in Registers */ - -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The arguments are CUM, which summarizes all the previous arguments; MODE, - the machine mode of the argument; TYPE, the data type of the argument as a - tree node or 0 if that is not known (which happens for C support library - functions); and NAMED, which is 1 for an ordinary argument and 0 for - nameless arguments that correspond to `...' in the called function's - prototype. - - The value of the expression should either be a `reg' RTX for the hard - register in which to pass the argument, or zero to pass the argument on the - stack. - - For machines like the Vax and 68000, where normally all arguments are - pushed, zero suffices as a definition. - - The usual way to make the ANSI library `stdarg.h' work on a machine where - some arguments are usually passed in registers, is to cause nameless - arguments to be passed on the stack instead. This is done by making - `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of - this macro to determine if this argument is of a type that must be passed in - the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' - returns non-zero for such an argument, the compiler will abort. If - `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the - stack and then loaded into a register. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - d30v_function_arg (&CUM, (int)MODE, TYPE, NAMED, FALSE) - -/* Define this macro if the target machine has "register windows", so that the - register in which a function sees an arguments is not necessarily the same - as the one in which the caller passed the argument. - - For such machines, `FUNCTION_ARG' computes the register in which the caller - passes the value, and `FUNCTION_INCOMING_ARG' should be defined in a similar - fashion to tell the function being called where the arguments will arrive. - - If `FUNCTION_INCOMING_ARG' is not defined, `FUNCTION_ARG' serves both - purposes. */ - -#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ - d30v_function_arg (&CUM, (int)MODE, TYPE, NAMED, TRUE) - -/* A C expression for the number of words, at the beginning of an argument, - must be put in registers. The value must be zero for arguments that are - passed entirely in registers or that are entirely pushed on the stack. - - On some machines, certain arguments must be passed partially in registers - and partially in memory. On these machines, typically the first N words of - arguments are passed in registers, and the rest on the stack. If a - multi-word argument (a `double' or a structure) crosses that boundary, its - first few words must be passed in registers and the rest must be pushed. - This macro tells the compiler when this occurs, and how many of the words - should go in registers. - - `FUNCTION_ARG' for these arguments should return the first register to be - used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for - the called function. */ -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ - d30v_function_arg_partial_nregs (&CUM, (int)MODE, TYPE, NAMED) - -/* A C expression that indicates when an argument must be passed by reference. - If nonzero for an argument, a copy of that argument is made in memory and a - pointer to the argument is passed instead of the argument itself. The - pointer is passed in whatever way is appropriate for passing a pointer to - that type. - - On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable - definition of this macro might be - #define FUNCTION_ARG_PASS_BY_REFERENCE\ - (CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) */ -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0 - -/* If defined, a C expression that indicates when it is more - desirable to keep an argument passed by invisible reference as a - reference, rather than copying it to a pseudo register. */ -/* #define FUNCTION_ARG_KEEP_AS_REFERENCE(CUM, MODE, TYPE, NAMED) */ - -/* If defined, a C expression that indicates when it is the called function's - responsibility to make a copy of arguments passed by invisible reference. - Normally, the caller makes a copy and passes the address of the copy to the - routine being called. When FUNCTION_ARG_CALLEE_COPIES is defined and is - nonzero, the caller does not make a copy. Instead, it passes a pointer to - the "live" value. The called function must not modify this value. If it - can be determined that the value won't be modified, it need not make a copy; - otherwise a copy must be made. */ -/* #define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) */ - -/* If defined, a C expression that indicates when it is more desirable to keep - an argument passed by invisible reference as a reference, rather than - copying it to a pseudo register. */ -/* #define FUNCTION_ARG_KEEP_AS_REFERENCE(CUM, MODE, TYPE, NAMED) */ - -/* A C type for declaring a variable that is used as the first argument of - `FUNCTION_ARG' and other related values. For some target machines, the type - `int' suffices and can hold the number of bytes of argument so far. - - There is no need to record in `CUMULATIVE_ARGS' anything about the arguments - that have been passed on the stack. The compiler has other variables to - keep track of that. For target machines on which all arguments are passed - on the stack, there is no need to store anything in `CUMULATIVE_ARGS'; - however, the data structure must exist and should not be empty, so use - `int'. */ -typedef int CUMULATIVE_ARGS; - -/* A C statement (sans semicolon) for initializing the variable CUM for the - state at the beginning of the argument list. The variable has type - `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node for the data type - of the function which will receive the args, or 0 if the args are to a - compiler support library function. The value of INDIRECT is nonzero when - processing an indirect call, for example a call through a function pointer. - The value of INDIRECT is zero for a call to an explicitly named function, a - library function call, or when `INIT_CUMULATIVE_ARGS' is used to find - arguments for the function being compiled. - - When processing a call to a compiler support library function, LIBNAME - identifies which one. It is a `symbol_ref' rtx which contains the name of - the function, as a string. LIBNAME is 0 when an ordinary C function call is - being processed. Thus, each time this macro is called, either LIBNAME or - FNTYPE is nonzero, but never both of them at once. */ - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ - d30v_init_cumulative_args (&CUM, FNTYPE, LIBNAME, INDIRECT, FALSE) - -/* Like `INIT_CUMULATIVE_ARGS' but overrides it for the purposes of finding the - arguments for the function being compiled. If this macro is undefined, - `INIT_CUMULATIVE_ARGS' is used instead. - - The value passed for LIBNAME is always 0, since library routines with - special calling conventions are never compiled with GNU CC. The argument - LIBNAME exists for symmetry with `INIT_CUMULATIVE_ARGS'. */ - -#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \ - d30v_init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE, TRUE) - -/* A C statement (sans semicolon) to update the summarizer variable CUM to - advance past an argument in the argument list. The values MODE, TYPE and - NAMED describe that argument. Once this is done, the variable CUM is - suitable for analyzing the *following* argument with `FUNCTION_ARG', etc. - - This macro need not do anything if the argument in question was passed on - the stack. The compiler knows how to track the amount of stack space used - for arguments without any special help. */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - d30v_function_arg_advance (&CUM, (int) MODE, TYPE, NAMED) - -/* If defined, a C expression which determines whether, and in which direction, - to pad out an argument with extra space. The value should be of type `enum - direction': either `upward' to pad above the argument, `downward' to pad - below, or `none' to inhibit padding. - - The *amount* of padding is always just enough to reach the next multiple of - `FUNCTION_ARG_BOUNDARY'; this macro does not control it. - - This macro has a default definition which is right for most systems. For - little-endian machines, the default is to pad upward. For big-endian - machines, the default is to pad downward for an argument of constant size - shorter than an `int', and upward otherwise. */ -/* #define FUNCTION_ARG_PADDING(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) \ - d30v_function_arg_boundary ((int) MODE, TYPE) - -/* A C expression that is nonzero if REGNO is the number of a hard register in - which function arguments are sometimes passed. This does *not* include - implicit arguments such as the static chain and the structure-value address. - On many machines, no registers can be used for this purpose since all - function arguments are pushed on the stack. */ - -#define FUNCTION_ARG_REGNO_P(REGNO) \ - IN_RANGE_P (REGNO, GPR_ARG_FIRST, GPR_ARG_LAST) - - -/* How Scalar Function Values are Returned */ - -/* Define this macro if `-traditional' should not cause functions declared to - return `float' to convert the value to `double'. */ /* #define - TRADITIONAL_RETURN_FLOAT */ - -/* A C expression to create an RTX representing the place where a function - returns a value of data type VALTYPE. VALTYPE is a tree node representing a - data type. Write `TYPE_MODE (VALTYPE)' to get the machine mode used to - represent that type. On many machines, only the mode is relevant. - (Actually, on most machines, scalar values are returned in the same place - regardless of mode). - - If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion - rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type. - - If the precise function being called is known, FUNC is a tree node - (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This makes it - possible to use a different value-returning convention for specific - functions when all their calls are known. - - `FUNCTION_VALUE' is not used for return vales with aggregate data types, - because these are returned in another way. See `STRUCT_VALUE_REGNUM' and - related macros, below. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), GPR_RET_VALUE) - -/* Define this macro if the target machine has "register windows" so that the - register in which a function returns its value is not the same as the one in - which the caller sees the value. - - For such machines, `FUNCTION_VALUE' computes the register in which the - caller will see the value. `FUNCTION_OUTGOING_VALUE' should be defined in a - similar fashion to tell the function where to put the value. - - If `FUNCTION_OUTGOING_VALUE' is not defined, `FUNCTION_VALUE' serves both - purposes. - - `FUNCTION_OUTGOING_VALUE' is not used for return vales with aggregate data - types, because these are returned in another way. See `STRUCT_VALUE_REGNUM' - and related macros, below. */ -/* #define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) */ - -/* A C expression to create an RTX representing the place where a library - function returns a value of mode MODE. If the precise function being called - is known, FUNC is a tree node (`FUNCTION_DECL') for it; otherwise, FUNC is a - null pointer. This makes it possible to use a different value-returning - convention for specific functions when all their calls are known. - - Note that "library function" in this context means a compiler support - routine, used to perform arithmetic, whose name is known specially by the - compiler and was not mentioned in the C code being compiled. - - The definition of `LIBRARY_VALUE' need not be concerned aggregate data - types, because none of the library functions returns such types. */ - -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, GPR_RET_VALUE) - -/* A C expression that is nonzero if REGNO is the number of a hard register in - which the values of called function may come back. - - A register whose use for returning values is limited to serving as the - second of a pair (for a value of type `double', say) need not be recognized - by this macro. So for most machines, this definition suffices: - - #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) - - If the machine has register windows, so that the caller and the called - function use different registers for the return value, this macro should - recognize only the caller's register numbers. */ - -#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == GPR_RET_VALUE) - -/* Define this macro if `untyped_call' and `untyped_return' need more space - than is implied by `FUNCTION_VALUE_REGNO_P' for saving and restoring an - arbitrary return value. */ -/* #define APPLY_RESULT_SIZE */ - - -/* How Large Values are Returned */ - -/* A C expression which can inhibit the returning of certain function values in - registers, based on the type of value. A nonzero value says to return the - function value in memory, just as large structures are always returned. - Here TYPE will be a C expression of type `tree', representing the data type - of the value. - - Note that values of mode `BLKmode' must be explicitly handled by this macro. - Also, the option `-fpcc-struct-return' takes effect regardless of this - macro. On most systems, it is possible to leave the macro undefined; this - causes a default definition to be used, whose value is the constant 1 for - `BLKmode' values, and 0 otherwise. - - Do not use this macro to indicate that structures and unions should always - be returned in memory. You should instead use `DEFAULT_PCC_STRUCT_RETURN' - to indicate this. */ -/* #define RETURN_IN_MEMORY(TYPE) */ - -/* Define this macro to be 1 if all structure and union return values must be - in memory. Since this results in slower code, this should be defined only - if needed for compatibility with other compilers or with an ABI. 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. - - If not defined, this defaults to the value 1. */ -/* #define DEFAULT_PCC_STRUCT_RETURN */ - -/* If the structure value address is passed in a register, then - `STRUCT_VALUE_REGNUM' should be the number of that register. */ - -#define STRUCT_VALUE_REGNUM GPR_ARG_FIRST - -/* If the structure value address is not passed in a register, define - `STRUCT_VALUE' as an expression returning an RTX for the place where the - address is passed. If it returns 0, the address is passed as an "invisible" - first argument. */ - -#define STRUCT_VALUE 0 - -/* On some architectures the place where the structure value address is found - by the called function is not the same place that the caller put it. This - can be due to register windows, or it could be because the function prologue - moves it to a different place. - - If the incoming location of the structure value address is in a register, - define this macro as the register number. */ -/* #define STRUCT_VALUE_INCOMING_REGNUM */ - -/* If the incoming location is not a register, then you should define - `STRUCT_VALUE_INCOMING' as an expression for an RTX for where the called - function should find the value. If it should find the value on the stack, - define this to create a `mem' which refers to the frame pointer. A - definition of 0 means that the address is passed as an "invisible" first - argument. */ -/* #define STRUCT_VALUE_INCOMING */ - -/* Define this macro if the usual system convention on the target machine for - returning structures and unions is for the called function to return the - address of a static variable containing the value. - - Do not define this if the usual system convention is for the caller to pass - an address to the subroutine. - - This macro has effect in `-fpcc-struct-return' mode, but it does nothing - when you use `-freg-struct-return' mode. */ -/* #define PCC_STATIC_STRUCT_RETURN */ - - -/* Caller-Saves Register Allocation */ - -/* Define this macro if function calls on the target machine do not preserve - any registers; in other words, if `CALL_USED_REGISTERS' has 1 for all - registers. This macro enables `-fcaller-saves' by default. Eventually that - option will be enabled by default on all machines and both the option and - this macro will be eliminated. */ -/* #define DEFAULT_CALLER_SAVES */ - -/* A C expression to determine whether it is worthwhile to consider placing a - pseudo-register in a call-clobbered hard register and saving and restoring - it around each function call. The expression should be 1 when this is worth - doing, and 0 otherwise. - - If you don't define this macro, a default is used which is good on most - machines: `4 * CALLS < REFS'. */ -/* #define CALLER_SAVE_PROFITABLE(REFS, CALLS) */ - - -/* Function Entry and Exit */ - -/* A C compound statement that outputs the assembler code for entry to a - function. The prologue is responsible for setting up the stack frame, - initializing the frame pointer register, saving registers that must be - saved, and allocating SIZE additional bytes of storage for the local - variables. SIZE is an integer. FILE is a stdio stream to which the - assembler code should be output. - - The label for the beginning of the function need not be output by this - macro. That has already been done when the macro is run. - - To determine which registers to save, the macro can refer to the array - `regs_ever_live': element R is nonzero if hard register R is used anywhere - within the function. This implies the function prologue should save - register R, provided it is not one of the call-used registers. - (`FUNCTION_EPILOGUE' must likewise use `regs_ever_live'.) - - On machines that have "register windows", the function entry code does not - save on the stack the registers that are in the windows, even if they are - supposed to be preserved by function calls; instead it takes appropriate - steps to "push" the register stack, if any non-call-used registers are used - in the function. - - On machines where functions may or may not have frame-pointers, the function - entry code must vary accordingly; it must set up the frame pointer if one is - wanted, and not otherwise. To determine whether a frame pointer is in - wanted, the macro can refer to the variable `frame_pointer_needed'. The - variable's value will be 1 at run time in a function that needs a frame - pointer. *Note Elimination::. - - The function entry code is responsible for allocating any stack space - required for the function. This stack space consists of the regions listed - below. In most cases, these regions are allocated in the order listed, with - the last listed region closest to the top of the stack (the lowest address - if `STACK_GROWS_DOWNWARD' is defined, and the highest address if it is not - defined). You can use a different order for a machine if doing so is more - convenient or required for compatibility reasons. Except in cases where - required by standard or by a debugger, there is no reason why the stack - layout used by GCC need agree with that used by other compilers for a - machine. - - * A region of `current_function_pretend_args_size' bytes of - uninitialized space just underneath the first argument - arriving on the stack. (This may not be at the very start of - the allocated stack region if the calling sequence has pushed - anything else since pushing the stack arguments. But - usually, on such machines, nothing else has been pushed yet, - because the function prologue itself does all the pushing.) - This region is used on machines where an argument may be - passed partly in registers and partly in memory, and, in some - cases to support the features in `varargs.h' and `stdargs.h'. - - * An area of memory used to save certain registers used by the - function. The size of this area, which may also include - space for such things as the return address and pointers to - previous stack frames, is machine-specific and usually - depends on which registers have been used in the function. - Machines with register windows often do not require a save - area. - - * A region of at least SIZE bytes, possibly rounded up to an - allocation boundary, to contain the local variables of the - function. On some machines, this region and the save area - may occur in the opposite order, with the save area closer to - the top of the stack. - - * Optionally, when `ACCUMULATE_OUTGOING_ARGS' is defined, a - region of `current_function_outgoing_args_size' bytes to be - used for outgoing argument lists of the function. *Note - Stack Arguments::. - - Normally, it is necessary for the macros `FUNCTION_PROLOGUE' and - `FUNCTION_EPILOGUE' to treat leaf functions specially. The C variable - `leaf_function' is nonzero for such a function. */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) d30v_function_prologue (FILE, SIZE) - -/* Define this macro as a C expression that is nonzero if the return - instruction or the function epilogue ignores the value of the stack pointer; - in other words, if it is safe to delete an instruction to adjust the stack - pointer before a return from the function. - - Note that this macro's value is relevant only for functions for which frame - pointers are maintained. It is never safe to delete a final stack - adjustment in a function that has no frame pointer, and the compiler knows - this regardless of `EXIT_IGNORE_STACK'. */ -/* #define EXIT_IGNORE_STACK */ - -/* Define this macro as a C expression that is nonzero for registers - are used by the epilogue or the `return' pattern. The stack and - frame pointer registers are already be assumed to be used as - needed. */ -/* #define EPILOGUE_USES(REGNO) */ - -/* A C compound statement that outputs the assembler code for exit from a - function. The epilogue is responsible for restoring the saved registers and - stack pointer to their values when the function was called, and returning - control to the caller. This macro takes the same arguments as the macro - `FUNCTION_PROLOGUE', and the registers to restore are determined from - `regs_ever_live' and `CALL_USED_REGISTERS' in the same way. - - On some machines, there is a single instruction that does all the work of - returning from the function. On these machines, give that instruction the - name `return' and do not define the macro `FUNCTION_EPILOGUE' at all. - - Do not define a pattern named `return' if you want the `FUNCTION_EPILOGUE' - to be used. If you want the target switches to control whether return - instructions or epilogues are used, define a `return' pattern with a - validity condition that tests the target switches appropriately. If the - `return' pattern's validity condition is false, epilogues will be used. - - On machines where functions may or may not have frame-pointers, the function - exit code must vary accordingly. Sometimes the code for these two cases is - completely different. To determine whether a frame pointer is wanted, the - macro can refer to the variable `frame_pointer_needed'. The variable's - value will be 1 when compiling a function that needs a frame pointer. - - Normally, `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' must treat leaf - functions specially. The C variable `leaf_function' is nonzero for such a - function. *Note Leaf Functions::. - - On some machines, some functions pop their arguments on exit while others - leave that for the caller to do. For example, the 68020 when given `-mrtd' - pops arguments in functions that take a fixed number of arguments. - - Your definition of the macro `RETURN_POPS_ARGS' decides which functions pop - their own arguments. `FUNCTION_EPILOGUE' needs to know what was decided. - The variable that is called `current_function_pops_args' is the number of - bytes of its arguments that a function should pop. *Note Scalar Return::. */ - -#define FUNCTION_EPILOGUE(FILE, SIZE) d30v_function_epilogue (FILE, SIZE) - -/* Define this macro if the function epilogue contains delay slots to which - instructions from the rest of the function can be "moved". The definition - should be a C expression whose value is an integer representing the number - of delay slots there. */ -/* #define DELAY_SLOTS_FOR_EPILOGUE */ - -/* A C expression that returns 1 if INSN can be placed in delay slot number N - of the epilogue. - - The argument N is an integer which identifies the delay slot now being - considered (since different slots may have different rules of eligibility). - It is never negative and is always less than the number of epilogue delay - slots (what `DELAY_SLOTS_FOR_EPILOGUE' returns). If you reject a particular - insn for a given delay slot, in principle, it may be reconsidered for a - subsequent delay slot. Also, other insns may (at least in principle) be - considered for the so far unfilled delay slot. - - The insns accepted to fill the epilogue delay slots are put in an - RTL list made with `insn_list' objects, stored in the variable - `current_function_epilogue_delay_list'. The insn for the first - delay slot comes first in the list. Your definition of the macro - `FUNCTION_EPILOGUE' should fill the delay slots by outputting the - insns in this list, usually by calling `final_scan_insn'. - - You need not define this macro if you did not define - `DELAY_SLOTS_FOR_EPILOGUE'. */ -/* #define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN, N) */ - -/* A C compound statement that outputs the assembler code for a thunk function, - used to implement C++ virtual function calls with multiple inheritance. The - thunk acts as a wrapper around a virtual function, adjusting the implicit - object parameter before handing control off to the real function. - - First, emit code to add the integer DELTA to the location that contains the - incoming first argument. Assume that this argument contains a pointer, and - is the one used to pass the `this' pointer in C++. This is the incoming - argument *before* the function prologue, e.g. `%o0' on a sparc. The - addition must preserve the values of all other incoming arguments. - - After the addition, emit code to jump to FUNCTION, which is a - `FUNCTION_DECL'. This is a direct pure jump, not a call, and does not touch - the return address. Hence returning from FUNCTION will return to whoever - called the current `thunk'. - - The effect must be as if FUNCTION had been called directly with the adjusted - first argument. This macro is responsible for emitting all of the code for - a thunk function; `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' are not - invoked. - - The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already been - extracted from it.) It might possibly be useful on some targets, but - probably not. - - If you do not define this macro, the target-independent code in the C++ - frontend will generate a less efficient heavyweight thunk that calls - FUNCTION instead of jumping to it. The generic approach does not support - varargs. */ -/* #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) */ - - -/* Generating Code for Profiling. */ - -/* A C statement or compound statement to output to FILE some assembler code to - call the profiling subroutine `mcount'. Before calling, the assembler code - must load the address of a counter variable into a register where `mcount' - expects to find the address. The name of this variable is `LP' followed by - the number LABELNO, so you would generate the name using `LP%d' in a - `fprintf'. - - The details of how the address should be passed to `mcount' are determined - by your operating system environment, not by GNU CC. To figure them out, - compile a small program for profiling using the system's installed C - compiler and look at the assembler code that results. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) d30v_function_profiler (FILE, LABELNO) - -/* 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 */ - -/* A C statement or compound statement to output to FILE some assembler code to - initialize basic-block profiling for the current object module. The global - compile flag `profile_block_flag' distingishes two profile modes. - - profile_block_flag != 2' - Output code to call the subroutine `__bb_init_func' once per - object module, passing it as its sole argument the address of - a block allocated in the object module. - - The name of the block is a local symbol made with this - statement: - - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); - - Of course, since you are writing the definition of - `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, - you can take a short cut in the definition of this macro and - use the name that you know will result. - - The first word of this block is a flag which will be nonzero - if the object module has already been initialized. So test - this word first, and do not call `__bb_init_func' if the flag - is nonzero. BLOCK_OR_LABEL contains a unique number which - may be used to generate a label as a branch destination when - `__bb_init_func' will not be called. - - Described in assembler language, the code to be output looks - like: - - cmp (LPBX0),0 - bne local_label - parameter1 <- LPBX0 - call __bb_init_func - local_label: - - profile_block_flag == 2' - Output code to call the subroutine `__bb_init_trace_func' and - pass two parameters to it. The first parameter is the same as - for `__bb_init_func'. The second parameter is the number of - the first basic block of the function as given by - BLOCK_OR_LABEL. Note that `__bb_init_trace_func' has to be - called, even if the object module has been initialized - already. - - Described in assembler language, the code to be output looks - like: - parameter1 <- LPBX0 - parameter2 <- BLOCK_OR_LABEL - call __bb_init_trace_func */ -/* #define FUNCTION_BLOCK_PROFILER (FILE, LABELNO) */ - -/* A C statement or compound statement to output to FILE some assembler code to - increment the count associated with the basic block number BLOCKNO. The - global compile flag `profile_block_flag' distingishes two profile modes. - - profile_block_flag != 2' - Output code to increment the counter directly. Basic blocks - are numbered separately from zero within each compilation. - The count associated with block number BLOCKNO is at index - BLOCKNO in a vector of words; the name of this array is a - local symbol made with this statement: - - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2); - - Of course, since you are writing the definition of - `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, - you can take a short cut in the definition of this macro and - use the name that you know will result. - - Described in assembler language, the code to be output looks - like: - - inc (LPBX2+4*BLOCKNO) - - profile_block_flag == 2' - Output code to initialize the global structure `__bb' and - call the function `__bb_trace_func', which will increment the - counter. - - `__bb' consists of two words. In the first word, the current - basic block number, as given by BLOCKNO, has to be stored. In - the second word, the address of a block allocated in the - object module has to be stored. The address is given by the - label created with this statement: - - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); - - Described in assembler language, the code to be output looks - like: - move BLOCKNO -> (__bb) - move LPBX0 -> (__bb+4) - call __bb_trace_func */ -/* #define BLOCK_PROFILER(FILE, BLOCKNO) */ - -/* A C statement or compound statement to output to FILE assembler - code to call function `__bb_trace_ret'. The assembler code should - only be output if the global compile flag `profile_block_flag' == - 2. This macro has to be used at every place where code for - returning from a function is generated (e.g. `FUNCTION_EPILOGUE'). - Although you have to write the definition of `FUNCTION_EPILOGUE' - as well, you have to define this macro to tell the compiler, that - the proper call to `__bb_trace_ret' is produced. */ -/* #define FUNCTION_BLOCK_PROFILER_EXIT(FILE) */ - -/* A C statement or compound statement to save all registers, which may be - clobbered by a function call, including condition codes. The `asm' - statement will be mostly likely needed to handle this task. Local labels in - the assembler code can be concatenated with the string ID, to obtain a - unique lable name. - - Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or - `FUNCTION_EPILOGUE' must be saved in the macros `FUNCTION_BLOCK_PROFILER', - `FUNCTION_BLOCK_PROFILER_EXIT' and `BLOCK_PROFILER' prior calling - `__bb_init_trace_func', `__bb_trace_ret' and `__bb_trace_func' respectively. */ -/* #define MACHINE_STATE_SAVE(ID) */ - -/* A C statement or compound statement to restore all registers, including - condition codes, saved by `MACHINE_STATE_SAVE'. - - Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or - `FUNCTION_EPILOGUE' must be restored in the macros - `FUNCTION_BLOCK_PROFILER', `FUNCTION_BLOCK_PROFILER_EXIT' and - `BLOCK_PROFILER' after calling `__bb_init_trace_func', `__bb_trace_ret' and - `__bb_trace_func' respectively. */ -/* #define MACHINE_STATE_RESTORE(ID) */ - -/* A C function or functions which are needed in the library to support block - profiling. */ -/* #define BLOCK_PROFILER_CODE */ - - -/* Implementing the Varargs Macros. */ - -/* If defined, is a C expression that produces the machine-specific code for a - call to `__builtin_saveregs'. This code will be moved to the very beginning - of the function, before any parameter access are made. The return value of - this function should be an RTX that contains the value to use as the return - of `__builtin_saveregs'. - - The argument ARGS is a `tree_list' containing the arguments that were passed - to `__builtin_saveregs'. - - If this macro is not defined, the compiler will output an ordinary call to - the library function `__builtin_saveregs'. */ - -#define EXPAND_BUILTIN_SAVEREGS(ARGS) d30v_expand_builtin_saveregs (ARGS) - -/* This macro offers an alternative to using `__builtin_saveregs' and defining - the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register - arguments into the stack so that all the arguments appear to have been - passed consecutively on the stack. Once this is done, you can use the - standard implementation of varargs that works for machines that pass all - their arguments on the stack. - - The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, containing - the values that obtain after processing of the named arguments. The - arguments MODE and TYPE describe the last named argument--its machine mode - and its data type as a tree node. - - The macro implementation should do two things: first, push onto the stack - all the argument registers *not* used for the named arguments, and second, - store the size of the data thus pushed into the `int'-valued variable whose - name is supplied as the argument PRETEND_ARGS_SIZE. The value that you - store here will serve as additional offset for setting up the stack frame. - - Because you must generate code to push the anonymous arguments at compile - time without knowing their data types, `SETUP_INCOMING_VARARGS' is only - useful on machines that have just a single category of argument register and - use it uniformly for all data types. - - If the argument SECOND_TIME is nonzero, it means that the arguments of the - function are being analyzed for the second time. This happens for an inline - function, which is not actually compiled until the end of the source file. - The macro `SETUP_INCOMING_VARARGS' should not generate any instructions in - this case. */ - -#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_ARGS_SIZE, SECOND_TIME) \ - d30v_setup_incoming_varargs (&ARGS_SO_FAR, (int) MODE, TYPE, \ - &PRETEND_ARGS_SIZE, SECOND_TIME) - -/* 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. */ -/* #define STRICT_ARGUMENT_NAMING */ - - -/* Trampolines for Nested Functions. */ - -/* 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(FILE) d30v_trampoline_template (FILE) */ - -/* The name of a subroutine to switch to the section in which the trampoline - template is to be placed (*note Sections::.). The default is a value of - `readonly_data_section', which places the trampoline in the section - containing read-only data. */ -/* #define TRAMPOLINE_SECTION */ - -/* A C expression for the size in bytes of the trampoline, as an integer. */ -#define TRAMPOLINE_SIZE (d30v_trampoline_size ()) - -/* Alignment required for trampolines, in bits. - - If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for - aligning trampolines. */ -#define TRAMPOLINE_ALIGNMENT 64 - -/* A C statement to initialize the variable parts of a trampoline. ADDR is an - RTX for the address of the trampoline; FNADDR is an RTX for the address of - the nested function; STATIC_CHAIN is an RTX for the static chain value that - should be passed to the function when it is called. */ -#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \ - d30v_initialize_trampoline (ADDR, FNADDR, STATIC_CHAIN) - -/* A C expression to allocate run-time space for a trampoline. The expression - value should be an RTX representing a memory reference to the space for the - trampoline. - - If this macro is not defined, by default the trampoline is allocated as a - stack slot. This default is right for most machines. The exceptions are - machines where it is impossible to execute instructions in the stack area. - On such machines, you may have to implement a separate stack, using this - macro in conjunction with `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE'. - - FP points to a data structure, a `struct function', which describes the - compilation status of the immediate containing function of the function - which the trampoline is for. Normally (when `ALLOCATE_TRAMPOLINE' is not - defined), the stack slot for the trampoline is in the stack frame of this - containing function. Other allocation strategies probably must do something - analogous with this information. */ -/* #define ALLOCATE_TRAMPOLINE(FP) */ - -/* Implementing trampolines is difficult on many machines because they have - separate instruction and data caches. Writing into a stack location fails - to clear the memory in the instruction cache, so when the program jumps to - that location, it executes the old contents. - - Here are two possible solutions. One is to clear the relevant parts of the - instruction cache whenever a trampoline is set up. The other is to make all - trampolines identical, by having them jump to a standard subroutine. The - former technique makes trampoline execution faster; the latter makes - initialization faster. - - To clear the instruction cache when a trampoline is initialized, define the - following macros which describe the shape of the cache. */ - -/* The total size in bytes of the cache. */ -/* #define INSN_CACHE_SIZE */ - -/* The length in bytes of each cache line. The cache is divided into cache - lines which are disjoint slots, each holding a contiguous chunk of data - fetched from memory. Each time data is brought into the cache, an entire - line is read at once. The data loaded into a cache line is always aligned - on a boundary equal to the line size. */ -/* #define INSN_CACHE_LINE_WIDTH */ - -/* The number of alternative cache lines that can hold any particular memory - location. */ -/* #define INSN_CACHE_DEPTH */ - -/* Alternatively, if the machine has system calls or instructions to clear the - instruction cache directly, you can define the following macro. */ - -/* If defined, expands to a C expression clearing the *instruction cache* in - the specified interval. If it is not defined, and the macro INSN_CACHE_SIZE - is defined, some generic code is generated to clear the cache. The - definition of this macro would typically be a series of `asm' statements. - Both BEG and END are both pointer expressions. */ -/* #define CLEAR_INSN_CACHE (BEG, END) */ - -/* To use a standard subroutine, define the following macro. In addition, you - must make sure that the instructions in a trampoline fill an entire cache - line with identical instructions, or else ensure that the beginning of the - trampoline code is always aligned at the same point in its cache line. Look - in `m68k.h' as a guide. */ - -/* Define this macro if trampolines need a special subroutine to do their work. - The macro should expand to a series of `asm' statements which will be - compiled with GNU CC. They go in a library function named - `__transfer_from_trampoline'. - - If you need to avoid executing the ordinary prologue code of a compiled C - function when you jump to the subroutine, you can do so by placing a special - label of your own in the assembler code. Use one `asm' statement to - generate an assembler label, and another to make the label global. Then - trampolines can use that label to jump directly to your special assembler - code. */ -/* #define TRANSFER_FROM_TRAMPOLINE */ - - -/* Implicit Calls to Library Routines */ - -/* A C string constant giving the name of the function to call for - multiplication of one signed full-word by another. If you do not define - this macro, the default name is used, which is `__mulsi3', a function - defined in `libgcc.a'. */ -/* #define MULSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for division of - one signed full-word by another. If you do not define this macro, the - default name is used, which is `__divsi3', a function defined in `libgcc.a'. */ -/* #define DIVSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for division of - one unsigned full-word by another. If you do not define this macro, the - default name is used, which is `__udivsi3', a function defined in - `libgcc.a'. */ -/* #define UDIVSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for the - remainder in division of one signed full-word by another. If you do not - define this macro, the default name is used, which is `__modsi3', a function - defined in `libgcc.a'. */ -/* #define MODSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for the - remainder in division of one unsigned full-word by another. If you do not - define this macro, the default name is used, which is `__umodsi3', a - function defined in `libgcc.a'. */ -/* #define UMODSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for - multiplication of one signed double-word by another. If you do not define - this macro, the default name is used, which is `__muldi3', a function - defined in `libgcc.a'. */ -/* #define MULDI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for division of - one signed double-word by another. If you do not define this macro, the - default name is used, which is `__divdi3', a function defined in `libgcc.a'. */ -/* #define DIVDI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for division of - one unsigned full-word by another. If you do not define this macro, the - default name is used, which is `__udivdi3', a function defined in - `libgcc.a'. */ -/* #define UDIVDI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for the - remainder in division of one signed double-word by another. If you do not - define this macro, the default name is used, which is `__moddi3', a function - defined in `libgcc.a'. */ -/* #define MODDI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for the - remainder in division of one unsigned full-word by another. If you do not - define this macro, the default name is used, which is `__umoddi3', a - function defined in `libgcc.a'. */ -/* #define UMODDI3_LIBCALL */ - -/* Define this macro as a C statement that declares additional library routines - renames existing ones. `init_optabs' calls this macro after initializing all - the normal library routines. */ -/* #define INIT_TARGET_OPTABS */ - -/* The value of `EDOM' on the target machine, as a C integer constant - expression. If you don't define this macro, GNU CC does not attempt to - deposit the value of `EDOM' into `errno' directly. Look in - `/usr/include/errno.h' to find the value of `EDOM' on your system. - - If you do not define `TARGET_EDOM', then compiled code reports domain errors - by calling the library function and letting it report the error. If - mathematical functions on your system use `matherr' when there is an error, - then you should leave `TARGET_EDOM' undefined so that `matherr' is used - normally. */ -/* #define TARGET_EDOM */ - -/* Define this macro as a C expression to create an rtl expression that refers - to the global "variable" `errno'. (On certain systems, `errno' may not - actually be a variable.) If you don't define this macro, a reasonable - default is used. */ -/* #define GEN_ERRNO_RTX */ - -/* Define this macro if GNU CC should generate calls to the System V (and ANSI - C) library functions `memcpy' and `memset' rather than the BSD functions - `bcopy' and `bzero'. - - Defined in svr4.h. */ -/* #define TARGET_MEM_FUNCTIONS */ - -/* Define this macro if only `float' arguments cannot be passed to library - routines (so they must be converted to `double'). This macro affects both - how library calls are generated and how the library routines in `libgcc1.c' - accept their arguments. It is useful on machines where floating and fixed - point arguments are passed differently, such as the i860. */ -/* #define LIBGCC_NEEDS_DOUBLE */ - -/* Define this macro to override the type used by the library routines to pick - up arguments of type `float'. (By default, they use a union of `float' and - `int'.) - - The obvious choice would be `float'--but that won't work with traditional C - compilers that expect all arguments declared as `float' to arrive as - `double'. To avoid this conversion, the library routines ask for the value - as some other type and then treat it as a `float'. - - On some systems, no other type will work for this. For these systems, you - must use `LIBGCC_NEEDS_DOUBLE' instead, to force conversion of the values - `double' before they are passed. */ -/* #define FLOAT_ARG_TYPE */ - -/* Define this macro to override the way library routines redesignate a `float' - argument as a `float' instead of the type it was passed as. The default is - an expression which takes the `float' field of the union. */ -/* #define FLOATIFY(PASSED_VALUE) */ - -/* Define this macro to override the type used by the library routines to - return values that ought to have type `float'. (By default, they use - `int'.) - - The obvious choice would be `float'--but that won't work with traditional C - compilers gratuitously convert values declared as `float' into `double'. */ -/* #define FLOAT_VALUE_TYPE */ - -/* Define this macro to override the way the value of a `float'-returning - library routine should be packaged in order to return it. These functions - are actually declared to return type `FLOAT_VALUE_TYPE' (normally `int'). - - These values can't be returned as type `float' because traditional C - compilers would gratuitously convert the value to a `double'. - - A local variable named `intify' is always available when the macro `INTIFY' - is used. It is a union of a `float' field named `f' and a field named `i' - whose type is `FLOAT_VALUE_TYPE' or `int'. - - If you don't define this macro, the default definition works by copying the - value through that union. */ -/* #define INTIFY(FLOAT_VALUE) */ - -/* Define this macro as the name of the data type corresponding to `SImode' in - the system's own C compiler. - - You need not define this macro if that type is `long int', as it usually is. */ -/* #define nongcc_SI_type */ - -/* Define this macro as the name of the data type corresponding to the - word_mode in the system's own C compiler. - - You need not define this macro if that type is `long int', as it usually is. */ -/* #define nongcc_word_type */ - -/* Define these macros to supply explicit C statements to carry out various - arithmetic operations on types `float' and `double' in the library routines - in `libgcc1.c'. See that file for a full list of these macros and their - arguments. - - On most machines, you don't need to define any of these macros, because the - C compiler that comes with the system takes care of doing them. */ -/* #define perform_... */ - -/* Define this macro to generate code for Objective C message sending using the - calling convention of the NeXT system. This calling convention involves - passing the object, the selector and the method arguments all at once to the - method-lookup library function. - - The default calling convention passes just the object and the selector to - the lookup function, which returns a pointer to the method. */ -/* #define NEXT_OBJC_RUNTIME */ - - -/* Addressing Modes */ - -/* Define this macro if the machine supports post-increment addressing. */ -#define HAVE_POST_INCREMENT 1 - -/* Similar for other kinds of addressing. */ -/* #define HAVE_PRE_INCREMENT 0 */ -#define HAVE_POST_DECREMENT 1 -/* #define HAVE_PRE_DECREMENT 0 */ - -/* A C expression that is 1 if the RTX X is a constant which is a valid - address. On most machines, this can be defined as `CONSTANT_P (X)', but a - few machines are more restrictive in which constant addresses are supported. - - `CONSTANT_P' accepts integer-values expressions whose values are not - explicitly known, such as `symbol_ref', `label_ref', and `high' expressions - and `const' arithmetic expressions, in addition to `const_int' and - `const_double' expressions. */ -#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) - -/* A number, the maximum number of registers that can appear in a valid memory - address. Note that it is up to you to specify a value equal to the maximum - number that `GO_IF_LEGITIMATE_ADDRESS' would ever accept. */ -#define MAX_REGS_PER_ADDRESS 2 - -/* A C compound statement with a conditional `goto LABEL;' executed if X (an - RTX) is a legitimate memory address on the target machine for a memory - operand of mode MODE. - - It usually pays to define several simpler macros to serve as subroutines for - this one. Otherwise it may be too complicated to understand. - - This macro must exist in two variants: a strict variant and a non-strict - one. The strict variant is used in the reload pass. It must be defined so - that any pseudo-register that has not been allocated a hard register is - considered a memory reference. In contexts where some kind of register is - required, a pseudo-register with no hard register must be rejected. - - The non-strict variant is used in other passes. It must be defined to - accept all pseudo-registers in every context where some kind of register is - required. - - Compiler source files that want to use the strict variant of this macro - define the macro `REG_OK_STRICT'. You should use an `#ifdef REG_OK_STRICT' - conditional to define the strict variant in that case and the non-strict - variant otherwise. - - Subroutines to check for acceptable registers for various purposes (one for - base registers, one for index registers, and so on) are typically among the - subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'. Then only these - subroutine macros need have two variants; the higher levels of macros may be - the same whether strict or not. - - Normally, constant addresses which are the sum of a `symbol_ref' and an - integer are stored inside a `const' RTX to mark them as constant. - Therefore, there is no need to recognize such sums specifically as - legitimate addresses. Normally you would simply recognize any `const' as - legitimate. - - Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that - are not marked with `const'. It assumes that a naked `plus' indicates - indexing. If so, then you *must* reject such naked constant sums as - illegitimate addresses, so that none of them will be given to - `PRINT_OPERAND_ADDRESS'. - - On some machines, whether a symbolic address is legitimate depends on the - section that the address refers to. On these machines, define the macro - `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and - then check for it here. When you see a `const', you will have to look - inside it to find the `symbol_ref' in order to determine the section. *Note - Assembler Format::. - - The best way to modify the name string is by adding text to the beginning, - with suitable punctuation to prevent any ambiguity. Allocate the new name - in `saveable_obstack'. You will have to modify `ASM_OUTPUT_LABELREF' to - remove and decode the added text and output the name accordingly, and define - `STRIP_NAME_ENCODING' to access the original name string. - - You can check the information stored here into the `symbol_ref' in the - definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and - `PRINT_OPERAND_ADDRESS'. */ - -#ifdef REG_OK_STRICT -#define REG_OK_STRICT_P 1 -#else -#define REG_OK_STRICT_P 0 -#endif - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -do { \ - if (d30v_legitimate_address_p ((int)MODE, X, REG_OK_STRICT_P)) \ - goto ADDR; \ -} while (0) - -/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for - use as a base register. For hard registers, it should always accept those - which the hardware permits and reject the others. Whether the macro accepts - or rejects pseudo registers must be controlled by `REG_OK_STRICT' as - described above. This usually requires two variant definitions, of which - `REG_OK_STRICT' controls the one actually used. */ - -#ifdef REG_OK_STRICT -#define REG_OK_FOR_BASE_P(X) (GPR_P (REGNO (X))) -#else -#define REG_OK_FOR_BASE_P(X) (GPR_OR_PSEUDO_P (REGNO (X))) -#endif - -/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for - use as an index register. - - The difference between an index register and a base register is that the - index register may be scaled. If an address involves the sum of two - registers, neither one of them scaled, then either one may be labeled the - "base" and the other the "index"; but whichever labeling is used must fit - the machine's constraints of which registers may serve in each capacity. - The compiler will try both labelings, looking for one that is valid, and - will reload one or both registers only if neither labeling works. */ - -#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X) - -/* A C compound statement that attempts to replace X with a valid memory - address for an operand of mode MODE. WIN will be a C statement label - elsewhere in the code; the macro definition may use - - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); - - to avoid further processing if the address has become legitimate. - - X will always be the result of a call to `break_out_memory_refs', and OLDX - will be the operand that was given to that function to produce X. - - The code generated by this macro should not alter the substructure of X. If - it transforms X into a more legitimate form, it should assign X (which will - always be a C variable) a new value. - - It is not necessary for this macro to come up with a legitimate address. - The compiler has standard ways of doing so in all cases. In fact, it is - safe for this macro to do nothing. But often a machine-dependent strategy - can generate better code. */ - -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -do { \ - rtx y = d30v_legitimize_address (X, OLDX, (int)MODE, REG_OK_STRICT_P); \ - if (y) \ - { \ - X = y; \ - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); \ - } \ -} while (0) - -/* A C statement or compound statement with a conditional `goto LABEL;' - executed if memory address X (an RTX) can have different meanings depending - on the machine mode of the memory reference it is used for or if the address - is valid for some modes but not others. - - Autoincrement and autodecrement addresses typically have mode-dependent - effects because the amount of the increment or decrement is the size of the - operand being addressed. Some machines have other mode-dependent addresses. - Many RISC machines have no mode-dependent addresses. - - You may assume that ADDR is a valid address for the machine. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ -do { \ - if (d30v_mode_dependent_address_p (ADDR)) \ - goto LABEL; \ -} while (0) \ - -/* A C expression that is nonzero if X is a legitimate constant for an - immediate operand on the target machine. You can assume that X satisfies - `CONSTANT_P', so you need not check this. In fact, `1' is a suitable - definition for this macro on machines where anything `CONSTANT_P' is valid. */ -#define LEGITIMATE_CONSTANT_P(X) 1 - - -/* Condition Code Status */ - -/* C code for a data type which is used for declaring the `mdep' component of - `cc_status'. It defaults to `int'. - - This macro is not used on machines that do not use `cc0'. */ -/* #define CC_STATUS_MDEP */ - -/* A C expression to initialize the `mdep' field to "empty". The default - definition does nothing, since most machines don't use the field anyway. If - you want to use the field, you should probably define this macro to - initialize it. - - This macro is not used on machines that do not use `cc0'. */ -/* #define CC_STATUS_MDEP_INIT */ - -/* A C compound statement to set the components of `cc_status' appropriately - for an insn INSN whose body is EXP. It is this macro's responsibility to - recognize insns that set the condition code as a byproduct of other activity - as well as those that explicitly set `(cc0)'. - - This macro is not used on machines that do not use `cc0'. - - If there are insns that do not set the condition code but do alter other - machine registers, this macro must check to see whether they invalidate the - expressions that the condition code is recorded as reflecting. For example, - on the 68000, insns that store in address registers do not set the condition - code, which means that usually `NOTICE_UPDATE_CC' can leave `cc_status' - unaltered for such insns. But suppose that the previous insn set the - condition code based on location `a4@(102)' and the current insn stores a - new value in `a4'. Although the condition code is not changed by this, it - will no longer be true that it reflects the contents of `a4@(102)'. - Therefore, `NOTICE_UPDATE_CC' must alter `cc_status' in this case to say - that nothing is known about the condition code value. - - The definition of `NOTICE_UPDATE_CC' must be prepared to deal with the - results of peephole optimization: insns whose patterns are `parallel' RTXs - containing various `reg', `mem' or constants which are just the operands. - The RTL structure of these insns is not sufficient to indicate what the - insns actually do. What `NOTICE_UPDATE_CC' should do when it sees one is - just to run `CC_STATUS_INIT'. - - A possible definition of `NOTICE_UPDATE_CC' is to call a function that looks - at an attribute (*note Insn Attributes::.) named, for example, `cc'. This - avoids having detailed information about patterns in two places, the `md' - file and in `NOTICE_UPDATE_CC'. */ -/* #define NOTICE_UPDATE_CC(EXP, INSN) */ - -/* A list of names to be used for additional modes for condition code values in - registers (*note Jump Patterns::.). These names are added to `enum - machine_mode' and all have class `MODE_CC'. By convention, they should - start with `CC' and end with `mode'. - - You should only define this macro if your machine does not use `cc0' and - only if additional modes are required. */ -/* #define EXTRA_CC_MODES */ - -/* A list of C strings giving the names for the modes listed in - `EXTRA_CC_MODES'. For example, the Sparc defines this macro and - `EXTRA_CC_MODES' as - - #define EXTRA_CC_MODES CC_NOOVmode, CCFPmode, CCFPEmode - #define EXTRA_CC_NAMES "CC_NOOV", "CCFP", "CCFPE" - - This macro is not required if `EXTRA_CC_MODES' is not defined. */ -/* #define EXTRA_CC_NAMES */ - -/* Returns a mode from class `MODE_CC' to be used when comparison operation - code OP is applied to rtx X and Y. For example, on the Sparc, - `SELECT_CC_MODE' is defined as (see *note Jump Patterns::. for a - description of the reason for this definition) - - #define SELECT_CC_MODE(OP,X,Y) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ - : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ - || GET_CODE (X) == NEG) \ - ? CC_NOOVmode : CCmode)) - - You need not define this macro if `EXTRA_CC_MODES' is not defined. */ -/* #define SELECT_CC_MODE(OP, X, Y) */ - -/* One some machines not all possible comparisons are defined, but you can - convert an invalid comparison into a valid one. For example, the Alpha does - not have a `GT' comparison, but you can use an `LT' comparison instead and - swap the order of the operands. - - On such machines, define this macro to be a C statement to do any required - conversions. CODE is the initial comparison code and OP0 and OP1 are the - left and right operands of the comparison, respectively. You should modify - CODE, OP0, and OP1 as required. - - GNU CC will not assume that the comparison resulting from this macro is - valid but will see if the resulting insn matches a pattern in the `md' file. - - You need not define this macro if it would never change the comparison code - or operands. */ -/* #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) */ - -/* A C expression whose value is one if it is always safe to reverse a - comparison whose mode is MODE. If `SELECT_CC_MODE' can ever return MODE for - a floating-point inequality comparison, then `REVERSIBLE_CC_MODE (MODE)' - must be zero. - - You need not define this macro if it would always returns zero or if the - floating-point format is anything other than `IEEE_FLOAT_FORMAT'. For - example, here is the definition used on the Sparc, where floating-point - inequality comparisons are always given `CCFPEmode': - - #define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode) */ -/* #define REVERSIBLE_CC_MODE(MODE) */ - - -/* Describing Relative Costs of Operations */ - -/* A part of a C `switch' statement that describes the relative costs of - constant RTL expressions. It must contain `case' labels for expression - codes `const_int', `const', `symbol_ref', `label_ref' and `const_double'. - Each case must ultimately reach a `return' statement to return the relative - cost of the use of that kind of constant value in an expression. The cost - may depend on the precise value of the constant, which is available for - examination in X, and the rtx code of the expression in which it is - contained, found in OUTER_CODE. - - CODE is the expression code--redundant, since it can be obtained with - `GET_CODE (X)'. */ - -/* On the d30v, consider operatnds that fit in a short instruction very - cheap. However, at this time, it causes cse to generate incorrect - code, so disable it for now. */ -#if 0 -#define CONST_COSTS(X, CODE, OUTER_CODE) \ - case CONST_INT: \ - if (IN_RANGE_P (INTVAL (X), 0, 31)) \ - return 0; \ - else if ((OUTER_CODE) == LEU && (OUTER_CODE) == LTU \ - && (OUTER_CODE) == GEU && (OUTER_CODE) == GTU) \ - return IN_RANGE_P (INTVAL (X), 32, 63) ? 0 : COSTS_N_INSNS (2); \ - else \ - return IN_RANGE_P (INTVAL (X), -31, -1) ? 0 : COSTS_N_INSNS (2); \ - case SYMBOL_REF: \ - case LABEL_REF: \ - case CONST: \ - return COSTS_N_INSNS (2); \ - case CONST_DOUBLE: \ - return COSTS_N_INSNS ((GET_MODE (X) == SFmode) ? 2 : 4); -#else -#define CONST_COSTS(X, CODE, OUTER_CODE) -#endif - -/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. This can be - used, for example, to indicate how costly a multiply instruction is. In - writing this macro, you can use the construct `COSTS_N_INSNS (N)' to specify - a cost equal to N fast instructions. OUTER_CODE is the code of the - expression in which X is contained. - - This macro is optional; do not define it if the default cost assumptions are - adequate for the target machine. */ -#define RTX_COSTS(X, CODE, OUTER_CODE) \ - case MULT: \ - return COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT \ - && exact_log2 (INTVAL (XEXP (x, 1))) >= 0) \ - ? 1 : 2); - -/* An expression giving the cost of an addressing mode that contains ADDRESS. - If not defined, the cost is computed from the ADDRESS expression and the - `CONST_COSTS' values. - - For most CISC machines, the default cost is a good approximation of the true - cost of the addressing mode. However, on RISC machines, all instructions - normally have the same length and execution time. Hence all addresses will - have equal costs. - - In cases where more than one form of an address is known, the form with the - lowest cost will be used. If multiple forms have the same, lowest, cost, - the one that is the most complex will be used. - - For example, suppose an address that is equal to the sum of a register and a - constant is used twice in the same basic block. When this macro is not - defined, the address will be computed in a register and memory references - will be indirect through that register. On machines where the cost of the - addressing mode containing the sum is no higher than that of a simple - indirect reference, this will produce an additional instruction and possibly - require an additional register. Proper specification of this macro - eliminates this overhead for such machines. - - Similar use of this macro is made in strength reduction of loops. - - ADDRESS need not be valid as an address. In such a case, the cost is not - relevant and can be any value; invalid addresses need not be assigned a - different cost. - - On machines where an address involving more than one register is as cheap as - an address computation involving only one register, defining `ADDRESS_COST' - to reflect this can cause two registers to be live over a region of code - where only one would have been if `ADDRESS_COST' were not defined in that - manner. This effect should be considered in the definition of this macro. - Equivalent costs should probably only be given to addresses with different - numbers of registers on machines with lots of registers. - - This macro will normally either not be defined or be defined as a constant. */ -#define ADDRESS_COST(ADDRESS) 0 - -/* A C expression for the cost of moving data from a register in class FROM to - one in class TO. The classes are expressed using the enumeration values - such as `GENERAL_REGS'. A value of 4 is the default; other values are - interpreted relative to that. - - It is not required that the cost always equal 2 when FROM is the same as TO; - on some machines it is expensive to move between registers if they are not - general registers. - - If reload sees an insn consisting of a single `set' between two hard - registers, and if `REGISTER_MOVE_COST' applied to their classes returns a - value of 2, reload does not check to ensure that the constraints of the insn - are met. Setting a cost of other than 2 will allow reload to verify that - the constraints are met. You should do this if the `movM' pattern's - constraints do not allow such copying. */ - -#define REGISTER_MOVE_COST(FROM, TO) \ - (((FROM) != GPR_REGS && (FROM) != EVEN_REGS \ - && (TO) != GPR_REGS && (TO) != EVEN_REGS) ? 4 : 2) - -/* A C expression for the cost of moving data of mode M between a register and - memory. A value of 2 is the default; this cost is relative to those in - `REGISTER_MOVE_COST'. - - If moving between registers and memory is more expensive than between two - registers, you should define this macro to express the relative cost. */ -#define MEMORY_MOVE_COST(M,C,I) 4 - -/* A C expression for the cost of a branch instruction. A value of 1 is the - default; other values are interpreted relative to that. */ - -#define BRANCH_COST d30v_branch_cost - -#define D30V_DEFAULT_BRANCH_COST 2 - -/* Values of the -mbranch-cost=n string. */ -extern int d30v_branch_cost; -extern char *d30v_branch_cost_string; - -/* Here are additional macros which do not specify precise relative costs, but - only that certain actions are more expensive than GNU CC would ordinarily - expect. */ - -/* Define this macro as a C expression which is nonzero if accessing less than - a word of memory (i.e. a `char' or a `short') is no faster than accessing a - word of memory, i.e., if such access require more than one instruction or if - there is no difference in cost between byte and (aligned) word loads. - - When this macro is not defined, the compiler will access a field by finding - the smallest containing object; when it is defined, a fullword load will be - used if alignment permits. Unless bytes accesses are faster than word - accesses, using word accesses is preferable since it may eliminate - subsequent memory access if subsequent accesses occur to other fields in the - same word of the structure, but to different bytes. */ -#define SLOW_BYTE_ACCESS 1 - -/* Define this macro if zero-extension (of a `char' or `short' to an `int') can - be done faster if the destination is a register that is known to be zero. - - If you define this macro, you must have instruction patterns that recognize - RTL structures like this: - - (set (strict_low_part (subreg:QI (reg:SI ...) 0)) ...) - - and likewise for `HImode'. */ -#define SLOW_ZERO_EXTEND 0 - -/* Define this macro to be the value 1 if unaligned accesses have a cost many - times greater than aligned accesses, for example if they are emulated in a - trap handler. - - When this macro is non-zero, the compiler will act as if `STRICT_ALIGNMENT' - were non-zero when generating code for block moves. This can cause - significantly more instructions to be produced. Therefore, do not set this - macro non-zero if unaligned accesses only add a cycle or two to the time for - a memory access. - - If the value of this macro is always zero, it need not be defined. */ -/* #define SLOW_UNALIGNED_ACCESS */ - -/* Define this macro to inhibit strength reduction of memory addresses. (On - some machines, such strength reduction seems to do harm rather than good.) */ -/* #define DONT_REDUCE_ADDR */ - -/* The number of scalar move insns which should be generated instead of a - string move insn or a library call. Increasing the value will always make - code faster, but eventually incurs high cost in increased code size. - - If you don't define this, a reasonable default is used. */ -/* #define MOVE_RATIO */ - -/* 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 - -/* Define this macro if it is as good or better for a function to call itself - with an explicit address than to call an address kept in a register. */ -/* #define NO_RECURSIVE_FUNCTION_CSE */ - -/* A C statement (sans semicolon) to update the integer variable COST based on - the relationship between INSN that is dependent on DEP_INSN through the - dependence LINK. The default is to make no adjustment to COST. This can be - used for example to specify to the scheduler that an output- or - anti-dependence does not incur the same cost as a data-dependence. */ - -#define ADJUST_COST(INSN,LINK,DEP_INSN,COST) \ - (COST) = d30v_adjust_cost (INSN, LINK, DEP_INSN, COST) - -/* A C statement (sans semicolon) to update the integer scheduling - priority `INSN_PRIORITY(INSN)'. Reduce the priority to execute - the INSN earlier, increase the priority to execute INSN later. - Do not define this macro if you do not need to adjust the - scheduling priorities of insns. */ -/* #define ADJUST_PRIORITY (INSN) */ - -/* Macro to determine whether the Haifa scheduler is used. */ -#ifdef HAIFA -#define HAIFA_P 1 -#else -#define HAIFA_P 0 -#endif - - -/* Dividing the output into sections. */ - -/* A C expression whose value is a string containing the assembler operation - that should precede instructions and read-only data. Normally `".text"' is - right. */ -#define TEXT_SECTION_ASM_OP ".text" - -/* A C expression whose value is a string containing the assembler operation to - identify the following data as writable initialized data. Normally - `".data"' is right. */ -#define DATA_SECTION_ASM_OP ".data" - -/* if defined, a C expression whose value is a string containing the assembler - operation to identify the following data as shared data. If not defined, - `DATA_SECTION_ASM_OP' will be used. */ -/* #define SHARED_SECTION_ASM_OP */ - -/* 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 ".bss" - -/* If defined, a C expression whose value is a string containing the - assembler operation to identify the following data as - uninitialized global shared data. If not defined, and - `BSS_SECTION_ASM_OP' is, the latter will be used. */ -/* #define SHARED_BSS_SECTION_ASM_OP */ - -/* A list of names for sections other than the standard two, which are - `in_text' and `in_data'. You need not define this macro on a system with no - other sections (that GCC needs to use). - - Defined in svr4.h. */ -/* #define EXTRA_SECTIONS */ - -/* One or more functions to be defined in `varasm.c'. These functions should - do jobs analogous to those of `text_section' and `data_section', for your - additional sections. Do not define this macro if you do not define - `EXTRA_SECTIONS'. - - Defined in svr4.h. */ -/* #define EXTRA_SECTION_FUNCTIONS */ - -/* On most machines, read-only variables, constants, and jump tables are placed - in the text section. If this is not the case on your machine, this macro - should be defined to be the name of a function (either `data_section' or a - function defined in `EXTRA_SECTIONS') that switches to the section to be - used for read-only items. - - If these items should be placed in the text section, this macro should not - be defined. */ -/* #define READONLY_DATA_SECTION */ - -/* A C statement or statements to switch to the appropriate section for output - of EXP. You can assume that EXP is either a `VAR_DECL' node or a constant - of some sort. RELOC indicates whether the initial value of EXP requires - link-time relocations. Select the section by calling `text_section' or one - of the alternatives for other sections. - - Do not define this macro if you put all read-only variables and constants in - the read-only data section (usually the text section). - - Defined in svr4.h. */ -/* #define SELECT_SECTION(EXP, RELOC) */ - -/* 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. - - Do not define this macro if you put all constants in the read-only data - section. - - Defined in svr4.h. */ -/* #define SELECT_RTX_SECTION(MODE, RTX) */ - -/* Define this macro if jump tables (for `tablejump' insns) should be output in - the text section, along with the assembler instructions. Otherwise, the - readonly data section is used. - - This macro is irrelevant if there is no separate readonly data section. */ -/* #define JUMP_TABLES_IN_TEXT_SECTION */ - -/* Define this macro if references to a symbol must be treated differently - depending on something about the variable or function named by the symbol - (such as what section it is in). - - The macro definition, if any, is executed immediately after the rtl for DECL - has been created and stored in `DECL_RTL (DECL)'. The value of the rtl will - be a `mem' whose address is a `symbol_ref'. - - The usual thing for this macro to do is to record a flag in the `symbol_ref' - (such as `SYMBOL_REF_FLAG') or to store a modified name string in the - `symbol_ref' (if one bit is not enough information). */ -/* #define ENCODE_SECTION_INFO(DECL) */ - -/* Decode SYM_NAME and store the real name part in VAR, sans the characters - that encode section info. Define this macro if `ENCODE_SECTION_INFO' alters - the symbol's name string. */ -/* #define STRIP_NAME_ENCODING(VAR, SYM_NAME) */ - -/* A C expression which evaluates to true if DECL should be placed - into a unique section for some target-specific reason. If you do - not define this macro, the default is `0'. Note that the flag - `-ffunction-sections' will also cause functions to be placed into - unique sections. - - Defined in svr4.h. */ -/* #define UNIQUE_SECTION_P(DECL) */ - -/* 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, GNU CC - will use the symbol name prefixed by `.' as the section name. - - Defined in svr4.h. */ -/* #define UNIQUE_SECTION(DECL, RELOC) */ - - -/* Position Independent Code. */ - -/* The register number of the register used to address a table of static data - addresses in memory. In some cases this register is defined by a - processor's "application binary interface" (ABI). When this macro is - defined, RTL is generated for this register once, as with the stack pointer - and frame pointer registers. If this macro is not defined, it is up to the - machine-dependent files to allocate such a register (if necessary). */ -/* #define PIC_OFFSET_TABLE_REGNUM */ - -/* Define this macro if the register defined by `PIC_OFFSET_TABLE_REGNUM' is - clobbered by calls. Do not define this macro if `PIC_OFFSET_TABLE_REGNUM' - is not defined. */ -/* #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 not check this. You can also - assume FLAG_PIC is true, so you need not check it either. You need not - define this macro if all constants (including `SYMBOL_REF') can be immediate - operands when generating position independent code. */ -/* #define LEGITIMATE_PIC_OPERAND_P(X) */ - - -/* The Overall Framework of an Assembler File. */ - -/* A C expression which outputs to the stdio stream STREAM some appropriate - text to go at the start of an assembler file. - - Normally this macro is defined to output a line containing `#NO_APP', which - is a comment that has no effect on most assemblers but tells the GNU - assembler that it can save time by not checking for certain assembler - constructs. - - On systems that use SDB, it is necessary to output certain commands; see - `attasm.h'. - - Defined in svr4.h. */ - -/* #define ASM_FILE_START(STREAM) \ - output_file_directive ((STREAM), main_input_filename) */ - -/* A C expression which outputs to the stdio stream STREAM some appropriate - text to go at the end of an assembler file. - - If this macro is not defined, the default is to output nothing special at - the end of the file. Most systems don't require any definition. - - On systems that use SDB, it is necessary to output certain commands; see - `attasm.h'. - - Defined in svr4.h. */ -/* #define ASM_FILE_END(STREAM) */ - -/* A C statement to output assembler commands which will identify the object - file as having been compiled with GNU CC (or another GNU compiler). - - If you don't define this macro, the string `gcc_compiled.:' is output. This - string is calculated to define a symbol which, on BSD systems, will never be - defined for any other reason. GDB checks for the presence of this symbol - when reading the symbol table of an executable. - - On non-BSD systems, you must arrange communication with GDB in some other - fashion. If GDB is not used on your system, you can define this macro with - an empty body. - - Defined in svr4.h. */ -/* #define ASM_IDENTIFY_GCC(FILE) */ - -/* Like ASM_IDENTIFY_GCC, but used when dbx debugging is selected to emit - a stab the debugger uses to identify gcc as the compiler that is emitted - after the stabs for the filename, which makes it easier for GDB to parse. - - Defined in svr4.h. */ -/* #define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) */ - -/* A C string constant describing how to begin a comment in the target - assembler language. The compiler assumes that the comment will end at the - end of the line. */ -#define ASM_COMMENT_START ";" - -/* A C string constant for text to be output before each `asm' statement or - group of consecutive ones. Normally this is `"#APP"', which is a comment - that has no effect on most assemblers but tells the GNU assembler that it - must check the lines that follow for all valid assembler constructs. */ -#define ASM_APP_ON "#APP\n" - -/* A C string constant for text to be output after each `asm' statement or - group of consecutive ones. Normally this is `"#NO_APP"', which tells the - GNU assembler to resume making the time-saving assumptions that are valid - for ordinary compiler output. */ -#define ASM_APP_OFF "#NO_APP\n" - -/* A C statement to output COFF information or DWARF debugging information - which indicates that filename NAME is the current source file to the stdio - stream STREAM. - - This macro need not be defined if the standard form of output for the file - format in use is appropriate. */ -/* #define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) */ - -/* A C statement to output DBX or SDB debugging information before code for - line number LINE of the current source file to the stdio stream STREAM. - - This macro need not be defined if the standard form of debugging information - for the debugger in use is appropriate. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) */ - -/* A C statement to output something to the assembler file to handle a `#ident' - directive containing the text STRING. If this macro is not defined, nothing - is output for a `#ident' directive. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_IDENT(STREAM, STRING) */ - -/* A C statement to output something to the assembler file to switch to section - NAME for object DECL which is either a `FUNCTION_DECL', a `VAR_DECL' or - `NULL_TREE'. Some target formats do not support arbitrary sections. Do not - define this macro in such cases. - - At present this macro is only used to support section attributes. When this - macro is undefined, section attributes are disabled. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME) */ - -/* A C statement to output any assembler statements which are required to - precede any Objective C object definitions or message sending. The - statement is executed only when compiling an Objective C program. */ -/* #define OBJC_PROLOGUE */ - - -/* Output of Data. */ - -/* A C statement to output to the stdio stream STREAM an assembler instruction - to assemble a floating-point constant of `TFmode', `DFmode', `SFmode', - `TQFmode', `HFmode', or `QFmode', respectively, whose value is VALUE. VALUE - will be a C expression of type `REAL_VALUE_TYPE'. Macros such as - `REAL_VALUE_TO_TARGET_DOUBLE' are useful for writing these definitions. */ - -/* #define ASM_OUTPUT_LONG_DOUBLE(STREAM, VALUE) */ - -#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ - { \ - if (REAL_VALUE_ISINF (VALUE) \ - || REAL_VALUE_ISNAN (VALUE) \ - || REAL_VALUE_MINUS_ZERO (VALUE)) \ - { \ - long t[2]; \ - REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ - fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n", \ - t[0] & 0xffffffff, t[1] & 0xffffffff); \ - } \ - else \ - { \ - char str[30]; \ - REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", str); \ - fprintf (FILE, "\t.double 0d%s\n", str); \ - } \ - } - -#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ - { \ - if (REAL_VALUE_ISINF (VALUE) \ - || REAL_VALUE_ISNAN (VALUE) \ - || REAL_VALUE_MINUS_ZERO (VALUE)) \ - { \ - long t; \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \ - } \ - else \ - { \ - char str[30]; \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ - fprintf (FILE, "\t.float 0d%s\n", str); \ - } \ - } - -/* #define ASM_OUTPUT_THREE_QUARTER_FLOAT(STREAM, VALUE) */ -/* #define ASM_OUTPUT_SHORT_FLOAT(STREAM, VALUE) */ -/* #define ASM_OUTPUT_BYTE_FLOAT(STREAM, VALUE) */ - -/* A C statement to output to the stdio stream STREAM an assembler instruction - to assemble an integer of 16, 8, 4, 2 or 1 bytes, respectively, whose value - is VALUE. The argument EXP will be an RTL expression which represents a - constant value. Use `output_addr_const (STREAM, EXP)' to output this value - as an assembler expression. - - For sizes larger than `UNITS_PER_WORD', if the action of a macro would be - identical to repeatedly calling the macro corresponding to a size of - `UNITS_PER_WORD', once for each word, you need not define the macro. */ - -/* #define ASM_OUTPUT_QUADRUPLE_INT(STREAM, EXP) */ -/* #define ASM_OUTPUT_DOUBLE_INT(STREAM, EXP) */ - -#define ASM_OUTPUT_INT(STREAM, EXP) \ -do { \ - fputs ("\t.word ", STREAM); \ - output_addr_const (STREAM, EXP); \ - putc ('\n', STREAM); \ -} while (0) - -#define ASM_OUTPUT_SHORT(STREAM, EXP) \ -do { \ - fputs ("\t.hword ", STREAM); \ - output_addr_const (STREAM, EXP); \ - putc ('\n', STREAM); \ -} while (0) - -#define ASM_OUTPUT_CHAR(STREAM, EXP) \ -do { \ - fputs ("\t.byte ", STREAM); \ - output_addr_const (STREAM, EXP); \ - putc ('\n', STREAM); \ -} while (0) - -/* A C statement to output to the stdio stream STREAM an assembler instruction - to assemble a single byte containing the number VALUE. */ - -#define ASM_OUTPUT_BYTE(STREAM, VALUE) \ - fprintf (STREAM, "\t%s %d\n", ASM_BYTE_OP, VALUE) - -/* A C string constant giving the pseudo-op to use for a sequence of - single-byte constants. If this macro is not defined, the default - is `"byte"'. - - Defined in svr4.h. */ -/* #define ASM_BYTE_OP */ - -/* A C statement to output to the stdio stream STREAM an assembler instruction - to assemble a string constant containing the LEN bytes at PTR. PTR will be - a C expression of type `char *' and LEN a C expression of type `int'. - - If the assembler has a `.ascii' pseudo-op as found in the Berkeley Unix - assembler, do not define the macro `ASM_OUTPUT_ASCII'. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_ASCII(STREAM, PTR, LEN) */ - -/* You may define this macro as a C expression. You should define the - expression to have a non-zero value if GNU CC should output the - constant pool for a function before the code for the function, or - a zero value if GNU CC should output the constant pool after the - function. If you do not define this macro, the usual case, GNU CC - will output the constant pool before the function. */ -/* #define CONSTANT_POOL_BEFORE_FUNCTION */ - -/* A C statement to output assembler commands to define the start of the - constant pool for a function. FUNNAME is a string giving the name of the - function. Should the return type of the function be required, it can be - obtained via FUNDECL. SIZE is the size, in bytes, of the constant pool that - will be written immediately after this call. - - If no constant-pool prefix is required, the usual case, this macro need not - be defined. */ -/* #define ASM_OUTPUT_POOL_PROLOGUE(FILE FUNNAME FUNDECL SIZE) */ - -/* A C statement (with or without semicolon) to output a constant in the - constant pool, if it needs special treatment. (This macro need not do - anything for RTL expressions that can be output normally.) - - The argument FILE is the standard I/O stream to output the assembler code - on. X is the RTL expression for the constant to output, and MODE is the - machine mode (in case X is a `const_int'). ALIGN is the required alignment - for the value X; you should output an assembler directive to force this much - alignment. - - The argument LABELNO is a number to use in an internal label for the address - of this pool entry. The definition of this macro is responsible for - outputting the label definition at the proper place. Here is how to do - this: - - ASM_OUTPUT_INTERNAL_LABEL (FILE, "LC", LABELNO); - - When you output a pool entry specially, you should end with a `goto' to the - label JUMPTO. This will prevent the same pool entry from being output a - second time in the usual manner. - - You need not define this macro if it would do nothing. */ -/* #define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, JUMPTO) */ - -/* Define this macro as a C expression which is nonzero if the constant EXP, of - type `tree', should be output after the code for a function. The compiler - will normally output all constants before the function; you need not define - this macro if this is OK. */ -/* #define CONSTANT_AFTER_FUNCTION_P(EXP) */ - -/* A C statement to output assembler commands to at the end of the constant - pool for a function. FUNNAME is a string giving the name of the function. - Should the return type of the function be required, you can obtain it via - FUNDECL. SIZE is the size, in bytes, of the constant pool that GNU CC wrote - immediately before this call. - - If no constant-pool epilogue is required, the usual case, you need not - define this macro. */ -/* #define ASM_OUTPUT_POOL_EPILOGUE (FILE FUNNAME FUNDECL SIZE) */ - -/* Define this macro as a C expression which is nonzero if C is used as a - logical line separator by the assembler. - - If you do not define this macro, the default is that only the character `;' - is treated as a logical line separator. */ -/* #define IS_ASM_LOGICAL_LINE_SEPARATOR(C) */ - -/* These macros are defined as C string constant, describing the syntax in the - assembler for grouping arithmetic expressions. The following definitions - are correct for most assemblers: - - #define ASM_OPEN_PAREN "(" - #define ASM_CLOSE_PAREN ")" */ -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* These macros are provided by `real.h' for writing the definitions of - `ASM_OUTPUT_DOUBLE' and the like: */ - -/* These translate X, of type `REAL_VALUE_TYPE', to the target's floating point - representation, and store its bit pattern in the array of `long int' whose - address is L. The number of elements in the output array is determined by - the size of the desired target floating point data type: 32 bits of it go in - each `long int' array element. Each array element holds 32 bits of the - result, even if `long int' is wider than 32 bits on the host machine. - - The array element values are designed so that you can print them out using - `fprintf' in the order they should appear in the target machine's memory. */ -/* #define REAL_VALUE_TO_TARGET_SINGLE(X, L) */ -/* #define REAL_VALUE_TO_TARGET_DOUBLE(X, L) */ -/* #define REAL_VALUE_TO_TARGET_LONG_DOUBLE(X, L) */ - -/* This macro converts X, of type `REAL_VALUE_TYPE', to a decimal number and - stores it as a string into STRING. You must pass, as STRING, the address of - a long enough block of space to hold the result. - - The argument FORMAT is a `printf'-specification that serves as a suggestion - for how to format the output string. */ -/* #define REAL_VALUE_TO_DECIMAL(X, FORMAT, STRING) */ - - -/* Output of Uninitialized Variables. */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM the - assembler definition of a common-label named NAME whose size is SIZE bytes. - The variable ROUNDED is the size rounded up to whatever alignment the caller - wants. - - Use the expression `assemble_name (STREAM, NAME)' to output the name itself; - before and after that, output the additional assembler syntax for defining - the name, and a newline. - - This macro controls how the assembler definitions of uninitialized global - variables are output. */ -/* #define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) */ - -/* Like `ASM_OUTPUT_COMMON' except takes the required alignment as a separate, - explicit argument. If you define this macro, it is used in place of - `ASM_OUTPUT_COMMON', and gives you more flexibility in handling the required - alignment of the variable. The alignment is specified as the number of - bits. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_ALIGNED_COMMON(STREAM, NAME, SIZE, ALIGNMENT) */ - -/* Like ASM_OUTPUT_ALIGNED_COMMON except that it takes an additional argument - - the DECL of the variable to be output, if there is one. This macro can be - called with DECL == NULL_TREE. If you define this macro, it is used in - place of both ASM_OUTPUT_COMMON and ASM_OUTPUT_ALIGNED_COMMON, and gives you - more flexibility in handling the destination of the variable. */ -/* #define ASM_OUTPUT_DECL_COMMON (STREAM, DECL, NAME, SIZE, ALIGNMENT) */ - -/* If defined, it is similar to `ASM_OUTPUT_COMMON', except that it is used - when NAME is shared. If not defined, `ASM_OUTPUT_COMMON' will be used. */ -/* #define ASM_OUTPUT_SHARED_COMMON(STREAM, NAME, SIZE, ROUNDED) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM the - assembler definition of uninitialized global DECL named NAME whose size is - SIZE bytes. The variable ROUNDED is the size rounded up to whatever - alignment the caller wants. - - Try to use function `asm_output_bss' defined in `varasm.c' when defining - this macro. If unable, use the expression `assemble_name (STREAM, NAME)' to - output the name itself; before and after that, output the additional - assembler syntax for defining the name, and a newline. - - This macro controls how the assembler definitions of uninitialized global - variables are output. This macro exists to properly support languages like - `c++' which do not have `common' data. However, this macro currently is not - defined for all targets. If this macro and `ASM_OUTPUT_ALIGNED_BSS' are not - defined then `ASM_OUTPUT_COMMON' or `ASM_OUTPUT_ALIGNED_COMMON' or - `ASM_OUTPUT_DECL_COMMON' is used. */ -/* #define ASM_OUTPUT_BSS(STREAM, DECL, NAME, SIZE, ROUNDED) */ - -/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a separate, - explicit argument. If you define this macro, it is used in place of - `ASM_OUTPUT_BSS', and gives you more flexibility in handling the required - alignment of the variable. The alignment is specified as the number of - bits. - - Try to use function `asm_output_aligned_bss' defined in file `varasm.c' when - defining this macro. */ -/* #define ASM_OUTPUT_ALIGNED_BSS(STREAM, DECL, NAME, SIZE, ALIGNMENT) */ - -/* If defined, it is similar to `ASM_OUTPUT_BSS', except that it is used when - NAME is shared. If not defined, `ASM_OUTPUT_BSS' will be used. */ -/* #define ASM_OUTPUT_SHARED_BSS(STREAM, DECL, NAME, SIZE, ROUNDED) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM the - assembler definition of a local-common-label named NAME whose size is SIZE - bytes. The variable ROUNDED is the size rounded up to whatever alignment - the caller wants. - - Use the expression `assemble_name (STREAM, NAME)' to output the name itself; - before and after that, output the additional assembler syntax for defining - the name, and a newline. - - This macro controls how the assembler definitions of uninitialized static - variables are output. */ -/* #define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) */ - -/* Like `ASM_OUTPUT_LOCAL' except takes the required alignment as a separate, - explicit argument. If you define this macro, it is used in place of - `ASM_OUTPUT_LOCAL', and gives you more flexibility in handling the required - alignment of the variable. The alignment is specified as the number of - bits. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGNMENT) */ - -/* Like `ASM_OUTPUT_ALIGNED_LOCAL' except that it takes an additional - parameter - the DECL of variable to be output, if there is one. - This macro can be called with DECL == NULL_TREE. If you define - this macro, it is used in place of `ASM_OUTPUT_LOCAL' and - `ASM_OUTPUT_ALIGNED_LOCAL', and gives you more flexibility in - handling the destination of the variable. */ -/* #define ASM_OUTPUT_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) */ - -/* If defined, it is similar to `ASM_OUTPUT_LOCAL', except that it is used when - NAME is shared. If not defined, `ASM_OUTPUT_LOCAL' will be used. */ -/* #define ASM_OUTPUT_SHARED_LOCAL (STREAM, NAME, SIZE, ROUNDED) */ - - -/* Output and Generation of Labels. */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM the - assembler definition of a label named NAME. Use the expression - `assemble_name (STREAM, NAME)' to output the name itself; before and after - that, output the additional assembler syntax for defining the name, and a - newline. */ - -#define ASM_OUTPUT_LABEL(STREAM, NAME) \ -do { \ - assemble_name (STREAM, NAME); \ - fputs (":\n", STREAM); \ -} while (0) - -/* A C statement (sans semicolon) to output to the stdio stream STREAM any text - necessary for declaring the name NAME of a function which is being defined. - This macro is responsible for outputting the label definition (perhaps using - `ASM_OUTPUT_LABEL'). The argument DECL is the `FUNCTION_DECL' tree node - representing the function. - - If this macro is not defined, then the function name is defined in the usual - manner as a label (by means of `ASM_OUTPUT_LABEL'). - - Defined in svr4.h. */ -/* #define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM any text - necessary for declaring the size of a function which is being defined. The - argument NAME is the name of the function. The argument DECL is the - `FUNCTION_DECL' tree node representing the function. - - If this macro is not defined, then the function size is not defined. - - Defined in svr4.h. */ -/* #define ASM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM any text - necessary for declaring the name NAME of an initialized variable which is - being defined. This macro must output the label definition (perhaps using - `ASM_OUTPUT_LABEL'). The argument DECL is the `VAR_DECL' tree node - representing the variable. - - If this macro is not defined, then the variable name is defined in the usual - manner as a label (by means of `ASM_OUTPUT_LABEL'). - - Defined in svr4.h. */ -/* #define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) */ - -/* A C statement (sans semicolon) to finish up declaring a variable name once - the compiler has processed its initializer fully and thus has had a chance - to determine the size of an array when controlled by an initializer. This - is used on systems where it's necessary to declare something about the size - of the object. - - If you don't define this macro, that is equivalent to defining it to do - nothing. - - Defined in svr4.h. */ -/* #define ASM_FINISH_DECLARE_OBJECT(STREAM, DECL, TOPLEVEL, ATEND) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM some - commands that will make the label NAME global; that is, available for - reference from other files. Use the expression `assemble_name (STREAM, - NAME)' to output the name itself; before and after that, output the - additional assembler syntax for making that name global, and a newline. */ - -#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \ -do { \ - fputs ("\t.globl ", STREAM); \ - assemble_name (STREAM, NAME); \ - fputs ("\n", STREAM); \ -} while (0) - -/* A C statement (sans semicolon) to output to the stdio stream STREAM some - commands that will make the label NAME weak; that is, available for - reference from other files but only used if no other definition is - available. Use the expression `assemble_name (STREAM, NAME)' to output the - name itself; before and after that, output the additional assembler syntax - for making that name weak, and a newline. - - If you don't define this macro, GNU CC will not support weak symbols and you - should not define the `SUPPORTS_WEAK' macro. - - Defined in svr4.h. */ -/* #define ASM_WEAKEN_LABEL */ - -/* A C expression which evaluates to true if the target supports weak symbols. - - If you don't define this macro, `defaults.h' provides a default definition. - If `ASM_WEAKEN_LABEL' is defined, the default definition is `1'; otherwise, - it is `0'. Define this macro if you want to control weak symbol support - with a compiler flag such as `-melf'. */ -/* #define SUPPORTS_WEAK */ - -/* A C statement (sans semicolon) to mark DECL to be emitted as a - public symbol such that extra copies in multiple translation units - will be discarded by the linker. Define this macro if your object - file format provides support for this concept, such as the `COMDAT' - section flags in the Microsoft Windows PE/COFF format, and this - support requires changes to DECL, such as putting it in a separate - section. - - Defined in svr4.h. */ -/* #define MAKE_DECL_ONE_ONLY */ - -/* A C expression which evaluates to true if the target supports one-only - semantics. - - If you don't define this macro, `varasm.c' provides a default definition. - If `MAKE_DECL_ONE_ONLY' is defined, the default definition is `1'; - otherwise, it is `0'. Define this macro if you want to control one-only - symbol support with a compiler flag, or if setting the `DECL_ONE_ONLY' flag - is enough to mark a declaration to be emitted as one-only. */ -/* #define SUPPORTS_ONE_ONLY */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM any text - necessary for declaring the name of an external symbol named NAME which is - referenced in this compilation but not defined. The value of DECL is the - tree node for the declaration. - - This macro need not be defined if it does not need to output anything. The - GNU assembler and most Unix assemblers don't require anything. */ -/* #define ASM_OUTPUT_EXTERNAL(STREAM, DECL, NAME) */ - -/* A C statement (sans semicolon) to output on STREAM an assembler pseudo-op to - declare a library function name external. The name of the library function - is given by SYMREF, which has type `rtx' and is a `symbol_ref'. - - This macro need not be defined if it does not need to output anything. The - GNU assembler and most Unix assemblers don't require anything. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM, SYMREF) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM a - reference in assembler syntax to a label named NAME. This should add `_' to - the front of the name, if that is customary on your operating system, as it - is in most Berkeley Unix systems. This macro is used in `assemble_name'. */ -/* #define ASM_OUTPUT_LABELREF(STREAM, NAME) */ - -/* A C statement to output to the stdio stream STREAM a label whose name is - made from the string PREFIX and the number NUM. - - It is absolutely essential that these labels be distinct from the labels - used for user-level functions and variables. Otherwise, certain programs - will have name conflicts with internal labels. - - It is desirable to exclude internal labels from the symbol table of the - object file. Most assemblers have a naming convention for labels that - should be excluded; on many systems, the letter `L' at the beginning of a - label has this effect. You should find out what convention your system - uses, and follow it. - - The usual definition of this macro is as follows: - - fprintf (STREAM, "L%s%d:\n", PREFIX, NUM) - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) */ - -/* A C statement to store into the string STRING a label whose name is made - from the string PREFIX and the number NUM. - - This string, when output subsequently by `assemble_name', should produce the - output that `ASM_OUTPUT_INTERNAL_LABEL' would produce with the same PREFIX - and NUM. - - If the string begins with `*', then `assemble_name' will output the rest of - the string unchanged. It is often convenient for - `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way. If the string doesn't - start with `*', then `ASM_OUTPUT_LABELREF' gets to output the string, and - may change it. (Of course, `ASM_OUTPUT_LABELREF' is also part of your - machine description, so you should know what it does on your machine.) - - Defined in svr4.h. */ - -/* -#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ -do { \ - sprintf (LABEL, "*.%s%d", PREFIX, NUM); \ -} while (0) -*/ - -/* A C expression to assign to OUTVAR (which is a variable of type `char *') a - newly allocated string made from the string NAME and the number NUMBER, with - some suitable punctuation added. Use `alloca' to get space for the string. - - The string will be used as an argument to `ASM_OUTPUT_LABELREF' to produce - an assembler label for an internal static variable whose name is NAME. - Therefore, the string must be such as to result in valid assembler code. - The argument NUMBER is different each time this macro is executed; it - prevents conflicts between similarly-named internal static variables in - different scopes. - - Ideally this string should not be a valid C identifier, to prevent any - conflict with the user's own symbols. Most assemblers allow periods or - percent signs in assembler symbols; putting at least one of these between - the name and the number will suffice. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTVAR, NAME, NUMBER) \ -do { \ - (OUTVAR) = (char *) alloca (strlen ((NAME)) + 12); \ - sprintf ((OUTVAR), "%s.%ld", (NAME), (long)(NUMBER)); \ -} while (0) - -/* A C statement to output to the stdio stream STREAM assembler code which - defines (equates) the symbol NAME to have the value VALUE. - - If SET_ASM_OP is defined, a default definition is provided which is correct - for most systems. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_DEF(STREAM, NAME, VALUE) */ - -/* A C statement to output to the stdio stream STREAM assembler code which - defines (equates) the weak symbol NAME to have the value VALUE. - - Define this macro if the target only supports weak aliases; define - ASM_OUTPUT_DEF instead if possible. */ -/* #define ASM_OUTPUT_WEAK_ALIAS (STREAM, NAME, VALUE) */ - -/* Define this macro to override the default assembler names used for Objective - C methods. - - The default name is a unique method number followed by the name of the class - (e.g. `_1_Foo'). For methods in categories, the name of the category is - also included in the assembler name (e.g. `_1_Foo_Bar'). - - These names are safe on most systems, but make debugging difficult since the - method's selector is not present in the name. Therefore, particular systems - define other ways of computing names. - - BUF is an expression of type `char *' which gives you a buffer in which to - store the name; its length is as long as CLASS_NAME, CAT_NAME and SEL_NAME - put together, plus 50 characters extra. - - The argument IS_INST specifies whether the method is an instance method or a - class method; CLASS_NAME is the name of the class; CAT_NAME is the name of - the category (or NULL if the method is not in a category); and SEL_NAME is - the name of the selector. - - On systems where the assembler can handle quoted names, you can use this - macro to provide more human-readable names. */ -/* #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME) */ - - -/* Macros Controlling Initialization Routines. */ - -/* If defined, a C string constant for the assembler operation to identify the - following data as initialization code. If not defined, GNU CC will assume - such a section does not exist. When you are using special sections for - initialization and termination functions, this macro also controls how - `crtstuff.c' and `libgcc2.c' arrange to run the initialization functions. - - Defined in svr4.h. */ -/* #define INIT_SECTION_ASM_OP */ -#undef INIT_SECTION_ASM_OP - -/* If defined, `main' will not call `__main' as described above. This macro - should be defined for systems that control the contents of the init section - on a symbol-by-symbol basis, such as OSF/1, and should not be defined - explicitly for systems that support `INIT_SECTION_ASM_OP'. */ -/* #define HAS_INIT_SECTION */ - -/* If defined, a C string constant for a switch that tells the linker that the - following symbol is an initialization routine. */ -/* #define LD_INIT_SWITCH */ - -/* If defined, a C string constant for a switch that tells the linker that the - following symbol is a finalization routine. */ -/* #define LD_FINI_SWITCH */ - -/* If defined, `main' will call `__main' despite the presence of - `INIT_SECTION_ASM_OP'. This macro should be defined for systems where the - init section is not actually run automatically, but is still useful for - collecting the lists of constructors and destructors. */ -#define INVOKE__main - -/* Define this macro as a C statement to output on the stream STREAM the - assembler code to arrange to call the function named NAME at initialization - time. - - Assume that NAME is the name of a C function generated automatically by the - compiler. This function takes no arguments. Use the function - `assemble_name' to output the name NAME; this performs any system-specific - syntactic transformations such as adding an underscore. - - If you don't define this macro, nothing special is output to arrange to call - the function. This is correct when the function will be called in some - other manner--for example, by means of the `collect2' program, which looks - through the symbol table to find these functions by their names. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_CONSTRUCTOR(STREAM, NAME) */ - -/* This is like `ASM_OUTPUT_CONSTRUCTOR' but used for termination functions - rather than initialization functions. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_DESTRUCTOR(STREAM, NAME) */ - -/* If your system uses `collect2' as the means of processing constructors, then - that program normally uses `nm' to scan an object file for constructor - functions to be called. On certain kinds of systems, you can define these - macros to make `collect2' work faster (and, in some cases, make it work at - all): */ - -/* Define this macro if the system uses COFF (Common Object File Format) object - files, so that `collect2' can assume this format and scan object files - directly for dynamic constructor/destructor functions. */ -/* #define OBJECT_FORMAT_COFF */ - -/* Define this macro if the system uses ROSE format object files, so that - `collect2' can assume this format and scan object files directly for dynamic - constructor/destructor functions. - - These macros are effective only in a native compiler; `collect2' as - part of a cross compiler always uses `nm' for the target machine. */ -/* #define OBJECT_FORMAT_ROSE */ - -/* Define this macro if the system uses ELF format object files. - - Defined in svr4.h. */ -/* #define OBJECT_FORMAT_ELF */ - -/* Define this macro as a C string constant containing the file name to use to - execute `nm'. The default is to search the path normally for `nm'. - - If your system supports shared libraries and has a program to list the - dynamic dependencies of a given library or executable, you can define these - macros to enable support for running initialization and termination - functions in shared libraries: */ -/* #define REAL_NM_FILE_NAME */ - -/* Define this macro to a C string constant containing the name of the program - which lists dynamic dependencies, like `"ldd"' under SunOS 4. */ -/* #define LDD_SUFFIX */ - -/* Define this macro to be C code that extracts filenames from the output of - the program denoted by `LDD_SUFFIX'. PTR is a variable of type `char *' - that points to the beginning of a line of output from `LDD_SUFFIX'. If the - line lists a dynamic dependency, the code must advance PTR to the beginning - of the filename on that line. Otherwise, it must set PTR to `NULL'. */ -/* #define PARSE_LDD_OUTPUT (PTR) */ - - -/* Output of Assembler Instructions. */ - -/* A C initializer containing the assembler's names for the machine registers, - each one as a C string constant. This is what translates register numbers - in the compiler into assembler language. */ -#define REGISTER_NAMES \ -{ \ - "r0", "r1", "r2", "r3", \ - "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", \ - "r12", "r13", "r14", "r15", \ - "r16", "r17", "r18", "r19", \ - "r20", "r21", "r22", "r23", \ - "r24", "r25", "r26", "r27", \ - "r28", "r29", "r30", "r31", \ - "r32", "r33", "r34", "r35", \ - "r36", "r37", "r38", "r39", \ - "r40", "r41", "r42", "r43", \ - "r44", "r45", "r46", "r47", \ - "r48", "r49", "r50", "r51", \ - "r52", "r53", "r54", "r55", \ - "r56", "r57", "r58", "r59", \ - "r60", "r61", "link", "sp", \ - "ap", \ - "f0", "f1", "f2", "f3", \ - "s", "v", "va", "c", \ - "a0", "a1", \ - "psw", "bpsw", "pc", "bpc", \ - "dpsw", "dpc", "rpt_c", "rpt_s", \ - "rpt_e", "mod_s", "mod_e", "iba", \ - "eit_vb", "int_s", "int_m", \ -} - -/* If defined, a C initializer for an array of structures containing a name and - a register number. This macro defines additional names for hard registers, - thus allowing the `asm' option in declarations to refer to registers using - alternate names. */ -#define ADDITIONAL_REGISTER_NAMES \ -{ \ - "r62", GPR_LINK, \ - "r63", GPR_SP, \ - "f4", FLAG_SAT, \ - "f5", FLAG_OVERFLOW, \ - "f6", FLAG_ACC_OVER, \ - "f7", FLAG_CARRY, \ - "carry", FLAG_CARRY, \ - "borrow", FLAG_BORROW, \ - "b", FLAG_BORROW, \ - "cr0", CR_PSW, \ - "cr1", CR_BPSW, \ - "cr2", CR_PC, \ - "cr3", CR_BPC, \ - "cr4", CR_DPSW, \ - "cr5", CR_DPC, \ - "cr7", CR_RPT_C, \ - "cr8", CR_RPT_S, \ - "cr9", CR_RPT_E, \ - "cr10", CR_MOD_S, \ - "cr11", CR_MOD_E, \ - "cr14", CR_IBA, \ - "cr15", CR_EIT_VB, \ - "cr16", CR_INT_S, \ - "cr17", CR_INT_M \ -} - -/* Define this macro if you are using an unusual assembler that requires - different names for the machine instructions. - - The definition is a C statement or statements which output an assembler - instruction opcode to the stdio stream STREAM. The macro-operand PTR is a - variable of type `char *' which points to the opcode name in its "internal" - form--the form that is written in the machine description. The definition - should output the opcode name to STREAM, performing any translation you - desire, and increment the variable PTR to point at the end of the opcode so - that it will not be output twice. - - In fact, your macro definition may process less than the entire opcode name, - or more than the opcode name; but if you want to process text that includes - `%'-sequences to substitute operands, you must take care of the substitution - yourself. Just be sure to increment PTR over whatever text should not be - output normally. - - If you need to look at the operand values, they can be found as the elements - of `recog_operand'. - - If the macro definition does nothing, the instruction is output in the usual - way. */ -/* #define ASM_OUTPUT_OPCODE(STREAM, PTR) */ - -/* If defined, a C statement to be executed just prior to the output of - assembler code for INSN, to modify the extracted operands so they will be - output differently. - - Here the argument OPVEC is the vector containing the operands extracted from - INSN, and NOPERANDS is the number of elements of the vector which contain - meaningful data for this insn. The contents of this vector are what will be - used to convert the insn template into assembler code, so you can change the - assembler output by changing the contents of the vector. - - This macro is useful when various assembler syntaxes share a single file of - instruction patterns; by defining this macro differently, you can cause a - large class of instructions to be output differently (such as with - rearranged operands). Naturally, variations in assembler syntax affecting - individual insn patterns ought to be handled by writing conditional output - routines in those patterns. - - If this macro is not defined, it is equivalent to a null statement. */ -/* #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) */ - -/* If defined, `FINAL_PRESCAN_INSN' will be called on each - `CODE_LABEL'. In that case, OPVEC will be a null pointer and - NOPERANDS will be zero. */ -/* #define FINAL_PRESCAN_LABEL */ - -/* A C compound statement to output to stdio stream STREAM the assembler syntax - for an instruction operand X. X is an RTL expression. - - CODE is a value that can be used to specify one of several ways of printing - the operand. It is used when identical operands must be printed differently - depending on the context. CODE comes from the `%' specification that was - used to request printing of the operand. If the specification was just - `%DIGIT' then CODE is 0; if the specification was `%LTR DIGIT' then CODE is - the ASCII code for LTR. - - If X is a register, this macro should print the register's name. The names - can be found in an array `reg_names' whose type is `char *[]'. `reg_names' - is initialized from `REGISTER_NAMES'. - - When the machine description has a specification `%PUNCT' (a `%' followed by - a punctuation character), this macro is called with a null pointer for X and - the punctuation character for CODE. - - Standard operand flags that are handled elsewhere: - `=' Output a number unique to each instruction in the compilation. - `a' Substitute an operand as if it were a memory reference. - `c' Omit the syntax that indicates an immediate operand. - `l' Substitute a LABEL_REF into a jump instruction. - `n' Like %cDIGIT, except negate the value before printing. - - The d30v specific operand flags are: - `.' Print r0. - `f' Print a SF constant as an int. - `s' Subtract 32 and negate. - `A' Print accumulator number without an `a' in front of it. - `B' Print bit offset for BSET, etc. instructions. - `E' Print u if this is zero extend, nothing if this is sign extend. - `F' Emit /{f,t,x}{f,t,x} for executing a false condition. - `L' Print the lower half of a 64 bit item. - `M' Print a memory reference for ld/st instructions. - `R' Return appropriate cmp instruction for relational test. - `S' Subtract 32. - `T' Emit /{f,t,x}{f,t,x} for executing a true condition. - `U' Print the upper half of a 64 bit item. */ - -#define PRINT_OPERAND(STREAM, X, CODE) d30v_print_operand (STREAM, X, CODE) - -/* A C expression which evaluates to true if CODE is a valid punctuation - character for use in the `PRINT_OPERAND' macro. If - `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no punctuation - characters (except for the standard one, `%') are used in this way. */ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '.') - -/* A C compound statement to output to stdio stream STREAM the assembler syntax - for an instruction operand that is a memory reference whose address is X. X - is an RTL expression. - - On some machines, the syntax for a symbolic address depends on the section - that the address refers to. On these machines, define the macro - `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and - then check for it here. *Note Assembler Format::. */ - -#define PRINT_OPERAND_ADDRESS(STREAM, X) d30v_print_operand_address (STREAM, X) - -/* 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(FILE) */ - -/* If defined, C string expressions to be used for the `%R', `%L', `%U', and - `%I' options of `asm_fprintf' (see `final.c'). These are useful when a - single `md' file must support multiple assembler formats. In that case, the - various `tm.h' files can define these macros differently. - - USER_LABEL_PREFIX is defined in svr4.h. */ - -#define REGISTER_PREFIX "%" -#define LOCAL_LABEL_PREFIX "." -#define USER_LABEL_PREFIX "" -#define IMMEDIATE_PREFIX "" - -/* If your target supports multiple dialects of assembler language (such as - different opcodes), define this macro as a C expression that gives the - numeric index of the assembler language dialect to use, with zero as the - first variant. - - If this macro is defined, you may use `{option0|option1|option2...}' - constructs in the output templates of patterns (*note Output Template::.) or - in the first argument of `asm_fprintf'. This construct outputs `option0', - `option1' or `option2', etc., if the value of `ASSEMBLER_DIALECT' is zero, - one or two, etc. Any special characters within these strings retain their - usual meaning. - - If you do not define this macro, the characters `{', `|' and `}' do not have - any special meaning when used in templates or operands to `asm_fprintf'. - - Define the macros `REGISTER_PREFIX', `LOCAL_LABEL_PREFIX', - `USER_LABEL_PREFIX' and `IMMEDIATE_PREFIX' if you can express the variations - in assemble language syntax with that mechanism. Define `ASSEMBLER_DIALECT' - and use the `{option0|option1}' syntax if the syntax variant are larger and - involve such things as different opcodes or operand order. */ -/* #define ASSEMBLER_DIALECT */ - -/* A C expression to output to STREAM some assembler code which will push hard - register number REGNO onto the stack. The code need not be optimal, since - this macro is used only when profiling. */ -/* #define ASM_OUTPUT_REG_PUSH (STREAM, REGNO) */ - -/* A C expression to output to STREAM some assembler code which will pop hard - register number REGNO off of the stack. The code need not be optimal, since - this macro is used only when profiling. */ -/* #define ASM_OUTPUT_REG_POP (STREAM, REGNO) */ - - -/* Output of dispatch tables. */ - -/* This macro should be provided on machines where the addresses in a dispatch - table are relative to the table's own address. - - The definition should be a C statement to output to the stdio stream STREAM - an assembler pseudo-instruction to generate a difference between two labels. - VALUE and REL are the numbers of two internal labels. The definitions of - these labels are output using `ASM_OUTPUT_INTERNAL_LABEL', and they must be - printed in the same way here. For example, - - fprintf (STREAM, "\t.word L%d-L%d\n", VALUE, REL) */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ -fprintf (STREAM, "\t.word .L%d-.L%d\n", VALUE, REL) - -/* This macro should be provided on machines where the addresses in a dispatch - table are absolute. - - The definition should be a C statement to output to the stdio stream STREAM - an assembler pseudo-instruction to generate a reference to a label. VALUE - is the number of an internal label whose definition is output using - `ASM_OUTPUT_INTERNAL_LABEL'. For example, - - fprintf (STREAM, "\t.word L%d\n", VALUE) */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ -fprintf (STREAM, "\t.word .L%d\n", VALUE) - -/* Define this if the label before a jump-table needs to be output specially. - The first three arguments are the same as for `ASM_OUTPUT_INTERNAL_LABEL'; - the fourth argument is the jump-table which follows (a `jump_insn' - containing an `addr_vec' or `addr_diff_vec'). - - This feature is used on system V to output a `swbeg' statement for the - table. - - If this macro is not defined, these labels are output with - `ASM_OUTPUT_INTERNAL_LABEL'. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, TABLE) */ - -/* Define this if something special must be output at the end of a jump-table. - The definition should be a C statement to be executed after the assembler - code for the table is written. It should write the appropriate code to - stdio stream STREAM. The argument TABLE is the jump-table insn, and NUM is - the label-number of the preceding label. - - If this macro is not defined, nothing special is output at the end of the - jump-table. */ -/* #define ASM_OUTPUT_CASE_END(STREAM, NUM, TABLE) */ - - -/* Assembler Commands for Exception Regions. */ - -/* A C expression to output text to mark the start of an exception region. - - This macro need not be defined on most platforms. */ -/* #define ASM_OUTPUT_EH_REGION_BEG() */ - -/* A C expression to output text to mark the end of an exception region. - - This macro need not be defined on most platforms. */ -/* #define ASM_OUTPUT_EH_REGION_END() */ - -/* A C expression to switch to the section in which the main exception table is - to be placed (*note Sections::.). The default is a section named - `.gcc_except_table' on machines that support named sections via - `ASM_OUTPUT_SECTION_NAME', otherwise if `-fpic' or `-fPIC' is in effect, the - `data_section', otherwise the `readonly_data_section'. */ -/* #define EXCEPTION_SECTION() */ - -/* If defined, a C string constant for the assembler operation to switch to the - section for exception handling frame unwind information. If not defined, - GNU CC will provide a default definition if the target supports named - sections. `crtstuff.c' uses this macro to switch to the appropriate - section. - - You should define this symbol if your target supports DWARF 2 frame unwind - information and the default definition does not work. */ -/* #define EH_FRAME_SECTION_ASM_OP */ - -/* A C expression that is nonzero if the normal exception table output should - be omitted. - - This macro need not be defined on most platforms. */ -/* #define OMIT_EH_TABLE() */ - -/* Alternate runtime support for looking up an exception at runtime and finding - the associated handler, if the default method won't work. - - This macro need not be defined on most platforms. */ -/* #define EH_TABLE_LOOKUP() */ - -/* A C expression that decides whether or not the current function needs to - have a function unwinder generated for it. See the file `except.c' for - details on when to define this, and how. */ -/* #define DOESNT_NEED_UNWINDER */ - -/* An rtx used to mask the return address found via RETURN_ADDR_RTX, so that it - does not contain any extraneous set bits in it. */ -/* #define MASK_RETURN_ADDR */ - -/* Define this macro to 0 if your target supports DWARF 2 frame unwind - information, but it does not yet work with exception handling. Otherwise, - if your target supports this information (if it defines - `INCOMING_RETURN_ADDR_RTX' and either `UNALIGNED_INT_ASM_OP' or - `OBJECT_FORMAT_ELF'), GCC will provide a default definition of 1. - - If this macro is defined to 1, the DWARF 2 unwinder will be the default - exception handling mechanism; otherwise, setjmp/longjmp will be used by - default. - - If this macro is defined to anything, the DWARF 2 unwinder will be used - instead of inline unwinders and __unwind_function in the non-setjmp case. */ -/* #define DWARF2_UNWIND_INFO */ - - -/* Assembler Commands for Alignment. */ - -/* The alignment (log base 2) to put in front of LABEL, which follows - a BARRIER. - - This macro need not be defined if you don't want any special alignment to be - done at such a time. Most machine descriptions do not currently define the - macro. */ -/* #define LABEL_ALIGN_AFTER_BARRIER(LABEL) */ - -/* The desired alignment for the location counter at the beginning - of a loop. - - This macro need not be defined if you don't want any special alignment to be - done at such a time. Most machine descriptions do not currently define the - macro. */ -/* #define LOOP_ALIGN(LABEL) */ - -/* A C statement to output to the stdio stream STREAM an assembler instruction - to advance the location counter by NBYTES bytes. Those bytes should be zero - when loaded. NBYTES will be a C expression of type `int'. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_SKIP(STREAM, NBYTES) \ - fprintf (STREAM, "\t.zero\t%u\n", (NBYTES)) */ - -/* Define this macro if `ASM_OUTPUT_SKIP' should not be used in the text - section because it fails put zeros in the bytes that are skipped. This is - true on many Unix systems, where the pseudo-op to skip bytes produces no-op - instructions rather than zeros when used in the text section. */ -/* #define ASM_NO_SKIP_IN_TEXT */ - -/* A C statement to output to the stdio stream STREAM an assembler command to - advance the location counter to a multiple of 2 to the POWER bytes. POWER - will be a C expression of type `int'. */ -#define ASM_OUTPUT_ALIGN(STREAM, POWER) \ - fprintf ((STREAM), "\t.p2align %d\n", (POWER)) - - -/* Macros Affecting all Debug Formats. */ - -/* A C expression that returns the DBX register number for the compiler - register number REGNO. In simple cases, the value of this expression may be - REGNO itself. But sometimes there are some registers that the compiler - knows about and DBX does not, or vice versa. In such cases, some register - may need to have one number in the compiler and another for DBX. - - If two registers have consecutive numbers inside GNU CC, and they can be - used as a pair to hold a multiword value, then they *must* have consecutive - numbers after renumbering with `DBX_REGISTER_NUMBER'. Otherwise, debuggers - will be unable to access such a pair, because they expect register pairs to - be consecutive in their own numbering scheme. - - If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not - preserve register pairs, then what you must do instead is redefine the - actual register numbering scheme. */ -#define DBX_REGISTER_NUMBER(REGNO) \ -(GPR_P (REGNO) ? ((REGNO) - GPR_FIRST) \ - : ACCUM_P (REGNO) ? ((REGNO) - ACCUM_FIRST + 84) \ - : FLAG_P (REGNO) ? 66 /* return psw for all flags */ \ - : (REGNO) == ARG_POINTER_REGNUM ? (GPR_SP - GPR_FIRST) \ - : (REGNO) == CR_PSW ? (66 + 0) \ - : (REGNO) == CR_BPSW ? (66 + 1) \ - : (REGNO) == CR_PC ? (66 + 2) \ - : (REGNO) == CR_BPC ? (66 + 3) \ - : (REGNO) == CR_DPSW ? (66 + 4) \ - : (REGNO) == CR_DPC ? (66 + 5) \ - : (REGNO) == CR_RPT_C ? (66 + 7) \ - : (REGNO) == CR_RPT_S ? (66 + 8) \ - : (REGNO) == CR_RPT_E ? (66 + 9) \ - : (REGNO) == CR_MOD_S ? (66 + 10) \ - : (REGNO) == CR_MOD_E ? (66 + 11) \ - : (REGNO) == CR_IBA ? (66 + 14) \ - : (REGNO) == CR_EIT_VB ? (66 + 15) \ - : (REGNO) == CR_INT_S ? (66 + 16) \ - : (REGNO) == CR_INT_M ? (66 + 17) \ - : -1) - -/* A C expression that returns the integer offset value for an automatic - variable having address X (an RTL expression). The default computation - assumes that X is based on the frame-pointer and gives the offset from the - frame-pointer. This is required for targets that produce debugging output - for DBX or COFF-style debugging output for SDB and allow the frame-pointer - to be eliminated when the `-g' options is used. */ -/* #define DEBUGGER_AUTO_OFFSET(X) */ - -/* A C expression that returns the integer offset value for an argument having - address X (an RTL expression). The nominal offset is OFFSET. */ -/* #define DEBUGGER_ARG_OFFSET(OFFSET, X) */ - -/* A C expression that returns the type of debugging output GNU CC produces - when the user specifies `-g' or `-ggdb'. Define this if you have arranged - for GNU CC to support more than one format of debugging output. Currently, - the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG', - `DWARF2_DEBUG', and `XCOFF_DEBUG'. - - The value of this macro only affects the default debugging output; the user - can always get a specific type of output by using `-gstabs', `-gcoff', - `-gdwarf-1', `-gdwarf-2', or `-gxcoff'. - - Defined in svr4.h. */ - -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG - - -/* Specific Options for DBX Output. */ - -/* Define this macro if GNU CC should produce debugging output for DBX in - response to the `-g' option. - - Defined in svr4.h. */ -/* #define DBX_DEBUGGING_INFO */ - -/* Define this macro if GNU CC should produce XCOFF format debugging output in - response to the `-g' option. This is a variant of DBX format. */ -/* #define XCOFF_DEBUGGING_INFO */ - -/* Define this macro to control whether GNU CC should by default generate GDB's - extended version of DBX debugging information (assuming DBX-format debugging - information is enabled at all). If you don't define the macro, the default - is 1: always generate the extended information if there is any occasion to. */ -/* #define DEFAULT_GDB_EXTENSIONS */ - -/* Define this macro if all `.stabs' commands should be output while in the - text section. */ -/* #define DEBUG_SYMS_TEXT */ - -/* A C string constant naming the assembler pseudo op to use instead of - `.stabs' to define an ordinary debugging symbol. If you don't define this - macro, `.stabs' is used. This macro applies only to DBX debugging - information format. */ -/* #define ASM_STABS_OP */ - -/* A C string constant naming the assembler pseudo op to use instead of - `.stabd' to define a debugging symbol whose value is the current location. - If you don't define this macro, `.stabd' is used. This macro applies only - to DBX debugging information format. */ -/* #define ASM_STABD_OP */ - -/* A C string constant naming the assembler pseudo op to use instead of - `.stabn' to define a debugging symbol with no name. If you don't define - this macro, `.stabn' is used. This macro applies only to DBX debugging - information format. */ -/* #define ASM_STABN_OP */ - -/* Define this macro if DBX on your system does not support the construct - `xsTAGNAME'. On some systems, this construct is used to describe a forward - reference to a structure named TAGNAME. On other systems, this construct is - not supported at all. */ -/* #define DBX_NO_XREFS */ - -/* A symbol name in DBX-format debugging information is normally continued - (split into two separate `.stabs' directives) when it exceeds a certain - length (by default, 80 characters). On some operating systems, DBX requires - this splitting; on others, splitting must not be done. You can inhibit - splitting by defining this macro with the value zero. You can override the - default splitting-length by defining this macro as an expression for the - length you desire. */ -/* #define DBX_CONTIN_LENGTH */ - -/* Normally continuation is indicated by adding a `\' character to the end of a - `.stabs' string when a continuation follows. To use a different character - instead, define this macro as a character constant for the character you - want to use. Do not define this macro if backslash is correct for your - system. */ -/* #define DBX_CONTIN_CHAR */ - -/* Define this macro if it is necessary to go to the data section before - outputting the `.stabs' pseudo-op for a non-global static variable. */ -/* #define DBX_STATIC_STAB_DATA_SECTION */ - -/* The value to use in the "code" field of the `.stabs' directive for a - typedef. The default is `N_LSYM'. */ -/* #define DBX_TYPE_DECL_STABS_CODE */ - -/* The value to use in the "code" field of the `.stabs' directive for a static - variable located in the text section. DBX format does not provide any - "right" way to do this. The default is `N_FUN'. */ -/* #define DBX_STATIC_CONST_VAR_CODE */ - -/* The value to use in the "code" field of the `.stabs' directive for a - parameter passed in registers. DBX format does not provide any "right" way - to do this. The default is `N_RSYM'. */ -/* #define DBX_REGPARM_STABS_CODE */ - -/* The letter to use in DBX symbol data to identify a symbol as a parameter - passed in registers. DBX format does not customarily provide any way to do - this. The default is `'P''. */ -/* #define DBX_REGPARM_STABS_LETTER */ - -/* The letter to use in DBX symbol data to identify a symbol as a stack - parameter. The default is `'p''. */ -/* #define DBX_MEMPARM_STABS_LETTER */ - -/* Define this macro if the DBX information for a function and its arguments - should precede the assembler code for the function. Normally, in DBX - format, the debugging information entirely follows the assembler code. - - Defined in svr4.h. */ -/* #define DBX_FUNCTION_FIRST */ - -/* Define this macro if the `N_LBRAC' symbol for a block should precede the - debugging information for variables and functions defined in that block. - Normally, in DBX format, the `N_LBRAC' symbol comes first. */ -/* #define DBX_LBRAC_FIRST */ - -/* Define this macro if the value of a symbol describing the scope of a block - (`N_LBRAC' or `N_RBRAC') should be relative to the start of the enclosing - function. Normally, GNU C uses an absolute address. - - Defined in svr4.h. */ -/* #define DBX_BLOCKS_FUNCTION_RELATIVE */ - -/* Define this macro if GNU C should generate `N_BINCL' and `N_EINCL' - stabs for included header files, as on Sun systems. This macro - also directs GNU C to output a type number as a pair of a file - number and a type number within the file. Normally, GNU C does not - generate `N_BINCL' or `N_EINCL' stabs, and it outputs a single - number for a type number. */ -/* #define DBX_USE_BINCL */ - - -/* Open ended Hooks for DBX Output. */ - -/* Define this macro to say how to output to STREAM the debugging information - for the start of a scope level for variable names. The argument NAME is the - name of an assembler symbol (for use with `assemble_name') whose value is - the address where the scope begins. */ -/* #define DBX_OUTPUT_LBRAC(STREAM, NAME) */ - -/* Like `DBX_OUTPUT_LBRAC', but for the end of a scope level. */ -/* #define DBX_OUTPUT_RBRAC(STREAM, NAME) */ - -/* Define this macro if the target machine requires special handling to output - an enumeration type. The definition should be a C statement (sans - semicolon) to output the appropriate information to STREAM for the type - TYPE. */ -/* #define DBX_OUTPUT_ENUM(STREAM, TYPE) */ - -/* Define this macro if the target machine requires special output at the end - of the debugging information for a function. The definition should be a C - statement (sans semicolon) to output the appropriate information to STREAM. - FUNCTION is the `FUNCTION_DECL' node for the function. */ -/* #define DBX_OUTPUT_FUNCTION_END(STREAM, FUNCTION) */ - -/* Define this macro if you need to control the order of output of the standard - data types at the beginning of compilation. The argument SYMS is a `tree' - which is a chain of all the predefined global symbols, including names of - data types. - - Normally, DBX output starts with definitions of the types for integers and - characters, followed by all the other predefined types of the particular - language in no particular order. - - On some machines, it is necessary to output different particular types - first. To do this, define `DBX_OUTPUT_STANDARD_TYPES' to output those - symbols in the necessary order. Any predefined types that you don't - explicitly output will be output afterward in no particular order. - - Be careful not to define this macro so that it works only for C. There are - no global variables to access most of the built-in types, because another - language may have another set of types. The way to output a particular type - is to look through SYMS to see if you can find it. Here is an example: - - { - tree decl; - for (decl = syms; decl; decl = TREE_CHAIN (decl)) - if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), - "long int")) - dbxout_symbol (decl); - ... - } - - This does nothing if the expected type does not exist. - - See the function `init_decl_processing' in `c-decl.c' to find the names to - use for all the built-in C types. */ -/* #define DBX_OUTPUT_STANDARD_TYPES(SYMS) */ - -/* Some stabs encapsulation formats (in particular ECOFF), cannot - handle the `.stabs "",N_FUN,,0,0,Lscope-function-1' gdb dbx - extention construct. On those machines, define this macro to turn - this feature off without disturbing the rest of the gdb extensions. */ -/* #define NO_DBX_FUNCTION_END */ - - -/* File names in DBX format. */ - -/* Define this if DBX wants to have the current directory recorded in each - object file. - - Note that the working directory is always recorded if GDB extensions are - enabled. */ -/* #define DBX_WORKING_DIRECTORY */ - -/* A C statement to output DBX debugging information to the stdio stream STREAM - which indicates that file NAME is the main source file--the file specified - as the input file for compilation. This macro is called only once, at the - beginning of compilation. - - This macro need not be defined if the standard form of output for DBX - debugging information is appropriate. - - Defined in svr4.h. */ -/* #define DBX_OUTPUT_MAIN_SOURCE_FILENAME(STREAM, NAME) */ - -/* A C statement to output DBX debugging information to the stdio stream STREAM - which indicates that the current directory during compilation is named NAME. - - This macro need not be defined if the standard form of output for DBX - debugging information is appropriate. */ -/* #define DBX_OUTPUT_MAIN_SOURCE_DIRECTORY(STREAM, NAME) */ - -/* A C statement to output DBX debugging information at the end of compilation - of the main source file NAME. - - If you don't define this macro, nothing special is output at the end of - compilation, which is correct for most machines. */ -/* #define DBX_OUTPUT_MAIN_SOURCE_FILE_END(STREAM, NAME) */ - -/* A C statement to output DBX debugging information to the stdio stream STREAM - which indicates that file NAME is the current source file. This output is - generated each time input shifts to a different source file as a result of - `#include', the end of an included file, or a `#line' command. - - This macro need not be defined if the standard form of output for DBX - debugging information is appropriate. */ -/* #define DBX_OUTPUT_SOURCE_FILENAME(STREAM, NAME) */ - - -/* Macros for SDB and Dwarf Output. */ - -/* Define this macro if GNU CC should produce COFF-style debugging output for - SDB in response to the `-g' option. */ -/* #define SDB_DEBUGGING_INFO */ - -/* Define this macro if GNU CC should produce dwarf format debugging output in - response to the `-g' option. - - Defined in svr4.h. */ -/* #define DWARF_DEBUGGING_INFO */ - -/* Define this macro if GNU CC should produce dwarf version 2 format debugging - output in response to the `-g' option. - - To support optional call frame debugging information, you must also define - `INCOMING_RETURN_ADDR_RTX' and either set `RTX_FRAME_RELATED_P' on the - prologue insns if you use RTL for the prologue, or call `dwarf2out_def_cfa' - and `dwarf2out_reg_save' as appropriate from `FUNCTION_PROLOGUE' if you - don't. - - Defined in svr4.h. */ -/* #define DWARF2_DEBUGGING_INFO */ - -/* Define these macros to override the assembler syntax for the special SDB - assembler directives. See `sdbout.c' for a list of these macros and their - arguments. If the standard syntax is used, you need not define them - yourself. */ -/* #define PUT_SDB_... */ - -/* Some assemblers do not support a semicolon as a delimiter, even between SDB - assembler directives. In that case, define this macro to be the delimiter - to use (usually `\n'). It is not necessary to define a new set of - `PUT_SDB_OP' macros if this is the only change required. */ -/* #define SDB_DELIM */ - -/* Define this macro to override the usual method of constructing a dummy name - for anonymous structure and union types. See `sdbout.c' for more - information. */ -/* #define SDB_GENERATE_FAKE */ - -/* Define this macro to allow references to unknown structure, union, or - enumeration tags to be emitted. Standard COFF does not allow handling of - unknown references, MIPS ECOFF has support for it. */ -/* #define SDB_ALLOW_UNKNOWN_REFERENCES */ - -/* Define this macro to allow references to structure, union, or enumeration - tags that have not yet been seen to be handled. Some assemblers choke if - forward tags are used, while some require it. */ -/* #define SDB_ALLOW_FORWARD_REFERENCES */ - - -/* Cross Compilation and Floating Point. */ - -/* While all modern machines use 2's complement representation for integers, - there are a variety of representations for floating point numbers. This - means that in a cross-compiler the representation of floating point numbers - in the compiled program may be different from that used in the machine doing - the compilation. - - Because different representation systems may offer different amounts of - range and precision, the cross compiler cannot safely use the host machine's - floating point arithmetic. Therefore, floating point constants must be - represented in the target machine's format. This means that the cross - compiler cannot use `atof' to parse a floating point constant; it must have - its own special routine to use instead. Also, constant folding must emulate - the target machine's arithmetic (or must not be done at all). - - The macros in the following table should be defined only if you are cross - compiling between different floating point formats. - - Otherwise, don't define them. Then default definitions will be set up which - use `double' as the data type, `==' to test for equality, etc. - - You don't need to worry about how many times you use an operand of any of - these macros. The compiler never uses operands which have side effects. */ - -/* A macro for the C data type to be used to hold a floating point value in the - target machine's format. Typically this would be a `struct' containing an - array of `int'. */ -/* #define REAL_VALUE_TYPE */ - -/* A macro for a C expression which compares for equality the two values, X and - Y, both of type `REAL_VALUE_TYPE'. */ -/* #define REAL_VALUES_EQUAL(X, Y) */ - -/* A macro for a C expression which tests whether X is less than Y, both values - being of type `REAL_VALUE_TYPE' and interpreted as floating point numbers in - the target machine's representation. */ -/* #define REAL_VALUES_LESS(X, Y) */ - -/* A macro for a C expression which performs the standard library function - `ldexp', but using the target machine's floating point representation. Both - X and the value of the expression have type `REAL_VALUE_TYPE'. The second - argument, SCALE, is an integer. */ -/* #define REAL_VALUE_LDEXP(X, SCALE) */ - -/* A macro whose definition is a C expression to convert the target-machine - floating point value X to a signed integer. X has type `REAL_VALUE_TYPE'. */ -/* #define REAL_VALUE_FIX(X) */ - -/* A macro whose definition is a C expression to convert the target-machine - floating point value X to an unsigned integer. X has type - `REAL_VALUE_TYPE'. */ -/* #define REAL_VALUE_UNSIGNED_FIX(X) */ - -/* A macro whose definition is a C expression to round the target-machine - floating point value X towards zero to an integer value (but still as a - floating point number). X has type `REAL_VALUE_TYPE', and so does the - value. */ -/* #define REAL_VALUE_RNDZINT(X) */ - -/* A macro whose definition is a C expression to round the target-machine - floating point value X towards zero to an unsigned integer value (but still - represented as a floating point number). X has type `REAL_VALUE_TYPE', and - so does the value. */ -/* #define REAL_VALUE_UNSIGNED_RNDZINT(X) */ - -/* A macro for a C expression which converts STRING, an expression of type - `char *', into a floating point number in the target machine's - representation for mode MODE. The value has type `REAL_VALUE_TYPE'. */ -/* #define REAL_VALUE_ATOF(STRING, MODE) */ - -/* Define this macro if infinity is a possible floating point value, and - therefore division by 0 is legitimate. */ -/* #define REAL_INFINITY */ - -/* A macro for a C expression which determines whether X, a floating point - value, is infinity. The value has type `int'. By default, this is defined - to call `isinf'. */ -/* #define REAL_VALUE_ISINF(X) */ - -/* A macro for a C expression which determines whether X, a floating point - value, is a "nan" (not-a-number). The value has type `int'. By default, - this is defined to call `isnan'. */ -/* #define REAL_VALUE_ISNAN(X) */ - -/* Define the following additional macros if you want to make floating point - constant folding work while cross compiling. If you don't define them, - cross compilation is still possible, but constant folding will not happen - for floating point values. */ - -/* A macro for a C statement which calculates an arithmetic operation of the - two floating point values X and Y, both of type `REAL_VALUE_TYPE' in the - target machine's representation, to produce a result of the same type and - representation which is stored in OUTPUT (which will be a variable). - - The operation to be performed is specified by CODE, a tree code which will - always be one of the following: `PLUS_EXPR', `MINUS_EXPR', `MULT_EXPR', - `RDIV_EXPR', `MAX_EXPR', `MIN_EXPR'. - - The expansion of this macro is responsible for checking for overflow. If - overflow happens, the macro expansion should execute the statement `return - 0;', which indicates the inability to perform the arithmetic operation - requested. */ -/* #define REAL_ARITHMETIC(OUTPUT, CODE, X, Y) */ - -/* The real.h file actually defines REAL_ARITHMETIC appropriately if it was - defined at all before entering into the code, by using #undef first. */ -#define REAL_ARITHMETIC - -/* A macro for a C expression which returns the negative of the floating point - value X. Both X and the value of the expression have type `REAL_VALUE_TYPE' - and are in the target machine's floating point representation. - - There is no way for this macro to report overflow, since overflow can't - happen in the negation operation. */ -/* #define REAL_VALUE_NEGATE(X) */ - -/* A macro for a C expression which converts the floating point value X to mode - MODE. - - Both X and the value of the expression are in the target machine's floating - point representation and have type `REAL_VALUE_TYPE'. However, the value - should have an appropriate bit pattern to be output properly as a floating - constant whose precision accords with mode MODE. - - There is no way for this macro to report overflow. */ -/* #define REAL_VALUE_TRUNCATE(MODE, X) */ - -/* A macro for a C expression which converts a floating point value X into a - double-precision integer which is then stored into LOW and HIGH, two - variables of type INT. */ -/* #define REAL_VALUE_TO_INT(LOW, HIGH, X) */ - -/* A macro for a C expression which converts a double-precision integer found - in LOW and HIGH, two variables of type INT, into a floating point value - which is then stored into X. */ -/* #define REAL_VALUE_FROM_INT(X, LOW, HIGH) */ - - -/* Miscellaneous Parameters. */ - -/* Define this if you have defined special-purpose predicates in the file - `MACHINE.c'. This macro is called within an initializer of an array of - structures. The first field in the structure is the name of a predicate and - the second field is an array of rtl codes. For each predicate, list all rtl - codes that can be in expressions matched by the predicate. The list should - have a trailing comma. Here is an example of two entries in the list for a - typical RISC machine: - - #define PREDICATE_CODES \ - {"gen_reg_rtx_operand", {SUBREG, REG}}, \ - {"reg_or_short_cint_operand", {SUBREG, REG, CONST_INT}}, - - Defining this macro does not affect the generated code (however, incorrect - definitions that omit an rtl code that may be matched by the predicate can - cause the compiler to malfunction). Instead, it allows the table built by - `genrecog' to be more compact and efficient, thus speeding up the compiler. - The most important predicates to include in the list specified by this macro - are thoses used in the most insn patterns. */ - -#define PREDICATE_CODES \ - { "short_memory_operand", { MEM }}, \ - { "long_memory_operand", { MEM }}, \ - { "d30v_memory_operand", { MEM }}, \ - { "single_reg_memory_operand", { MEM }}, \ - { "const_addr_memory_operand", { MEM }}, \ - { "call_operand", { MEM }}, \ - { "gpr_operand", { REG, SUBREG }}, \ - { "accum_operand", { REG, SUBREG }}, \ - { "gpr_or_accum_operand", { REG, SUBREG }}, \ - { "cr_operand", { REG, SUBREG }}, \ - { "repeat_operand", { REG, SUBREG }}, \ - { "flag_operand", { REG, SUBREG }}, \ - { "br_flag_operand", { REG, SUBREG }}, \ - { "br_flag_or_constant_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_br_flag_operand", { REG, SUBREG }}, \ - { "f0_operand", { REG, SUBREG }}, \ - { "f1_operand", { REG, SUBREG }}, \ - { "carry_operand", { REG, SUBREG }}, \ - { "reg_or_0_operand", { REG, SUBREG, CONST_INT, \ - CONST_DOUBLE }}, \ - { "gpr_or_signed6_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_unsigned5_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_unsigned6_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_constant_operand", { REG, SUBREG, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF }}, \ - { "gpr_or_dbl_const_operand", { REG, SUBREG, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF, CONST_DOUBLE }}, \ - { "gpr_or_memory_operand", { REG, SUBREG, MEM }}, \ - { "move_input_operand", { REG, SUBREG, MEM, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF, CONST_DOUBLE }}, \ - { "move_output_operand", { REG, SUBREG, MEM }}, \ - { "signed6_operand", { CONST_INT }}, \ - { "unsigned5_operand", { CONST_INT }}, \ - { "unsigned6_operand", { CONST_INT }}, \ - { "bitset_operand", { CONST_INT }}, \ - { "condexec_test_operator", { EQ, NE }}, \ - { "condexec_branch_operator", { EQ, NE }}, \ - { "condexec_unary_operator", { ABS, NEG, NOT, ZERO_EXTEND }}, \ - { "condexec_addsub_operator", { PLUS, MINUS }}, \ - { "condexec_binary_operator", { MULT, AND, IOR, XOR, \ - ASHIFT, ASHIFTRT, LSHIFTRT, \ - ROTATE, ROTATERT }}, \ - { "condexec_shiftl_operator", { ASHIFT, ROTATE }}, \ - { "condexec_extend_operator", { SIGN_EXTEND, ZERO_EXTEND }}, \ - { "branch_zero_operator", { EQ, NE }}, \ - { "cond_move_operand", { REG, SUBREG, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF, MEM }}, \ - { "cond_exec_operand", { REG, SUBREG, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF, MEM }}, \ - { "srelational_si_operator", { EQ, NE, LT, LE, GT, GE }}, \ - { "urelational_si_operator", { LTU, LEU, GTU, GEU }}, \ - { "relational_di_operator", { EQ, NE, LT, LE, GT, GE, \ - LTU, LEU, GTU, GEU }}, - -/* An alias for a machine mode name. This is the machine mode that elements of - a jump-table should have. */ -#define CASE_VECTOR_MODE SImode - -/* Define 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 if control falls through a `case' insn when the index value is - out of range. This means the specified default-label is actually ignored by - the `case' insn proper. */ -/* #define CASE_DROPS_THROUGH */ - -/* Define this to be the smallest number of different values for which it is - best to use a jump-table instead of a tree of conditional branches. The - default is four for machines with a `casesi' instruction and five otherwise. - This is best for most machines. */ -/* #define CASE_VALUES_THRESHOLD */ - -/* Define this macro if operations between registers with integral mode smaller - than a word are always performed on the entire register. Most RISC machines - have this property and most CISC machines do not. */ -#define WORD_REGISTER_OPERATIONS 1 - -/* Define this macro to be a C expression indicating when insns that read - memory in MODE, an integral mode narrower than a word, set the bits outside - of MODE to be either the sign-extension or the zero-extension of the data - read. Return `SIGN_EXTEND' for values of MODE for which the insn - sign-extends, `ZERO_EXTEND' for which it zero-extends, and `NIL' for other - modes. - - This macro is not called with MODE non-integral or with a width greater than - or equal to `BITS_PER_WORD', so you may return any value in this case. Do - not define this macro if it would always return `NIL'. On machines where - this macro is defined, you will normally define it as the constant - `SIGN_EXTEND' or `ZERO_EXTEND'. */ - -#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND - -/* Define if loading short immediate values into registers sign extends. */ -#define SHORT_IMMEDIATES_SIGN_EXTEND - -/* An alias for a tree code that should be used by default for conversion of - floating point values to fixed point. Normally, `FIX_ROUND_EXPR' is used. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* Define this macro if the same instructions that convert a floating point - number to a signed fixed point number also convert validly to an unsigned - one. */ -/* #define FIXUNS_TRUNC_LIKE_FIX_TRUNC */ - -/* An alias for a tree code that is the easiest kind of division to compile - code for in the general case. It may be `TRUNC_DIV_EXPR', `FLOOR_DIV_EXPR', - `CEIL_DIV_EXPR' or `ROUND_DIV_EXPR'. These four division operators differ - in how they round the result to an integer. `EASY_DIV_EXPR' is used when it - is permissible to use any of those kinds of division and the choice should - be made on the basis of efficiency. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* The maximum number of bytes that a single instruction can move quickly from - memory to memory. */ -#define MOVE_MAX 8 - -/* The maximum number of bytes that a single instruction can move quickly from - memory to memory. If this is undefined, the default is `MOVE_MAX'. - Otherwise, it is the constant value that is the largest value that - `MOVE_MAX' can have at run-time. */ -/* #define MAX_MOVE_MAX */ - -/* A C expression that is nonzero if on this machine the number of bits - actually used for the count of a shift operation is equal to the number of - bits needed to represent the size of the object being shifted. When this - macro is non-zero, the compiler will assume that it is safe to omit a - sign-extend, zero-extend, and certain bitwise `and' instructions that - truncates the count of a shift operation. On machines that have - instructions that act on bitfields at variable positions, which may include - `bit test' instructions, a nonzero `SHIFT_COUNT_TRUNCATED' also enables - deletion of truncations of the values that serve as arguments to bitfield - instructions. - - If both types of instructions truncate the count (for shifts) and position - (for bitfield operations), or if no variable-position bitfield instructions - exist, you should define this macro. - - However, on some machines, such as the 80386 and the 680x0, truncation only - applies to shift operations and not the (real or pretended) bitfield - operations. Define `SHIFT_COUNT_TRUNCATED' to be zero on such machines. - Instead, add patterns to the `md' file that include the implied truncation - of the shift instructions. - - You need not define this macro if it would always have the value of zero. */ -/* #define SHIFT_COUNT_TRUNCATED */ - -/* A C expression which is nonzero if on this machine it is safe to "convert" - an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller - than INPREC) by merely operating on it as if it had only OUTPREC bits. - - On many machines, this expression can be 1. - - When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for - which `MODES_TIEABLE_P' is 0, suboptimal code can result. If this is the - case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve - things. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* A C expression describing the value returned by a comparison operator with - an integral mode and stored by a store-flag instruction (`sCOND') when the - condition is true. This description must apply to *all* the `sCOND' - patterns and all the comparison operators whose results have a `MODE_INT' - mode. - - A value of 1 or -1 means that the instruction implementing the comparison - operator returns exactly 1 or -1 when the comparison is true and 0 when the - comparison is false. Otherwise, the value indicates which bits of the - result are guaranteed to be 1 when the comparison is true. This value is - interpreted in the mode of the comparison operation, which is given by the - mode of the first operand in the `sCOND' pattern. Either the low bit or the - sign bit of `STORE_FLAG_VALUE' be on. Presently, only those bits are used - by the compiler. - - If `STORE_FLAG_VALUE' is neither 1 or -1, the compiler will generate code - that depends only on the specified bits. It can also replace comparison - operators with equivalent operations if they cause the required bits to be - set, even if the remaining bits are undefined. For example, on a machine - whose comparison operators return an `SImode' value and where - `STORE_FLAG_VALUE' is defined as `0x80000000', saying that just the sign bit - is relevant, the expression - - (ne:SI (and:SI X (const_int POWER-OF-2)) (const_int 0)) - - can be converted to - - (ashift:SI X (const_int N)) - - where N is the appropriate shift count to move the bit being tested into the - sign bit. - - There is no way to describe a machine that always sets the low-order bit for - a true value, but does not guarantee the value of any other bits, but we do - not know of any machine that has such an instruction. If you are trying to - port GNU CC to such a machine, include an instruction to perform a - logical-and of the result with 1 in the pattern for the comparison operators - and let us know (*note How to Report Bugs: Bug Reporting.). - - Often, a machine will have multiple instructions that obtain a value from a - comparison (or the condition codes). Here are rules to guide the choice of - value for `STORE_FLAG_VALUE', and hence the instructions to be used: - - * Use the shortest sequence that yields a valid definition for - `STORE_FLAG_VALUE'. It is more efficient for the compiler to - "normalize" the value (convert it to, e.g., 1 or 0) than for - the comparison operators to do so because there may be - opportunities to combine the normalization with other - operations. - - * For equal-length sequences, use a value of 1 or -1, with -1 - being slightly preferred on machines with expensive jumps and - 1 preferred on other machines. - - * As a second choice, choose a value of `0x80000001' if - instructions exist that set both the sign and low-order bits - but do not define the others. - - * Otherwise, use a value of `0x80000000'. - - Many machines can produce both the value chosen for `STORE_FLAG_VALUE' and - its negation in the same number of instructions. On those machines, you - should also define a pattern for those cases, e.g., one matching - - (set A (neg:M (ne:M B C))) - - Some machines can also perform `and' or `plus' operations on condition code - values with less instructions than the corresponding `sCOND' insn followed - by `and' or `plus'. On those machines, define the appropriate patterns. - Use the names `incscc' and `decscc', respectively, for the the patterns - which perform `plus' or `minus' operations on condition code values. See - `rs6000.md' for some examples. The GNU Superoptizer can be used to find - such instruction sequences on other machines. - - You need not define `STORE_FLAG_VALUE' if the machine has no store-flag - instructions. */ -/* #define STORE_FLAG_VALUE */ - -/* A C expression that gives a non-zero floating point value that is returned - when comparison operators with floating-point results are true. Define this - macro on machine that have comparison operations that return floating-point - values. If there are no such operations, do not define this macro. */ -/* #define FLOAT_STORE_FLAG_VALUE */ - -/* An alias for the machine mode for pointers. On most machines, define this - to be the integer mode corresponding to the width of a hardware pointer; - `SImode' on 32-bit machine or `DImode' on 64-bit machines. On some machines - you must define this to be one of the partial integer modes, such as - `PSImode'. - - The width of `Pmode' must be at least as large as the value of - `POINTER_SIZE'. If it is not equal, you must define the macro - `POINTERS_EXTEND_UNSIGNED' to specify how pointers are extended to `Pmode'. */ -#define Pmode SImode - -/* An alias for the machine mode used for memory references to functions being - called, in `call' RTL expressions. On most machines this should be - `QImode'. */ -#define FUNCTION_MODE QImode - -/* A C expression for the maximum number of instructions above which the - function DECL should not be inlined. DECL is a `FUNCTION_DECL' node. - - The default definition of this macro is 64 plus 8 times the number of - arguments that the function accepts. Some people think a larger threshold - should be used on RISC machines. */ -/* #define INTEGRATE_THRESHOLD(DECL) */ - -/* Define this if the preprocessor should ignore `#sccs' directives and print - no error message. - - Defined in svr4.h. */ -/* #define SCCS_DIRECTIVE */ - -/* Define this macro if the system header files support C++ as well as C. This - macro inhibits the usual method of using system header files in C++, which - is to pretend that the file's contents are enclosed in `extern "C" {...}'. */ -/* #define NO_IMPLICIT_EXTERN_C */ - -/* Define this macro if you want to implement any pragmas. If defined, it - should be a C statement to be executed when `#pragma' is seen. The argument - STREAM is the stdio input stream from which the source text can be read. - - It is generally a bad idea to implement new uses of `#pragma'. The only - reason to define this macro is for compatibility with other compilers that - do support `#pragma' for the sake of any user programs which already use it. */ -/* #define HANDLE_PRAGMA(STREAM) */ - -/* Define this macro to handle System V style pragmas (particularly #pack). - - Defined in svr4.h. */ -#define HANDLE_SYSV_PRAGMA - -/* Define this macro if you want to handle #pragma weak (HANDLE_SYSV_PRAGMA - must also be defined). */ -/* #define HANDLE_WEAK_PRAGMA */ - -/* If defined, a C expression whose value is nonzero if IDENTIFIER with - arguments ARGS is a valid machine specific attribute for DECL. The - attributes in ATTRIBUTES have previously been assigned to DECL. */ -/* #define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) */ - -/* If defined, a C expression whose value is nonzero if IDENTIFIER with - arguments ARGS is a valid machine specific attribute for TYPE. The - attributes in ATTRIBUTES have previously been assigned to TYPE. */ -/* #define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, IDENTIFIER, ARGS) */ - -/* If defined, a C expression whose value is zero if the attributes on TYPE1 - and TYPE2 are incompatible, one if they are compatible, and two if they are - nearly compatible (which causes a warning to be generated). */ -/* #define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) */ - -/* If defined, a C statement that assigns default attributes to newly defined - TYPE. */ -/* #define SET_DEFAULT_TYPE_ATTRIBUTES(TYPE) */ - -/* Define this macro to control use of the character `$' in identifier names. - The value should be 0, 1, or 2. 0 means `$' is not allowed by default; 1 - means it is allowed by default if `-traditional' is used; 2 means it is - allowed by default provided `-ansi' is not used. 1 is the default; there is - no need to define this macro in that case. */ -/* #define DOLLARS_IN_IDENTIFIERS */ - -/* Define this macro if the assembler does not accept the character `$' in - label names. By default constructors and destructors in G++ have `$' in the - identifiers. If this macro is defined, `.' is used instead. - - Defined in svr4.h. */ -/* #define NO_DOLLAR_IN_LABEL */ - -/* Define this macro if the assembler does not accept the character `.' in - label names. By default constructors and destructors in G++ have names that - use `.'. If this macro is defined, these names are rewritten to avoid `.'. */ -/* #define NO_DOT_IN_LABEL */ - -/* Define this macro if the target system expects every program's `main' - function to return a standard "success" value by default (if no other value - is explicitly returned). - - The definition should be a C statement (sans semicolon) to generate the - appropriate rtl instructions. It is used only when compiling the end of - `main'. */ -/* #define DEFAULT_MAIN_RETURN */ - -/* Define this if the target system supports the function `atexit' from the - ANSI C standard. If this is not defined, and `INIT_SECTION_ASM_OP' is not - defined, a default `exit' function will be provided to support C++. - - Defined by svr4.h */ -/* #define HAVE_ATEXIT */ - -/* Define this if your `exit' function needs to do something besides calling an - external function `_cleanup' before terminating with `_exit'. The - `EXIT_BODY' macro is only needed if netiher `HAVE_ATEXIT' nor - `INIT_SECTION_ASM_OP' are defined. */ -/* #define EXIT_BODY */ - -/* Define this macro as a C expression that is nonzero if it is safe for the - delay slot scheduler to place instructions in the delay slot of INSN, even - if they appear to use a resource set or clobbered in INSN. INSN is always a - `jump_insn' or an `insn'; GNU CC knows that every `call_insn' has this - behavior. On machines where some `insn' or `jump_insn' is really a function - call and hence has this behavior, you should define this macro. - - You need not define this macro if it would always return zero. */ -/* #define INSN_SETS_ARE_DELAYED(INSN) */ - -/* Define this macro as a C expression that is nonzero if it is safe for the - delay slot scheduler to place instructions in the delay slot of INSN, even - if they appear to set or clobber a resource referenced in INSN. INSN is - always a `jump_insn' or an `insn'. On machines where some `insn' or - `jump_insn' is really a function call and its operands are registers whose - use is actually in the subroutine it calls, you should define this macro. - Doing so allows the delay slot scheduler to move instructions which copy - arguments into the argument registers into the delay slot of INSN. - - You need not define this macro if it would always return zero. */ -/* #define INSN_REFERENCES_ARE_DELAYED(INSN) */ - -/* In rare cases, correct code generation requires extra machine dependent - processing between the second jump optimization pass and delayed branch - scheduling. On those machines, define this macro as a C statement to act on - the code starting at INSN. */ -#define MACHINE_DEPENDENT_REORG(INSN) d30v_machine_dependent_reorg (INSN) - -/* 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 */ - -/* A C expression for the maximum number of instructions to execute via - conditional execution instructions instead of a branch. A value of - BRANCH_COST+1 is the default if the machine does not use cc0, and 1 if it - does use cc0. */ -#define MAX_CONDITIONAL_EXECUTE d30v_cond_exec - -#define D30V_DEFAULT_MAX_CONDITIONAL_EXECUTE 4 - -/* Values of the -mcond-exec=n string. */ -extern int d30v_cond_exec; -extern char *d30v_cond_exec_string; - -/* Indicate how many instructions can be issued at the same time. */ -#define ISSUE_RATE 2 - - -/* External functions called. */ - -#ifndef PROTO -#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) -#define PROTO(ARGS) ARGS -#else -#define PROTO(ARGS) () -#endif -#endif - -#ifdef BUFSIZ /* stdio.h has been included, ok to use FILE * */ -#define STDIO_PROTO(ARGS) PROTO(ARGS) -#else -#define STDIO_PROTO(ARGS) () -#endif - -#ifndef TREE_CODE -union tree_node; -#define Tree union tree_node * -#else -#define Tree tree -#endif - -#ifndef RTX_CODE -struct rtx_def; -#define Rtx struct rtx_def * -#else -#define Rtx rtx -#endif - -extern void override_options PROTO((void)); -extern int short_memory_operand PROTO((Rtx, int)); -extern int long_memory_operand PROTO((Rtx, int)); -extern int d30v_memory_operand PROTO((Rtx, int)); -extern int single_reg_memory_operand PROTO((Rtx, int)); -extern int const_addr_memory_operand PROTO((Rtx, int)); -extern int call_operand PROTO((Rtx, int)); -extern int gpr_operand PROTO((Rtx, int)); -extern int accum_operand PROTO((Rtx, int)); -extern int gpr_or_accum_operand PROTO((Rtx, int)); -extern int cr_operand PROTO((Rtx, int)); -extern int repeat_operand PROTO((Rtx, int)); -extern int flag_operand PROTO((Rtx, int)); -extern int br_flag_operand PROTO((Rtx, int)); -extern int br_flag_or_constant_operand PROTO((Rtx, int)); -extern int gpr_br_flag_operand PROTO((Rtx, int)); -extern int f0_operand PROTO((Rtx, int)); -extern int f1_operand PROTO((Rtx, int)); -extern int carry_operand PROTO((Rtx, int)); -extern int reg_or_0_operand PROTO((Rtx, int)); -extern int gpr_or_signed6_operand PROTO((Rtx, int)); -extern int gpr_or_unsigned5_operand PROTO((Rtx, int)); -extern int gpr_or_unsigned6_operand PROTO((Rtx, int)); -extern int gpr_or_constant_operand PROTO((Rtx, int)); -extern int gpr_or_dbl_const_operand PROTO((Rtx, int)); -extern int gpr_or_memory_operand PROTO((Rtx, int)); -extern int move_input_operand PROTO((Rtx, int)); -extern int move_output_operand PROTO((Rtx, int)); -extern int signed6_operand PROTO((Rtx, int)); -extern int unsigned5_operand PROTO((Rtx, int)); -extern int unsigned6_operand PROTO((Rtx, int)); -extern int bitset_operand PROTO((Rtx, int)); -extern int condexec_test_operator PROTO((Rtx, int)); -extern int condexec_branch_operator PROTO((Rtx, int)); -extern int condexec_unary_operator PROTO((Rtx, int)); -extern int condexec_addsub_operator PROTO((Rtx, int)); -extern int condexec_binary_operator PROTO((Rtx, int)); -extern int condexec_shiftl_operator PROTO((Rtx, int)); -extern int condexec_extend_operator PROTO((Rtx, int)); -extern int branch_zero_operator PROTO((Rtx, int)); -extern int cond_move_operand PROTO((Rtx, int)); -extern int cond_exec_operand PROTO((Rtx, int)); -extern int srelational_si_operand PROTO((Rtx, int)); -extern int urelational_si_operand PROTO((Rtx, int)); -extern int relational_di_operand PROTO((Rtx, int)); -extern d30v_stack_t *d30v_stack_info PROTO((void)); -extern int direct_return PROTO((void)); - -extern void d30v_init_cumulative_args PROTO((CUMULATIVE_ARGS *, Tree, - Rtx, int, int)); - -extern int d30v_function_arg_boundary PROTO((int, Tree)); -extern Rtx d30v_function_arg PROTO((CUMULATIVE_ARGS *, int, - Tree, int, int)); - -extern int d30v_function_arg_partial_nregs PROTO((CUMULATIVE_ARGS *, int, - Tree, int)); - -extern int d30v_function_arg_pass_by_reference PROTO((CUMULATIVE_ARGS *, int, - Tree, int)); - -extern void d30v_function_arg_advance PROTO((CUMULATIVE_ARGS *, int, - Tree, int)); - - -extern Rtx d30v_expand_builtin_saveregs PROTO((Tree)); -extern void d30v_setup_incoming_varargs PROTO((CUMULATIVE_ARGS *, int, - Tree, int *, int)); - -extern void d30v_function_prologue STDIO_PROTO((FILE *, int)); -extern void d30v_function_epilogue STDIO_PROTO((FILE *, int)); -extern void d30v_function_profiler STDIO_PROTO((FILE *, int)); -extern void d30v_split_double PROTO((Rtx, Rtx *, Rtx *)); -extern void d30v_print_operand STDIO_PROTO((FILE *, Rtx, int)); -extern void d30v_print_operand_address STDIO_PROTO((FILE *, Rtx)); -extern int d30v_trampoline_size PROTO((void)); -extern void d30v_initialize_trampoline PROTO((Rtx, Rtx, Rtx)); -extern int d30v_legitimate_address_p PROTO((int, Rtx, int)); -extern Rtx d30v_legitimize_address PROTO((Rtx, Rtx, int, int)); -extern int d30v_mode_dependent_address_p PROTO((Rtx)); -extern Rtx d30v_emit_comparison PROTO((int, Rtx, Rtx, Rtx)); -extern char *d30v_move_2words PROTO((Rtx *, Rtx)); -extern int d30v_emit_cond_move PROTO((Rtx, Rtx, Rtx, Rtx)); -extern char *d30v_cond_move PROTO((Rtx *, Rtx, char *, char *)); -extern void d30v_machine_dependent_reorg PROTO((Rtx)); -extern int d30v_adjust_cost PROTO((Rtx, Rtx, Rtx, int)); -extern Rtx d30v_return_addr PROTO((void)); - - -/* External variables referenced */ - -/* 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 Rtx d30v_compare_op0; -extern Rtx d30v_compare_op1; - -/* Define the information needed to modify the epilogue for EH. */ - -extern Rtx d30v_eh_epilogue_sp_ofs; - -/* Size of the accumulated function arguments. */ -extern int current_function_outgoing_args_size; - -/* End of d30v.h */ -/* END CYGNUS LOCAL -- meissner/d30v */ diff --git a/gcc/config/d30v/d30v.md b/gcc/config/d30v/d30v.md deleted file mode 100755 index 35d5b30..0000000 --- a/gcc/config/d30v/d30v.md +++ /dev/null @@ -1,3910 +0,0 @@ -;; CYGNUS LOCAL -- meissner/d30v -;; D30v Machine description template -;; Copyright (C) 1997, 1998 Free Software Foundation, Inc. -;; Contributed by Cygnus Solutions. - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - - -;; :::::::::::::::::::: -;; :: -;; :: Constraints -;; :: -;; :::::::::::::::::::: - -;; Standard Constraints -;; -;; `m' A memory operand is allowed, with any kind of address that the -;; machine supports in general. -;; -;; `o' A memory operand is allowed, but only if the address is -;; "offsettable". This means that adding a small integer (actually, the -;; width in bytes of the operand, as determined by its machine mode) may be -;; added to the address and the result is also a valid memory address. -;; -;; `V' A memory operand that is not offsettable. In other words, -;; anything that would fit the `m' constraint but not the `o' constraint. -;; -;; `<' A memory operand with autodecrement addressing (either -;; predecrement or postdecrement) is allowed. -;; -;; `>' A memory operand with autoincrement addressing (either -;; preincrement or postincrement) is allowed. -;; -;; `r' A register operand is allowed provided that it is in a general -;; register. -;; -;; `d', `a', `f', ... -;; Other letters can be defined in machine-dependent fashion to stand for -;; particular classes of registers. `d', `a' and `f' are defined on the -;; 68000/68020 to stand for data, address and floating point registers. -;; -;; `i' An immediate integer operand (one with constant value) is allowed. -;; This includes symbolic constants whose values will be known only at -;; assembly time. -;; -;; `n' An immediate integer operand with a known numeric value is allowed. -;; Many systems cannot support assembly-time constants for operands less -;; than a word wide. Constraints for these operands should use `n' rather -;; than `i'. -;; -;; 'I' First machine-dependent integer constant. -;; 'J' Second machine-dependent integer constant. -;; 'K' Third machine-dependent integer constant. -;; 'L' Fourth machine-dependent integer constant. -;; 'M' Fifth machine-dependent integer constant. -;; 'N' Sixth machine-dependent integer constant. -;; 'O' Seventh machine-dependent integer constant. -;; 'P' Eighth machine-dependent integer constant. -;; -;; Other letters in the range `I' through `P' may be defined in a -;; machine-dependent fashion to permit immediate integer operands with -;; explicit integer values in specified ranges. For example, on the 68000, -;; `I' is defined to stand for the range of values 1 to 8. This is the -;; range permitted as a shift count in the shift instructions. -;; -;; `E' An immediate floating operand (expression code `const_double') is -;; allowed, but only if the target floating point format is the same as -;; that of the host machine (on which the compiler is running). -;; -;; `F' An immediate floating operand (expression code `const_double') is -;; allowed. -;; -;; 'G' First machine-dependent const_double. -;; 'H' Second machine-dependent const_double. -;; -;; `s' An immediate integer operand whose value is not an explicit -;; integer is allowed. -;; -;; This might appear strange; if an insn allows a constant operand with a -;; value not known at compile time, it certainly must allow any known -;; value. So why use `s' instead of `i'? Sometimes it allows better code -;; to be generated. -;; -;; For example, on the 68000 in a fullword instruction it is possible to -;; use an immediate operand; but if the immediate value is between -128 and -;; 127, better code results from loading the value into a register and -;; using the register. This is because the load into the register can be -;; done with a `moveq' instruction. We arrange for this to happen by -;; defining the letter `K' to mean "any integer outside the range -128 to -;; 127", and then specifying `Ks' in the operand constraints. -;; -;; `g' Any register, memory or immediate integer operand is allowed, -;; except for registers that are not general registers. -;; -;; `X' Any operand whatsoever is allowed, even if it does not satisfy -;; `general_operand'. This is normally used in the constraint of a -;; `match_scratch' when certain alternatives will not actually require a -;; scratch register. -;; -;; `0' Match operand 0. -;; `1' Match operand 1. -;; `2' Match operand 2. -;; `3' Match operand 3. -;; `4' Match operand 4. -;; `5' Match operand 5. -;; `6' Match operand 6. -;; `7' Match operand 7. -;; `8' Match operand 8. -;; `9' Match operand 9. -;; -;; An operand that matches the specified operand number is allowed. If a -;; digit is used together with letters within the same alternative, the -;; digit should come last. -;; -;; This is called a "matching constraint" and what it really means is that -;; the assembler has only a single operand that fills two roles considered -;; separate in the RTL insn. For example, an add insn has two input -;; operands and one output operand in the RTL, but on most CISC machines an -;; add instruction really has only two operands, one of them an -;; input-output operand: -;; -;; addl #35,r12 -;; -;; Matching constraints are used in these circumstances. More precisely, -;; the two operands that match must include one input-only operand and one -;; output-only operand. Moreover, the digit must be a smaller number than -;; the number of the operand that uses it in the constraint. -;; -;; For operands to match in a particular case usually means that they are -;; identical-looking RTL expressions. But in a few special cases specific -;; kinds of dissimilarity are allowed. For example, `*x' as an input -;; operand will match `*x++' as an output operand. For proper results in -;; such cases, the output template should always use the output-operand's -;; number when printing the operand. -;; -;; `p' An operand that is a valid memory address is allowed. This is for -;; "load address" and "push address" instructions. -;; -;; `p' in the constraint must be accompanied by `address_operand' as the -;; predicate in the `match_operand'. This predicate interprets the mode -;; specified in the `match_operand' as the mode of the memory reference for -;; which the address would be valid. -;; -;; `Q` First non constant, non register machine-dependent insns -;; `R` Second non constant, non register machine-dependent insns -;; `S` Third non constant, non register machine-dependent insns -;; `T` Fourth non constant, non register machine-dependent insns -;; `U` Fifth non constant, non register machine-dependent insns -;; -;; Letters in the range `Q' through `U' may be defined in a -;; machine-dependent fashion to stand for arbitrary operand types. The -;; machine description macro `EXTRA_CONSTRAINT' is passed the operand as -;; its first argument and the constraint letter as its second operand. -;; -;; A typical use for this would be to distinguish certain types of memory -;; references that affect other insn operands. -;; -;; Do not define these constraint letters to accept register references -;; (`reg'); the reload pass does not expect this and would not handle it -;; properly. - -;; Multiple Alternative Constraints -;; `?' Disparage slightly the alternative that the `?' appears in, as a -;; choice when no alternative applies exactly. The compiler regards this -;; alternative as one unit more costly for each `?' that appears in it. -;; -;; `!' Disparage severely the alternative that the `!' appears in. This -;; alternative can still be used if it fits without reloading, but if -;; reloading is needed, some other alternative will be used. - -;; Constraint modifiers -;; `=' Means that this operand is write-only for this instruction: the -;; previous value is discarded and replaced by output data. -;; -;; `+' Means that this operand is both read and written by the -;; instruction. -;; -;; When the compiler fixes up the operands to satisfy the constraints, it -;; needs to know which operands are inputs to the instruction and which are -;; outputs from it. `=' identifies an output; `+' identifies an operand -;; that is both input and output; all other operands are assumed to be -;; input only. -;; -;; `&' Means (in a particular alternative) that this operand is written -;; before the instruction is finished using the input operands. Therefore, -;; this operand may not lie in a register that is used as an input operand -;; or as part of any memory address. -;; -;; `&' applies only to the alternative in which it is written. In -;; constraints with multiple alternatives, sometimes one alternative -;; requires `&' while others do not. -;; -;; `&' does not obviate the need to write `='. -;; -;; `%' Declares the instruction to be commutative for this operand and the -;; following operand. This means that the compiler may interchange the two -;; operands if that is the cheapest way to make all operands fit the -;; constraints. This is often used in patterns for addition instructions -;; that really have only two operands: the result must go in one of the -;; arguments. -;; -;; `#' Says that all following characters, up to the next comma, are to be -;; ignored as a constraint. They are significant only for choosing -;; register preferences. -;; -;; `*' Says that the following character should be ignored when choosing -;; register preferences. `*' has no effect on the meaning of the -;; constraint as a constraint, and no effect on reloading. - -;; :::::::::::::::::::: -;; :: -;; :: D30V register classes -;; :: -;; :::::::::::::::::::: - -;; `a' Accumulator registers (a0, a1) -;; `b' Flag registers for speculative execution (f0, f1) -;; `c' CR registers -;; `d' GPR registers -;; `e' Even GPR registers -;; `f' Any flag registers (f0, f1, ..., c) -;; `l' CR7, the repeat count -;; `x' F0 -;; `y' F1 -;; `z' Flag registers other than F0 and F1. - -;; :::::::::::::::::::: -;; :: -;; :: D30V special constraints -;; :: -;; :::::::::::::::::::: - -;; `G' Const double with 0 in both low & high part. -;; `H' Unused. -;; `I' Signed 6 bit integer constant (>= -32 && <= 31). -;; `J' Unsigned 5 bit integer constant (>= 0 && <= 31). -;; `K' Integer constant with 1 bit set (for bset). -;; `L' Integer constant with 1 bit clear (for bclr). -;; `M' Integer constant 32. -;; `N' Integer constant 1. -;; `O' Integer constant 0. -;; `P' Integer constant >= 32 && <= 63. -;; `Q' Short memory operand (can be done in small insn). -;; `R' Memory operand using a single register for address. -;; `S' Memory operand to constant address. -;; `T' Unused. -;; `U' Unused. - -;; :::::::::::::::::::: -;; :: -;; :: Standard operand flags -;; :: -;; :::::::::::::::::::: - -;; `=' Output a number unique to each instruction in the compilation. -;; `a' Substitute an operand as if it were a memory reference. -;; `c' Omit the syntax that indicates an immediate operand. -;; `l' Substitute a LABEL_REF into a jump instruction. -;; `n' Like %cDIGIT, except negate the value before printing. - -;; :::::::::::::::::::: -;; :: -;; :: D30V print_operand flags -;; :: -;; :::::::::::::::::::: - -;; `.' Print r0 -;; `f' Print a SF constant as an int. -;; `s' Subtract 32 and negate. -;; `A' Print accumulator number without an `a' in front of it. -;; `B' Print bit offset for BSET, etc. instructions. -;; `E' Print u if this is zero extend, nothing if this is sign extend. -;; `F' Emit /{f,t,x}{f,t,x} for executing a false condition. -;; `L' Print the lower half of a 64 bit item. -;; `M' Print a memory reference for ld/st instructions. -;; `R' Return appropriate cmp instruction for relational test. -;; `S' Subtract 32. -;; `T' Emit /{f,t,x}{f,t,x} for executing a true condition. -;; `U' Print the upper half of a 64 bit item. - - -;; :::::::::::::::::::: -;; :: -;; :: Attributes -;; :: -;; :::::::::::::::::::: - -;; The `define_attr' expression is used to define each attribute required by -;; the target machine. It looks like: -;; -;; (define_attr NAME LIST-OF-VALUES DEFAULT) - -;; NAME is a string specifying the name of the attribute being defined. - -;; LIST-OF-VALUES is either a string that specifies a comma-separated list of -;; values that can be assigned to the attribute, or a null string to indicate -;; that the attribute takes numeric values. - -;; DEFAULT is an attribute expression that gives the value of this attribute -;; for insns that match patterns whose definition does not include an explicit -;; value for this attribute. - -;; For each defined attribute, a number of definitions are written to the -;; `insn-attr.h' file. For cases where an explicit set of values is specified -;; for an attribute, the following are defined: - -;; * A `#define' is written for the symbol `HAVE_ATTR_NAME'. -;; -;; * An enumeral class is defined for `attr_NAME' with elements of the -;; form `UPPER-NAME_UPPER-VALUE' where the attribute name and value are first -;; converted to upper case. -;; -;; * A function `get_attr_NAME' is defined that is passed an insn and -;; returns the attribute value for that insn. - -;; For example, if the following is present in the `md' file: -;; -;; (define_attr "type" "branch,fp,load,store,arith" ...) -;; -;; the following lines will be written to the file `insn-attr.h'. -;; -;; #define HAVE_ATTR_type -;; enum attr_type {TYPE_BRANCH, TYPE_FP, TYPE_LOAD, TYPE_STORE, TYPE_ARITH}; -;; extern enum attr_type get_attr_type (); - -;; If the attribute takes numeric values, no `enum' type will be defined and -;; the function to obtain the attribute's value will return `int'. - -;; Whether we are using the haifa scheduler -(define_attr "haifa" "no,yes" - (const (symbol_ref "HAIFA_P"))) - -;; Note, we lie a little bit here to make it simpler to optimize. We pretend there -;; is a separate long functional unit for long instructions that uses both the IU & MU. - -(define_attr "type" "iu,mu,br,br2,either,scarry,lcarry,scmp,lcmp,sload,lload,mul,long,multi,unknown" - (const_string "unknown")) - -;; Length in word units -(define_attr "length" "" - (cond [(eq_attr "type" "iu,mu,either,scmp,sload,mul,scarry,") - (const_int 4) - (eq_attr "type" "long,lcmp,lload,lcarry") - (const_int 8) - (eq_attr "type" "multi,unknown") (const_int 64) ;; set higher to give a fudge factor - (eq_attr "type" "br") (if_then_else (and (ge (minus (pc) (match_dup 0)) - (const_int -1048576)) - (lt (minus (pc) (match_dup 0)) - (const_int 1048575))) - (const_int 4) - (const_int 8)) - (eq_attr "type" "br2") (if_then_else (and (ge (minus (pc) (match_dup 0)) - (const_int -16384)) - (lt (minus (pc) (match_dup 0)) - (const_int 16383))) - (const_int 4) - (const_int 8))] - (const_int 8))) - - -;; :::::::::::::::::::: -;; :: -;; :: Function Units -;; :: -;; :::::::::::::::::::: - -;; On most RISC machines, there are instructions whose results are not -;; available for a specific number of cycles. Common cases are instructions -;; that load data from memory. On many machines, a pipeline stall will result -;; if the data is referenced too soon after the load instruction. - -;; In addition, many newer microprocessors have multiple function units, -;; usually one for integer and one for floating point, and often will incur -;; pipeline stalls when a result that is needed is not yet ready. - -;; The descriptions in this section allow the specification of how much time -;; must elapse between the execution of an instruction and the time when its -;; result is used. It also allows specification of when the execution of an -;; instruction will delay execution of similar instructions due to function -;; unit conflicts. - -;; For the purposes of the specifications in this section, a machine is divided -;; into "function units", each of which execute a specific class of -;; instructions in first-in-first-out order. Function units that accept one -;; instruction each cycle and allow a result to be used in the succeeding -;; instruction (usually via forwarding) need not be specified. Classic RISC -;; microprocessors will normally have a single function unit, which we can call -;; `memory'. The newer "superscalar" processors will often have function units -;; for floating point operations, usually at least a floating point adder and -;; multiplier. - -;; Each usage of a function units by a class of insns is specified with a -;; `define_function_unit' expression, which looks like this: - -;; (define_function_unit NAME MULTIPLICITY SIMULTANEITY TEST READY-DELAY -;; ISSUE-DELAY [CONFLICT-LIST]) - -;; NAME is a string giving the name of the function unit. - -;; MULTIPLICITY is an integer specifying the number of identical units in the -;; processor. If more than one unit is specified, they will be scheduled -;; independently. Only truly independent units should be counted; a pipelined -;; unit should be specified as a single unit. (The only common example of a -;; machine that has multiple function units for a single instruction class that -;; are truly independent and not pipelined are the two multiply and two -;; increment units of the CDC 6600.) - -;; SIMULTANEITY specifies the maximum number of insns that can be executing in -;; each instance of the function unit simultaneously or zero if the unit is -;; pipelined and has no limit. - -;; All `define_function_unit' definitions referring to function unit NAME must -;; have the same name and values for MULTIPLICITY and SIMULTANEITY. - -;; TEST is an attribute test that selects the insns we are describing in this -;; definition. Note that an insn may use more than one function unit and a -;; function unit may be specified in more than one `define_function_unit'. - -;; READY-DELAY is an integer that specifies the number of cycles after which -;; the result of the instruction can be used without introducing any stalls. - -;; ISSUE-DELAY is an integer that specifies the number of cycles after the -;; instruction matching the TEST expression begins using this unit until a -;; subsequent instruction can begin. A cost of N indicates an N-1 cycle delay. -;; A subsequent instruction may also be delayed if an earlier instruction has a -;; longer READY-DELAY value. This blocking effect is computed using the -;; SIMULTANEITY, READY-DELAY, ISSUE-DELAY, and CONFLICT-LIST terms. For a -;; normal non-pipelined function unit, SIMULTANEITY is one, the unit is taken -;; to block for the READY-DELAY cycles of the executing insn, and smaller -;; values of ISSUE-DELAY are ignored. - -;; CONFLICT-LIST is an optional list giving detailed conflict costs for this -;; unit. If specified, it is a list of condition test expressions to be -;; applied to insns chosen to execute in NAME following the particular insn -;; matching TEST that is already executing in NAME. For each insn in the list, -;; ISSUE-DELAY specifies the conflict cost; for insns not in the list, the cost -;; is zero. If not specified, CONFLICT-LIST defaults to all instructions that -;; use the function unit. - -;; Typical uses of this vector are where a floating point function unit can -;; pipeline either single- or double-precision operations, but not both, or -;; where a memory unit can pipeline loads, but not stores, etc. - -;; As an example, consider a classic RISC machine where the result of a load -;; instruction is not available for two cycles (a single "delay" instruction is -;; required) and where only one load instruction can be executed -;; simultaneously. This would be specified as: - -;; (define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0) - -;; For the case of a floating point function unit that can pipeline -;; either single or double precision, but not both, the following could be -;; specified: -;; -;; (define_function_unit "fp" 1 0 -;; (eq_attr "type" "sp_fp") 4 4 -;; [(eq_attr "type" "dp_fp")]) -;; -;; (define_function_unit "fp" 1 0 -;; (eq_attr "type" "dp_fp") 4 4 -;; [(eq_attr "type" "sp_fp")]) - -;; Note: The scheduler attempts to avoid function unit conflicts and uses all -;; the specifications in the `define_function_unit' expression. It has -;; recently come to our attention that these specifications may not allow -;; modeling of some of the newer "superscalar" processors that have insns using -;; multiple pipelined units. These insns will cause a potential conflict for -;; the second unit used during their execution and there is no way of -;; representing that conflict. We welcome any examples of how function unit -;; conflicts work in such processors and suggestions for their representation. - -(define_function_unit "iu" 1 0 - (and (eq_attr "haifa" "no") - (eq_attr "type" "iu,either")) - 2 2 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "iu" 1 0 - (and (eq_attr "haifa" "yes") - (eq_attr "type" "iu,either")) - 1 1 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "iu" 1 0 - (and (eq_attr "haifa" "no") - (eq_attr "type" "scmp,mul,scarry")) - 4 2 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "iu" 1 0 - (and (eq_attr "haifa" "yes") - (eq_attr "type" "scmp,mul,scarry")) - 2 1 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "mu" 1 0 - (and (eq_attr "haifa" "no") - (eq_attr "type" "mu,br,br2,scarry,scmp,sload,either")) - 2 2 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "mu" 1 0 - (and (eq_attr "haifa" "yes") - (eq_attr "type" "mu,br,br2,either")) - 1 1 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "mu" 1 0 - (and (eq_attr "haifa" "no") - (eq_attr "type" "scarry,scmp,sload")) - 4 2 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "mu" 1 0 - (and (eq_attr "haifa" "yes") - (eq_attr "type" "scarry,scmp,sload")) - 2 1 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "long" 1 0 - (and (eq_attr "haifa" "no") - (eq_attr "type" "long,multi,unknown")) - 2 2 - [(eq_attr "type" "iu,mu,scarry,scmp,sload,mul,br,br2,either")]) - -(define_function_unit "long" 1 0 - (and (eq_attr "haifa" "yes") - (eq_attr "type" "long,multi,unknown")) - 1 1 - [(eq_attr "type" "iu,mu,scarry,scmp,sload,mul,br,br2,either")]) - -(define_function_unit "long" 1 0 - (and (eq_attr "haifa" "no") - (eq_attr "type" "lcmp,lload,lcarry")) - 4 2 - [(eq_attr "type" "iu,mu,scarry,scmp,sload,mul,br,br2,either")]) - -(define_function_unit "long" 1 0 - (and (eq_attr "haifa" "yes") - (eq_attr "type" "lcmp,lload,lcarry")) - 2 1 - [(eq_attr "type" "iu,mu,scarry,scmp,sload,mul,br,br2,either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Delay Slots -;; :: -;; :::::::::::::::::::: - -;; The insn attribute mechanism can be used to specify the requirements for -;; delay slots, if any, on a target machine. An instruction is said to require -;; a "delay slot" if some instructions that are physically after the -;; instruction are executed as if they were located before it. Classic -;; examples are branch and call instructions, which often execute the following -;; instruction before the branch or call is performed. - -;; On some machines, conditional branch instructions can optionally "annul" -;; instructions in the delay slot. This means that the instruction will not be -;; executed for certain branch outcomes. Both instructions that annul if the -;; branch is true and instructions that annul if the branch is false are -;; supported. - -;; Delay slot scheduling differs from instruction scheduling in that -;; determining whether an instruction needs a delay slot is dependent only -;; on the type of instruction being generated, not on data flow between the -;; instructions. See the next section for a discussion of data-dependent -;; instruction scheduling. - -;; The requirement of an insn needing one or more delay slots is indicated via -;; the `define_delay' expression. It has the following form: -;; -;; (define_delay TEST -;; [DELAY-1 ANNUL-TRUE-1 ANNUL-FALSE-1 -;; DELAY-2 ANNUL-TRUE-2 ANNUL-FALSE-2 -;; ...]) - -;; TEST is an attribute test that indicates whether this `define_delay' applies -;; to a particular insn. If so, the number of required delay slots is -;; determined by the length of the vector specified as the second argument. An -;; insn placed in delay slot N must satisfy attribute test DELAY-N. -;; ANNUL-TRUE-N is an attribute test that specifies which insns may be annulled -;; if the branch is true. Similarly, ANNUL-FALSE-N specifies which insns in -;; the delay slot may be annulled if the branch is false. If annulling is not -;; supported for that delay slot, `(nil)' should be coded. - -;; For example, in the common case where branch and call insns require a single -;; delay slot, which may contain any insn other than a branch or call, the -;; following would be placed in the `md' file: - -;; (define_delay (eq_attr "type" "branch,call") -;; [(eq_attr "type" "!branch,call") (nil) (nil)]) - -;; Multiple `define_delay' expressions may be specified. In this case, each -;; such expression specifies different delay slot requirements and there must -;; be no insn for which tests in two `define_delay' expressions are both true. - -;; For example, if we have a machine that requires one delay slot for branches -;; but two for calls, no delay slot can contain a branch or call insn, and any -;; valid insn in the delay slot for the branch can be annulled if the branch is -;; true, we might represent this as follows: - -;; (define_delay (eq_attr "type" "branch") -;; [(eq_attr "type" "!branch,call") -;; (eq_attr "type" "!branch,call") -;; (nil)]) -;; -;; (define_delay (eq_attr "type" "call") -;; [(eq_attr "type" "!branch,call") (nil) (nil) -;; (eq_attr "type" "!branch,call") (nil) (nil)]) - - -;; :::::::::::::::::::: -;; :: -;; :: Moves -;; :: -;; :::::::::::::::::::: - -;; Wrap moves in define_expand to prevent memory->memory moves from being -;; generated at the RTL level, which generates better code for most machines -;; which can't do mem->mem moves. - -;; If operand 0 is a `subreg' with mode M of a register whose own mode is wider -;; than M, the effect of this instruction is to store the specified value in -;; the part of the register that corresponds to mode M. The effect on the rest -;; of the register is undefined. - -;; This class of patterns is special in several ways. First of all, each of -;; these names *must* be defined, because there is no other way to copy a datum -;; from one place to another. - -;; Second, these patterns are not used solely in the RTL generation pass. Even -;; the reload pass can generate move insns to copy values from stack slots into -;; temporary registers. When it does so, one of the operands is a hard -;; register and the other is an operand that can need to be reloaded into a -;; register. - -;; Therefore, when given such a pair of operands, the pattern must -;; generate RTL which needs no reloading and needs no temporary -;; registers--no registers other than the operands. For example, if -;; you support the pattern with a `define_expand', then in such a -;; case the `define_expand' mustn't call `force_reg' or any other such -;; function which might generate new pseudo registers. - -;; This requirement exists even for subword modes on a RISC machine -;; where fetching those modes from memory normally requires several -;; insns and some temporary registers. Look in `spur.md' to see how -;; the requirement can be satisfied. - -;; During reload a memory reference with an invalid address may be passed as an -;; operand. Such an address will be replaced with a valid address later in the -;; reload pass. In this case, nothing may be done with the address except to -;; use it as it stands. If it is copied, it will not be replaced with a valid -;; address. No attempt should be made to make such an address into a valid -;; address and no routine (such as `change_address') that will do so may be -;; called. Note that `general_operand' will fail when applied to such an -;; address. -;; -;; The global variable `reload_in_progress' (which must be explicitly declared -;; if required) can be used to determine whether such special handling is -;; required. -;; -;; The variety of operands that have reloads depends on the rest of -;; the machine description, but typically on a RISC machine these can -;; only be pseudo registers that did not get hard registers, while on -;; other machines explicit memory references will get optional -;; reloads. -;; -;; If a scratch register is required to move an object to or from memory, it -;; can be allocated using `gen_reg_rtx' prior to reload. But this is -;; impossible during and after reload. If there are cases needing scratch -;; registers after reload, you must define `SECONDARY_INPUT_RELOAD_CLASS' and -;; perhaps also `SECONDARY_OUTPUT_RELOAD_CLASS' to detect them, and provide -;; patterns `reload_inM' or `reload_outM' to handle them. *Note Register -;; Classes::. - -;; The constraints on a `moveM' must permit moving any hard register to any -;; other hard register provided that `HARD_REGNO_MODE_OK' permits mode M in -;; both registers and `REGISTER_MOVE_COST' applied to their classes returns a -;; value of 2. - -;; It is obligatory to support floating point `moveM' instructions -;; into and out of any registers that can hold fixed point values, -;; because unions and structures (which have modes `SImode' or -;; `DImode') can be in those registers and they may have floating -;; point members. - -;; There may also be a need to support fixed point `moveM' instructions in and -;; out of floating point registers. Unfortunately, I have forgotten why this -;; was so, and I don't know whether it is still true. If `HARD_REGNO_MODE_OK' -;; rejects fixed point values in floating point registers, then the constraints -;; of the fixed point `moveM' instructions must be designed to avoid ever -;; trying to reload into a floating point register. - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], QImode) - && !reg_or_0_operand (operands[1], QImode)) - operands[1] = copy_to_mode_reg (QImode, operands[1]); -}") - -(define_insn "*movqi_internal" - [(set (match_operand:QI 0 "move_output_operand" "=d,d,d,d,Q,m,Q,m,d,c") - (match_operand:QI 1 "move_input_operand" "dI,i,Q,m,d,d,O,O,c,d"))] - "register_operand (operands[0], QImode) || reg_or_0_operand (operands[1], QImode)" - "@ - or %0,%.,%1 - or %0,%.,%1 - ldb %0,%M1 - ldb %0,%M1 - stb %1,%M0 - stb %1,%M0 - stb %.,%M0 - stb %.,%M0 - mvfsys %0,%1 - mvtsys %0,%1" - [(set_attr "length" "4,8,4,8,4,8,4,8,4,4") - (set_attr "type" "either,long,sload,lload,mu,long,mu,long,mu,mu")]) - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], HImode) - && !reg_or_0_operand (operands[1], HImode)) - operands[1] = copy_to_mode_reg (HImode, operands[1]); -}") - -(define_insn "*movhi_internal" - [(set (match_operand:HI 0 "move_output_operand" "=d,d,d,d,Q,m,Q,m,d,c") - (match_operand:HI 1 "move_input_operand" "dI,i,Q,m,d,d,O,O,c,d"))] - "register_operand (operands[0], HImode) || reg_or_0_operand (operands[1], HImode)" - "@ - or %0,%.,%1 - or %0,%.,%1 - ldh %0,%M1 - ldh %0,%M1 - sth %1,%M0 - sth %1,%M0 - sth %.,%M0 - sth %.,%M0 - mvfsys %0,%1 - mvtsys %0,%1" - [(set_attr "length" "4,8,4,8,4,8,4,8,4,4") - (set_attr "type" "either,long,sload,lload,mu,long,mu,long,mu,mu")]) - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], SImode) - && !reg_or_0_operand (operands[1], SImode)) - operands[1] = copy_to_mode_reg (SImode, operands[1]); - - /* Convert addressing modes into the appropriate add/sub with the clobbers - needed. This is generated by builtin_setjmp in the exception handling. */ - if (GET_CODE (operands[1]) == PLUS) - { - emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), - XEXP (operands[1], 1))); - DONE; - } - - else if (GET_CODE (operands[1]) == MINUS) - { - emit_insn (gen_subsi3 (operands[0], XEXP (operands[1], 0), - XEXP (operands[1], 1))); - DONE; - } -}") - -(define_insn "*movsi_internal" - [(set (match_operand:SI 0 "move_output_operand" "=d,d,d,d,d,Q,m,Q,m,d,c") - (match_operand:SI 1 "move_input_operand" "dI,F,i,Q,m,d,d,O,O,c,d"))] - "register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode)" - "@ - or %0,%.,%1 - or %0,%.,%L1 - or %0,%.,%1 - ldw %0,%M1 - ldw %0,%M1 - stw %1,%M0 - stw %1,%M0 - stw %.,%M0 - stw %.,%M0 - mvfsys %0,%1 - mvtsys %0,%1" - [(set_attr "length" "4,8,8,4,8,4,8,4,8,4,4") - (set_attr "type" "either,long,long,sload,lload,mu,long,mu,long,mu,mu")]) - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], DImode) - && !register_operand (operands[1], DImode)) - operands[1] = copy_to_mode_reg (DImode, operands[1]); -}") - -(define_insn "*movdi_internal" - [(set (match_operand:DI 0 "move_output_operand" "=e,e,e,e,Q,m,e,a,a") - (match_operand:DI 1 "move_input_operand" "eI,iF,Q,m,e,e,a,e,O"))] - "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" - "* return d30v_move_2words (operands, insn);" - [(set_attr "length" "8,16,4,8,4,8,8,4,4") - (set_attr "type" "multi,multi,sload,lload,mu,long,multi,iu,iu")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (match_operand:DI 1 "gpr_or_dbl_const_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - " -{ - d30v_split_double (operands[0], &operands[2], &operands[4]); - d30v_split_double (operands[1], &operands[3], &operands[5]); -}") - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], SFmode) - && !reg_or_0_operand (operands[1], SFmode)) - operands[1] = copy_to_mode_reg (SFmode, operands[1]); -}") - -(define_insn "*movsf_internal" - [(set (match_operand:SF 0 "move_output_operand" "=d,d,d,d,d,Q,m,Q,m") - (match_operand:SF 1 "move_input_operand" "d,G,F,Q,m,d,d,G,G"))] - "register_operand (operands[0], SFmode) || reg_or_0_operand (operands[1], SFmode)" - "@ - or %0,%.,%1 - or %0,%.,0 - or %0,%.,%f1 - ldw %0,%M1 - ldw %0,%M1 - stw %1,%M0 - stw %1,%M0 - stw %.,%M0 - stw %.,%M0" - [(set_attr "length" "4,4,8,4,8,4,8,4,8") - (set_attr "type" "either,either,long,sload,lload,mu,long,mu,long")]) - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], DFmode) - && !register_operand (operands[1], DFmode)) - operands[1] = copy_to_mode_reg (DFmode, operands[1]); -}") - -(define_insn "*movdf_internal" - [(set (match_operand:DF 0 "move_output_operand" "=e,e,e,e,Q,m,!*e,!*a") - (match_operand:DF 1 "move_input_operand" "eG,F,Q,m,e,e,!*a,!*e"))] - "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" - "* return d30v_move_2words (operands, insn);" - [(set_attr "length" "8,16,4,8,4,8,8,4") - (set_attr "type" "multi,multi,sload,lload,mu,long,multi,iu")]) - -(define_split - [(set (match_operand:DF 0 "gpr_operand" "") - (match_operand:DF 1 "gpr_or_dbl_const_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - " -{ - d30v_split_double (operands[0], &operands[2], &operands[4]); - d30v_split_double (operands[1], &operands[3], &operands[5]); -}") - -(define_expand "movcc" - [(set (match_operand:CC 0 "general_operand" "") - (match_operand:CC 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - operands[1] = copy_to_mode_reg (CCmode, operands[1]); -}") - -(define_insn "*movcc_internal" - [(set (match_operand:CC 0 "move_output_operand" "=f,f,f,d,f,d,*d,*d,*Q,*m") - (match_operand:CC 1 "move_input_operand" "f,O,N,f,d,dON,*Q,*m,*d,*d"))] - "!memory_operand (operands[0], CCmode) || !memory_operand (operands[1], CCmode)" - "@ - orfg %0,%1,%1 - andfg %0,%0,0 - orfg %0,%0,1 - mvfsys %0,%1 - mvtsys %0,%1 - or %0,%.,%1 - ldb %0,%M1 - ldb %0,%M1 - stb %1,%M0 - stb %1,%M0" - [(set_attr "length" "4,4,4,4,4,4,4,8,4,8") - (set_attr "type" "either,either,either,mu,mu,either,sload,lload,mu,long")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Conversions -;; :: -;; :::::::::::::::::::: - -;; Signed conversions from a smaller integer to a larger integer -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (sign_extend:HI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - # - ldb %0,%M1 - ldb %0,%M1" - [(set_attr "type" "multi,sload,lload") - (set_attr "length" "16,4,8")]) - -(define_split - [(set (match_operand:HI 0 "gpr_operand" "") - (sign_extend:HI (match_operand:QI 1 "gpr_operand" "")))] - "reload_completed" - [(match_dup 2) - (match_dup 3)] - " -{ - rtx op0 = gen_lowpart (SImode, operands[0]); - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx shift = gen_rtx (CONST_INT, VOIDmode, 24); - - operands[2] = gen_ashlsi3 (op0, op1, shift); - operands[3] = gen_ashrsi3 (op0, op0, shift); -}") - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d") - (sign_extend:SI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - # - ldb %0,%M1 - ldb %0,%M1" - [(set_attr "type" "multi,sload,lload") - (set_attr "length" "16,4,8")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (sign_extend:SI (match_operand:QI 1 "gpr_operand" "")))] - "reload_completed" - [(match_dup 2) - (match_dup 3)] - " -{ - rtx op0 = gen_lowpart (SImode, operands[0]); - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx shift = gen_rtx (CONST_INT, VOIDmode, 24); - - operands[2] = gen_ashlsi3 (op0, op1, shift); - operands[3] = gen_ashrsi3 (op0, op0, shift); -}") - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d") - (sign_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - # - ldh %0,%M1 - ldh %0,%M1" - [(set_attr "type" "multi,sload,lload") - (set_attr "length" "16,4,8")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (sign_extend:SI (match_operand:HI 1 "gpr_operand" "")))] - "reload_completed" - [(match_dup 2) - (match_dup 3)] - " -{ - rtx op0 = gen_lowpart (SImode, operands[0]); - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx shift = gen_rtx (CONST_INT, VOIDmode, 16); - - operands[2] = gen_ashlsi3 (op0, op1, shift); - operands[3] = gen_ashrsi3 (op0, op0, shift); -}") - -(define_insn "extendqidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (sign_extend:DI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "12,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (sign_extend:DI (match_operand:QI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (sign_extend:SI (match_dup 1))) - (set (match_dup 3) (ashiftrt:SI (match_dup 2) (const_int 31)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -(define_insn "extendhidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (sign_extend:DI (match_operand:HI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "12,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (sign_extend:DI (match_operand:HI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (sign_extend:SI (match_dup 1))) - (set (match_dup 3) (ashiftrt:SI (match_dup 2) (const_int 31)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (sign_extend:DI (match_operand:SI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (sign_extend:DI (match_operand:SI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (ashiftrt:SI (match_dup 2) (const_int 31)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -;; Unsigned conversions from a smaller integer to a larger integer - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (zero_extend:HI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - and %0,%1,0xff - ldbu %0,%M1 - ldbu %0,%M1" - [(set_attr "length" "8,4,8") - (set_attr "type" "long,sload,lload")]) - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d") - (zero_extend:SI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - and %0,%1,0xff - ldbu %0,%M1 - ldbu %0,%M1" - [(set_attr "length" "8,4,8") - (set_attr "type" "long,sload,lload")]) - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d") - (zero_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - and %0,%1,0xffff - ldhu %0,%M1 - ldhu %0,%M1" - [(set_attr "length" "8,4,8") - (set_attr "type" "long,sload,lload")]) - -(define_insn "zero_extendqidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (zero_extend:DI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "12,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (zero_extend:DI (match_operand:QI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (zero_extend:SI (match_dup 1))) - (set (match_dup 3) (const_int 0))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -(define_insn "zero_extendhidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (zero_extend:DI (match_operand:HI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (zero_extend:DI (match_operand:HI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (zero_extend:SI (match_dup 1))) - (set (match_dup 3) (const_int 0))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -(define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (zero_extend:DI (match_operand:SI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (zero_extend:DI (match_operand:SI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (const_int 0))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: 32 bit Integer arithmetic -;; :: -;; :::::::::::::::::::: - -;; Addition -(define_expand "addsi3" - [(parallel [(set (match_operand:SI 0 "gpr_operand" "") - (plus:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_constant_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_dup 5))])] - "" - " -{ - operands[3] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[4] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[5] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*addsi3_internal" - [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (plus:SI (match_operand:SI 1 "gpr_operand" "%d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i"))) - (clobber (match_operand:CC 3 "flag_operand" "f,f")) - (clobber (match_operand:CC 4 "flag_operand" "f,f")) - (clobber (match_operand:CC 5 "flag_operand" "f,f"))] - "" - "add %0,%1,%2" - [(set_attr "length" "4,8") - (set_attr "type" "either,long")]) - -;; Subtraction -(define_expand "subsi3" - [(parallel [(set (match_operand:SI 0 "gpr_operand" "") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "") - (match_operand:SI 2 "gpr_or_constant_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_dup 5))])] - "" - " -{ - operands[3] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[4] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[5] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*subsi3_internal" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "d,d,O,O") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i,dI,i"))) - (clobber (match_operand:CC 3 "flag_operand" "f,f,f,f")) - (clobber (match_operand:CC 4 "flag_operand" "f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "f,f,f,f"))] - "" - "@ - sub %0,%1,%2 - sub %0,%1,%2 - sub %0,%.,%2 - sub %0,%.,%2" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,either,long")]) - -;; Multiplication (same size) -(define_insn "mulsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (mult:SI (match_operand:SI 1 "gpr_operand" "%d") - (match_operand:SI 2 "gpr_or_signed6_operand" "dI")))] - "" - "mul %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -;; Signed multiplication producing 64 bit results from 32 bit inputs -(define_insn "mulsidi3" - [(set (match_operand:DI 0 "accum_operand" "=a") - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d"))))] - "" - "mulx %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*mulsidi3_const" - [(set (match_operand:DI 0 "accum_operand" "=a") - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (match_operand:DI 2 "signed6_operand" "I")))] - "" - "mulx %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -;; Signed multiplication producing just the upper 32 bits from a 32x32->64 -;; bit multiply. We specifically allow any integer constant here so -;; allow division by constants to be done by multiplying by a large constant. - -(define_expand "smulsi3_highpart" - [(set (match_dup 3) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "")) - (match_operand:SI 2 "gpr_or_constant_operand" ""))) - (set (match_operand:SI 0 "gpr_operand" "") - (truncate:SI (lshiftrt:DI (match_dup 3) - (const_int 32))))] - "" - " -{ - operands[3] = gen_reg_rtx (DImode); - - if (GET_CODE (operands[2]) == CONST_INT && - !IN_RANGE_P (INTVAL (operands[2]), -32, 31)) - operands[2] = force_reg (SImode, operands[2]); - - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - operands[2] = gen_rtx (SIGN_EXTEND, DImode, operands[2]); -}") - -(define_insn "*di_highpart" - [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (truncate:SI (lshiftrt:DI (match_operand:DI 1 "gpr_or_accum_operand" "e,a") - (const_int 32))))] - "" - "@ - or %0,%.,%U1 - mvfacc %0,%1,32" - [(set_attr "length" "4") - (set_attr "type" "either,iu")]) - -;; Negation -(define_expand "negsi2" - [(parallel [(set (match_operand:SI 0 "gpr_operand" "") - (neg:SI (match_operand:SI 1 "gpr_operand" ""))) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "" - " -{ - operands[2] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[3] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[4] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*negsi2_internal" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (neg:SI (match_operand:SI 1 "gpr_operand" "d"))) - (clobber (match_operand:CC 2 "flag_operand" "=f")) - (clobber (match_operand:CC 3 "flag_operand" "=f")) - (clobber (match_operand:CC 4 "flag_operand" "=f"))] - "" - "sub %0,%.,%1" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Absolute value -(define_insn "abssi2" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (abs:SI (match_operand:SI 1 "gpr_operand" "d")))] - "" - "abs %0,%1" - [(set_attr "length" "4") - (set_attr "type" "either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 64 bit Integer arithmetic -;; :: -;; :::::::::::::::::::: - -;; Addition -(define_expand "adddi3" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (plus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_constant_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_dup 5))])] - "" - " -{ - operands[3] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[4] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[5] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*adddi3_internal" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e,e") - (plus:DI (match_operand:DI 1 "gpr_operand" "%e,e,e,e") - (match_operand:DI 2 "gpr_or_constant_operand" "I,i,e,F"))) - (clobber (match_operand:CC 3 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 4 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f,f,f"))] - "" - "#" - [(set_attr "length" "8,12,8,16") - (set_attr "type" "multi")]) - -(define_insn "addsi3_set_carry" - [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (plus:SI (match_operand:SI 1 "gpr_operand" "%d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i"))) - (set (match_operand:CC 3 "carry_operand" "=f,f") - (unspec [(match_dup 1) - (match_dup 2)] 1)) - (clobber (match_operand:CC 4 "flag_operand" "=f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f"))] - "" - "add %0,%1,%2" - [(set_attr "length" "4,8") - (set_attr "type" "scarry,lcarry")]) - -(define_insn "addsi3_use_carry" - [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (unspec [(match_operand:SI 1 "gpr_operand" "%d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i") - (match_operand:CC 3 "carry_operand" "+f,f")] 2)) - (clobber (match_operand:CC 4 "flag_operand" "=f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f"))] - "" - "addc %0,%1,%2" - [(set_attr "length" "4,8") - (set_attr "type" "scarry,lcarry")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (plus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_constant_operand" ""))) - (clobber (match_operand:CC 3 "flag_operand" "")) - (clobber (match_operand:CC 4 "flag_operand" "")) - (clobber (match_operand:CC 5 "flag_operand" ""))] - "reload_completed" - [(match_dup 6) - (match_dup 7)] - " -{ - rtx high[3]; - rtx low[3]; - - d30v_split_double (operands[0], &high[0], &low[0]); - d30v_split_double (operands[1], &high[1], &low[1]); - d30v_split_double (operands[2], &high[2], &low[2]); - - operands[6] = gen_addsi3_set_carry (low[0], low[1], low[2], operands[3], - operands[4], operands[5]); - - operands[7] = gen_addsi3_use_carry (high[0], high[1], high[2], operands[3], - operands[4], operands[5]); -}") - -;; Subtraction -(define_expand "subdi3" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (minus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_constant_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_dup 5))])] - "" - " -{ - operands[3] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[4] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[5] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*subdi3_internal" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e,e") - (minus:DI (match_operand:DI 1 "gpr_operand" "e,e,e,e") - (match_operand:DI 2 "gpr_or_constant_operand" "I,i,e,F"))) - (clobber (match_operand:CC 3 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 4 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f,f,f"))] - "" - "#" - [(set_attr "length" "8,12,8,16") - (set_attr "type" "multi")]) - -(define_insn "subsi3_set_carry" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "d,d,O,O") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i,dI,i"))) - (set (match_operand:CC 3 "carry_operand" "=f,f,f,f") - (unspec [(match_dup 1) - (match_dup 2)] 3)) - (clobber (match_operand:CC 4 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f,f,f"))] - "" - "@ - sub %0,%1,%2 - sub %0,%1,%2 - sub %0,%.,%2 - sub %0,%.,%2" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "scarry,lcarry,scarry,lcarry")]) - -(define_insn "subsi3_use_carry" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (unspec [(match_operand:SI 1 "reg_or_0_operand" "d,d,O,O") - (match_operand:SI 2 "gpr_operand" "dI,i,dI,i") - (match_operand:CC 3 "carry_operand" "+f,f,f,f")] 4)) - (clobber (match_operand:CC 4 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f,f,f"))] - "" - "@ - subb %0,%1,%2 - subb %0,%1,%2 - subb %0,%.,%2 - subb %0,%.,%2" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "scarry,lcarry,scarry,lcarry")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (minus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_constant_operand" ""))) - (clobber (match_operand:CC 3 "flag_operand" "")) - (clobber (match_operand:CC 4 "flag_operand" "")) - (clobber (match_operand:CC 5 "flag_operand" ""))] - "reload_completed" - [(match_dup 6) - (match_dup 7)] - " -{ - rtx high[3]; - rtx low[3]; - - d30v_split_double (operands[0], &high[0], &low[0]); - d30v_split_double (operands[1], &high[1], &low[1]); - d30v_split_double (operands[2], &high[2], &low[2]); - - operands[6] = gen_subsi3_set_carry (low[0], low[1], low[2], operands[3], - operands[4], operands[5]); - - operands[7] = gen_subsi3_use_carry (high[0], high[1], high[2], operands[3], - operands[4], operands[5]); -}") - -;; Negation -(define_expand "negdi2" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (neg:DI (match_operand:DI 1 "gpr_operand" ""))) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "" - " -{ - operands[2] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[3] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[4] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*negdi2_internal" - [(set (match_operand:DI 0 "gpr_operand" "=e") - (neg:DI (match_operand:DI 1 "gpr_operand" "e"))) - (clobber (match_operand:CC 2 "flag_operand" "=f")) - (clobber (match_operand:CC 3 "flag_operand" "=f")) - (clobber (match_operand:CC 4 "flag_operand" "=f"))] - "" - "#" - [(set_attr "length" "8") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "=e") - (neg:DI (match_operand:DI 1 "gpr_operand" "e"))) - (clobber (match_operand:CC 2 "flag_operand" "=f")) - (clobber (match_operand:CC 3 "flag_operand" "=f")) - (clobber (match_operand:CC 4 "flag_operand" "=f"))] - "reload_completed" - [(match_dup 5) - (match_dup 6)] - " -{ - rtx high[2]; - rtx low[2]; - rtx r0 = const0_rtx; - - d30v_split_double (operands[0], &high[0], &low[0]); - d30v_split_double (operands[1], &high[1], &low[1]); - - operands[5] = gen_subsi3_set_carry (low[0], r0, low[1], operands[2], - operands[3], operands[4]); - - operands[6] = gen_subsi3_use_carry (high[0], r0, high[1], operands[2], - operands[3], operands[4]); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: 32 bit Integer Shifts and Rotates -;; :: -;; :::::::::::::::::::: - -;; Arithmetic Shift Left (negate the shift value and use shift right) -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "gpr_operand" "") - (ashift:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*ashlsi3_constant" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (ashift:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "unsigned5_operand" "J")))] - "" - "sra %0,%1,%n2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*ashlsi3_register" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (ashift:SI (match_operand:SI 1 "gpr_operand" "d") - (neg:SI (match_operand:SI 2 "gpr_operand" "d"))))] - "" - "sra %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Arithmetic Shift Right -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "dJ")))] - "" - "sra %0,%1,%2" - [(set_attr "length" "4")]) - -;; Logical Shift Right -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (lshiftrt:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "dJ")))] - "" - "srl %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Rotate Left (negate the shift value and use rotate right) -(define_expand "rotlsi3" - [(set (match_operand:SI 0 "gpr_operand" "") - (rotate:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*rotlsi3_constant" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (rotate:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "unsigned5_operand" "J")))] - "" - "rot %0,%1,%n2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*rotlsi3_register" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (rotate:SI (match_operand:SI 1 "gpr_operand" "d") - (neg:SI (match_operand:SI 2 "gpr_operand" "d"))))] - "" - "rot %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Rotate Right -(define_insn "rotrsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (rotatert:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "dJ")))] - "" - "rot %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 64 bit Integer Shifts and Rotates -;; :: -;; :::::::::::::::::::: - -;; Arithmetic Shift Left -(define_expand "ashldi3" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (ashift:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_unsigned6_operand" ""))) - (clobber (match_scratch:CC 3 ""))])] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - if (IN_RANGE_P (INTVAL (operands[2]), 0, 63)) - { - emit_insn (gen_ashldi3_constant (operands[0], operands[1], operands[2])); - DONE; - } - else - operands[2] = copy_to_mode_reg (SImode, operands[2]); - } - - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "ashldi3_constant" - [(set (match_operand:DI 0 "gpr_operand" "=e,e") - (ashift:DI (match_operand:DI 1 "gpr_operand" "0,e") - (match_operand:SI 2 "unsigned6_operand" "J,P")))] - "" - "@ - src %U0,%L0,%n2\;sra %L0,%L0,%n2 - sra %U0,%L1,%s2\;or %L0,%.,0" - [(set_attr "length" "8") - (set_attr "type" "multi")]) - -(define_insn "*ashldi3_register" - [(set (match_operand:DI 0 "gpr_operand" "=e") - (ashift:DI (match_operand:DI 1 "gpr_operand" "0") - (neg:SI (match_operand:SI 2 "gpr_operand" "d")))) - (clobber (match_scratch:CC 3 "=b"))] - "" - "cmpge %3,%2,-31\;src%T3 %U0,%L0,%2\;sra%T3 %L0,%L0,%2\;sub%F3 %U0,%2,-32\;sra%F3 %U0,%L0,%U0\;or%F3 %L0,%.,0" - [(set_attr "length" "32") - (set_attr "type" "multi")]) - -;; Arithmetic Shift Right -(define_insn "ashrdi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (ashiftrt:DI (match_operand:DI 1 "gpr_operand" "0,e,0") - (match_operand:SI 2 "gpr_or_unsigned6_operand" "J,P,d"))) - (clobber (match_scratch:CC 3 "=X,X,b"))] - "" - "@ - src %L0,%U0,%2\;sra %U0,%U0,%2 - sra %L0,%U1,%S2\;sra %U0,%L0,31 - cmple %3,%2,31\;src%T3 %L0,%U0,%2\;sra%T3 %U0,%U0,%2\;add%F3 %L0,%2,-32\;sra%F3 %L0,%U0,%L0\;sra%F3 %U0,%U0,31" - [(set_attr "length" "8,8,28") - (set_attr "type" "multi")]) - -;; Logical Shift Right - -(define_insn "lshrdi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (lshiftrt:DI (match_operand:DI 1 "gpr_operand" "0,e,0") - (match_operand:SI 2 "gpr_or_unsigned6_operand" "J,P,d"))) - (clobber (match_scratch:CC 3 "=X,X,b"))] - "" - "@ - src %L0,%U0,%2\;srl %U0,%U0,%2 - srl %L0,%U1,%S2\;or %U0,%.,0 - cmple %3,%2,31\;src%T3 %L0,%U0,%2\;srl%T3 %U0,%U0,%2\;add%F3 %L0,%2,-32\;srl%F3 %L0,%U0,%L0\;or%F3 %U0,%.,0" - [(set_attr "length" "8,8,28") - (set_attr "type" "multi")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 32 Bit Integer Logical operations -;; :: -;; :::::::::::::::::::: - -;; Logical AND, 32 bit integers -(define_expand "andsi3" - [(set (match_operand:SI 0 "gpr_operand" "") - (and:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_constant_operand" "")))] - "" - "") - -(define_insn "*andsi3_register" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (and:SI (match_operand:SI 1 "gpr_operand" "%d") - (match_operand:SI 2 "gpr_operand" "d")))] - "" - "and %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*andsi3_move" - [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (and:SI (match_operand:SI 1 "gpr_operand" "%0,d") - (match_operand:SI 2 "const_int_operand" "n,n")))] - "((INTVAL (operands[2]) & 0xffffffff) == 0xffffffff)" - "@ - ; and 0xffffffff to same register - and %0,%1,-1" - [(set_attr "length" "0,4") - (set_attr "type" "either")]) - -(define_insn "*andsi3_constant" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (and:SI (match_operand:SI 1 "gpr_operand" "%d,d,d,d") - (match_operand:SI 2 "const_int_operand" "L,O,I,i")))] - "" - "@ - bclr %0,%1,%B2 - or %0,%.,0 - and %0,%1,%2 - and %0,%1,%2" - [(set_attr "length" "4,4,4,8") - (set_attr "type" "either,either,either,long")]) - -(define_insn "*andsi3_bclr" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (and:SI (match_operand:SI 1 "gpr_operand" "d") - (not:SI (lshiftrt:SI (const_int -2147483648) - (match_operand:SI 2 "gpr_operand" "d")))))] - "" - "bclr %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Inclusive OR, 32 bit integers -(define_expand "iorsi3" - [(set (match_operand:SI 0 "gpr_operand" "") - (ior:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_constant_operand" "")))] - "" - "") - -(define_insn "*iorsi3_register" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (ior:SI (match_operand:SI 1 "gpr_operand" "%d") - (match_operand:SI 2 "gpr_operand" "d")))] - "" - "or %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*iorsi3_constant" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (ior:SI (match_operand:SI 1 "gpr_operand" "%d,0,d,d") - (match_operand:SI 2 "const_int_operand" "K,O,I,i")))] - "" - "@ - bset %0,%1,%B2 - ; or 0 to same register (%0) - or %0,%1,%2 - or %0,%1,%2" - [(set_attr "length" "4,0,4,8") - (set_attr "type" "either,either,either,long")]) - -(define_insn "*iorsi3_bset" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (ior:SI (match_operand:SI 1 "gpr_operand" "d") - (lshiftrt:SI (const_int -2147483648) - (match_operand:SI 2 "gpr_operand" "d"))))] - "" - "bset %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Exclusive OR, 32 bit integers -(define_expand "xorsi3" - [(set (match_operand:SI 0 "gpr_operand" "") - (xor:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_constant_operand" "")))] - "" - "") - -(define_insn "*xorsi3_register" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (xor:SI (match_operand:SI 1 "gpr_operand" "%d") - (match_operand:SI 2 "gpr_operand" "d")))] - "" - "xor %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*xorsi3_constant" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (xor:SI (match_operand:SI 1 "gpr_operand" "%d,0,d,d") - (match_operand:SI 2 "const_int_operand" "K,O,I,i")))] - "" - "@ - bnot %0,%1,%B2 - ; xor 0 to same register (%0) - xor %0,%1,%2 - xor %0,%1,%2" - [(set_attr "length" "4,0,4,8") - (set_attr "type" "either,either,either,long")]) - -(define_insn "*iorsi3_bnot" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (xor:SI (match_operand:SI 1 "gpr_operand" "d") - (lshiftrt:SI (const_int -2147483648) - (match_operand:SI 2 "gpr_operand" "d"))))] - "" - "bnot %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; One's complement, 32 bit integers -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (not:SI (match_operand:SI 1 "gpr_operand" "d")))] - "" - "not %0,%1" - [(set_attr "length" "4") - (set_attr "type" "either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 64 Bit Integer Logical operations -;; :: -;; :::::::::::::::::::: - -;; Logical AND, 64 bit integers -(define_insn "anddi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,&e,e,e,e") - (and:DI (match_operand:DI 1 "gpr_operand" "%e,0,e,e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "0,e,e,I,i,F")))] - "" - "#" - [(set_attr "length" "8,8,8,8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (and:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 3) (and:SI (match_dup 4) (match_dup 5))) - (set (match_dup 6) (and:SI (match_dup 7) (match_dup 8)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[6]); - d30v_split_double (operands[1], &operands[4], &operands[7]); - d30v_split_double (operands[2], &operands[5], &operands[8]); -}") - -;; Includive OR, 64 bit integers -(define_insn "iordi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,&e,e,e,e") - (ior:DI (match_operand:DI 1 "gpr_operand" "%e,0,e,e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "0,e,e,I,i,F")))] - "" - "#" - [(set_attr "length" "8,8,8,8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (ior:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 3) (ior:SI (match_dup 4) (match_dup 5))) - (set (match_dup 6) (ior:SI (match_dup 7) (match_dup 8)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[6]); - d30v_split_double (operands[1], &operands[4], &operands[7]); - d30v_split_double (operands[2], &operands[5], &operands[8]); -}") - -;; Excludive OR, 64 bit integers -(define_insn "xordi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,&e,e,e,e") - (xor:DI (match_operand:DI 1 "gpr_operand" "%e,0,e,e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "0,e,e,I,i,F")))] - "" - "#" - [(set_attr "length" "8,8,8,8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (xor:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 3) (xor:SI (match_dup 4) (match_dup 5))) - (set (match_dup 6) (xor:SI (match_dup 7) (match_dup 8)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[6]); - d30v_split_double (operands[1], &operands[4], &operands[7]); - d30v_split_double (operands[2], &operands[5], &operands[8]); -}") - -;; One's complement, 64 bit integers -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,&e") - (not:DI (match_operand:DI 1 "gpr_operand" "0,e")))] - "" - "#" - [(set_attr "length" "8") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (not:DI (match_operand:DI 1 "gpr_operand" "")))] - "reload_completed" - [(set (match_dup 3) (not:SI (match_dup 4))) - (set (match_dup 5) (not:SI (match_dup 6)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[5]); - d30v_split_double (operands[1], &operands[4], &operands[6]); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Multiply and accumulate instructions -;; :: -;; :::::::::::::::::::: - -(define_insn "*mac_reg" - [(set (match_operand:DI 0 "accum_operand" "+a") - (plus:DI (match_dup 0) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d")))))] - "" - "mac%A0 %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*mac_const" - [(set (match_operand:DI 0 "accum_operand" "+a") - (plus:DI (match_dup 0) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (match_operand:DI 2 "signed6_operand" "I"))))] - "" - "mac%A0 %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*macs_reg" - [(set (match_operand:DI 0 "accum_operand" "+a") - (plus:DI (match_dup 0) - (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d"))) - (const_int 1))))] - "" - "macs%A0 %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*macs_const" - [(set (match_operand:DI 0 "accum_operand" "+a") - (plus:DI (match_dup 0) - (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (match_operand:DI 2 "signed6_operand" "I")) - (const_int 1))))] - "" - "macs%A0 %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*msub_reg" - [(set (match_operand:DI 0 "accum_operand" "+a") - (minus:DI (match_dup 0) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d")))))] - "" - "msub%A0 %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*msub_const" - [(set (match_operand:DI 0 "accum_operand" "+a") - (minus:DI (match_dup 0) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (match_operand:DI 2 "signed6_operand" "I"))))] - "" - "msub%A0 %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*msubs_reg" - [(set (match_operand:DI 0 "accum_operand" "+a") - (minus:DI (match_dup 0) - (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d"))) - (const_int 1))))] - "" - "msubs%A0 %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*msubs_const" - [(set (match_operand:DI 0 "accum_operand" "+a") - (minus:DI (match_dup 0) - (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (match_operand:DI 2 "signed6_operand" "I")) - (const_int 1))))] - "" - "msubs%A0 %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Comparisons -;; :: -;; :::::::::::::::::::: - -;; Note, we store the operands in the comparison insns, and use them later -;; when generating the branch or scc operation. - -;; First the routines called by the machine independent part of the compiler -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "gpr_operand" "") - (match_operand:SI 1 "gpr_or_constant_operand" "")))] - "" - " -{ - d30v_compare_op0 = operands[0]; - d30v_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "gpr_operand" "") - (match_operand:DI 1 "nonmemory_operand" "")))] - "" - " -{ - d30v_compare_op0 = operands[0]; - d30v_compare_op1 = operands[1]; - DONE; -}") - -;; Now, the actual comparisons, generated by the branch and/or scc operations - -;; 32 bit integer tests -(define_insn "*srelational" - [(set (match_operand:CC 0 "flag_operand" "=f,f") - (match_operator:CC 1 "srelational_si_operator" - [(match_operand:SI 2 "gpr_operand" "d,d") - (match_operand:SI 3 "gpr_or_constant_operand" "dI,i")]))] - "" - "%R1 %0,%2,%3" - [(set_attr "length" "4,8") - (set_attr "type" "scmp,lcmp")]) - -(define_insn "*urelational" - [(set (match_operand:CC 0 "flag_operand" "=f,f") - (match_operator:CC 1 "urelational_si_operator" - [(match_operand:SI 2 "gpr_operand" "d,d") - (match_operand:SI 3 "gpr_or_constant_operand" "dJP,i")]))] - "" - "%R1 %0,%2,%3" - [(set_attr "length" "4,8") - (set_attr "type" "scmp,lcmp")]) - -;; Code used after splitting DI compares - -(define_insn "*movcccc_signed_true" - [(set (match_operand:CC 0 "flag_operand" "=f,f") - (if_then_else:CC (match_operand:CC 1 "br_flag_operand" "f,f") - (match_operator:CC 3 "srelational_si_operator" - [(match_operand:SI 4 "gpr_operand" "d,d") - (match_operand:SI 5 "gpr_or_constant_operand" "dI,i")]) - (match_dup 0)))] - "" - "%R3%T1 %0,%4,%5" - [(set_attr "length" "4,8") - (set_attr "type" "scmp,lcmp")]) - -(define_insn "*movcccc_signed_false" - [(set (match_operand:CC 0 "flag_operand" "=f,f") - (if_then_else:CC (match_operand:CC 1 "br_flag_operand" "f,f") - (match_dup 0) - (match_operator:CC 3 "srelational_si_operator" - [(match_operand:SI 4 "gpr_operand" "d,d") - (match_operand:SI 5 "gpr_or_constant_operand" "dI,i")])))] - "" - "%R3%F1 %0,%4,%5" - [(set_attr "length" "4,8") - (set_attr "type" "scmp,lcmp")]) - -(define_insn "*movcccc_unsigned_true" - [(set (match_operand:CC 0 "flag_operand" "=f,f") - (if_then_else:CC (match_operand:CC 1 "br_flag_operand" "f,f") - (match_operator:CC 3 "urelational_si_operator" - [(match_operand:SI 4 "gpr_operand" "d,d") - (match_operand:SI 5 "gpr_or_constant_operand" "dJP,i")]) - (match_dup 0)))] - "" - "%R3%T1 %0,%4,%5" - [(set_attr "length" "4,8") - (set_attr "type" "scmp,lcmp")]) - -(define_insn "*movcccc_unsigned_false" - [(set (match_operand:CC 0 "flag_operand" "=f,f") - (if_then_else:CC (match_operand:CC 1 "br_flag_operand" "f,f") - (match_dup 0) - (match_operator:CC 3 "urelational_si_operator" - [(match_operand:SI 4 "gpr_operand" "d,d") - (match_operand:SI 5 "gpr_or_constant_operand" "dJP,i")])))] - "" - "%R3%F1 %0,%4,%5" - [(set_attr "length" "4,8") - (set_attr "type" "scmp,lcmp")]) - -;; 64 bit integer tests -(define_insn "*eqdi_internal" - [(set (match_operand:CC 0 "br_flag_operand" "=b,b,b") - (eq:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eI,i,F")))] - "" - "#" - [(set_attr "length" "8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:CC 0 "br_flag_operand" "") - (eq:CC (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 0) - (eq:CC (match_dup 3) - (match_dup 4))) - (set (match_dup 0) - (if_then_else:CC (match_dup 0) - (eq:CC (match_dup 5) - (match_dup 6)) - (match_dup 0)))] - " -{ - d30v_split_double (operands[1], &operands[3], &operands[5]); - d30v_split_double (operands[2], &operands[4], &operands[6]); -}") - -(define_insn "*nedi_internal" - [(set (match_operand:CC 0 "br_flag_operand" "=b,b,b") - (ne:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eI,i,F")))] - "" - "#" - [(set_attr "length" "8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:CC 0 "br_flag_operand" "") - (ne:CC (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 0) - (ne:CC (match_dup 3) - (match_dup 4))) - (set (match_dup 0) - (if_then_else:CC (match_dup 0) - (match_dup 0) - (ne:CC (match_dup 5) - (match_dup 6))))] - " -{ - d30v_split_double (operands[1], &operands[3], &operands[5]); - d30v_split_double (operands[2], &operands[4], &operands[6]); -}") - -(define_insn "*ltdi_zero" - [(set (match_operand:CC 0 "flag_operand" "=f") - (lt:CC (match_operand:DI 1 "gpr_operand" "e") - (const_int 0)))] - "" - "cmplt %0,%U1,0" - [(set_attr "length" "4") - (set_attr "type" "scmp")]) - -(define_insn "*ltdi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (lt:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*ledi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (le:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*gtdi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (gt:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*gedi_zero" - [(set (match_operand:CC 0 "flag_operand" "=f") - (ge:CC (match_operand:DI 1 "gpr_operand" "e") - (const_int 0)))] - "" - "cmpge %0,%U1,0" - [(set_attr "length" "4") - (set_attr "type" "scmp")]) - -(define_insn "*gedi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (ge:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*ltudi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (ltu:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*leudi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (leu:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*gtudi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (gtu:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*geudi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (geu:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:CC 0 "flag_operand" "") - (match_operator:CC 1 "relational_di_operator" - [(match_operand:DI 2 "gpr_operand" "") - (match_operand:DI 3 "gpr_or_dbl_const_operand" "")])) - (clobber (match_operand:CC 4 "br_flag_operand" ""))] - "reload_completed" - [(match_dup 5) - (match_dup 6) - (match_dup 7)] - " -{ - enum rtx_code cond = GET_CODE (operands[1]); - enum rtx_code ucond = unsigned_condition (cond); - rtx tmpflag = operands[4]; - rtx outflag = operands[0]; - rtx high[2]; - rtx low[2]; - - d30v_split_double (operands[2], &high[0], &low[0]); - d30v_split_double (operands[3], &high[1], &low[1]); - - operands[5] = gen_rtx (SET, VOIDmode, - tmpflag, - gen_rtx (EQ, CCmode, high[0], high[1])); - - operands[6] = gen_rtx (SET, VOIDmode, - outflag, - gen_rtx (IF_THEN_ELSE, CCmode, - tmpflag, - outflag, - gen_rtx (cond, CCmode, high[0], high[1]))); - - operands[7] = gen_rtx (SET, VOIDmode, - outflag, - gen_rtx (IF_THEN_ELSE, CCmode, - tmpflag, - gen_rtx (ucond, CCmode, low[0], low[1]), - outflag)); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Branches -;; :: -;; :::::::::::::::::::: - -;; Define_expands called by the machine independent part of the compiler -;; to allocate a new comparison register - -(define_expand "beq" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (EQ, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bne" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (NE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bgt" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GT, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bge" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "blt" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LT, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "ble" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bgtu" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GTU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bgeu" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GEU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bltu" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LTU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bleu" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LEU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -;; Actual branches. We must allow for the (label_ref) and the (pc) to be -;; swapped. If they are swapped, it reverses the sense of the branch. -;; Also handle changing the ne to eq. -;; In order for the length calculations to be correct, the label must be -;; operand 0. - -;; We used to handle branches against 0 to be folded directly into -;; bratnz/bratzr instruction, but this dimisses the possibility of doing -;; conditional execution. Instead handle these via peepholes. - -;; Branches based off of the flag bits -(define_insn "*bra_true" - [(set (pc) - (if_then_else (match_operator:CC 1 "condexec_branch_operator" - [(match_operand:CC 2 "br_flag_or_constant_operand" "b,I,N") - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - return \"bra%F1 %l0\"; - - if (GET_CODE (operands[1]) != CONST_INT) - fatal_insn (\"bad jump\", insn); - - if ((GET_CODE (operands[1]) == EQ && INTVAL (operands[2]) == 0) - || (GET_CODE (operands[1]) == NE && INTVAL (operands[2]) != 0)) - return \"bra %l0\"; - - return \"; jump to %l0 optimized away\"; -}" - [(set_attr "type" "br")]) - -(define_insn "*bra_false" - [(set (pc) - (if_then_else (match_operator:CC 1 "condexec_branch_operator" - [(match_operand:CC 2 "br_flag_or_constant_operand" "b,I,N") - (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - return \"bra%T1 %l0\"; - - if (GET_CODE (operands[1]) != CONST_INT) - fatal_insn (\"bad jump\", insn); - - if ((GET_CODE (operands[1]) == EQ && INTVAL (operands[2]) != 0) - || (GET_CODE (operands[1]) == NE && INTVAL (operands[2]) == 0)) - return \"bra %l0\"; - - return \"; jump to %l0 optimized away\"; -}" - [(set_attr "type" "br")]) - -;; Peepholes to turn set flag, cond. jumps into branch if register ==/!= 0. - -(define_peephole - [(set (match_operand:CC 1 "br_flag_operand" "=b") - (match_operator:CC 2 "branch_zero_operator" - [(match_operand:SI 3 "gpr_operand" "d") - (const_int 0)])) - (set (pc) - (if_then_else (match_operator:CC 4 "condexec_test_operator" - [(match_dup 1) - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "(find_regno_note (insn, REG_DEAD, REGNO (operands[1])) != 0)" - "* -{ - int true_false = 1; - - if (GET_CODE (operands[2]) == EQ) - true_false = !true_false; - - if (GET_CODE (operands[4]) == EQ) - true_false = !true_false; - - return (true_false) ? \"bratnz %3,%l0\" : \"bratzr %3,%l0\"; -}" - [(set_attr "type" "br2")]) - -(define_peephole - [(set (match_operand:CC 1 "br_flag_operand" "=b") - (match_operator:CC 2 "branch_zero_operator" - [(match_operand:SI 3 "gpr_operand" "d") - (const_int 0)])) - (set (pc) - (if_then_else (match_operator:CC 4 "condexec_test_operator" - [(match_dup 1) - (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "(find_regno_note (insn, REG_DEAD, REGNO (operands[1])) != 0)" - "* -{ - int true_false = 0; - - if (GET_CODE (operands[2]) == EQ) - true_false = !true_false; - - if (GET_CODE (operands[4]) == EQ) - true_false = !true_false; - - return (true_false) ? \"bratnz %3,%l0\" : \"bratzr %3,%l0\"; -}" - [(set_attr "type" "br2")]) - -;; Convert if (a & mask) into btst. */ -(define_peephole - [(set (match_operand:SI 0 "gpr_operand" "=d") - (and:SI (match_operand:SI 1 "gpr_operand" "%d") - (match_operand:SI 2 "bitset_operand" "K"))) - (set (match_operand:CC 3 "flag_operand" "=f") - (ne:CC (match_dup 0) - (const_int 0)))] - "(find_regno_note (prev_nonnote_insn (insn), REG_DEAD, REGNO (operands[0])) != 0)" - "btst %3,%1,%B2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Set flag operations -;; :: -;; :::::::::::::::::::: - -;; Define_expands called by the machine independent part of the compiler -;; to allocate a new comparison register - -;; ??? These patterns should all probably use (ne:SI ... (const_int 0)) instead -;; of (eq:SI ... (const_int 1)), because the former is the canonical form. -;; The non-canonical form was used here because I was just trying to get the -;; port working again after it broke, and the non-canonical form was the -;; safer faster way to fix this. - - -(define_expand "seq" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (EQ, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sne" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (NE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sgt" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GT, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sge" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "slt" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LT, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sle" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sgtu" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GTU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sgeu" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GEU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sltu" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LTU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sleu" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (eq:SI (match_dup 1) (const_int 1)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LEU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -;; Set flag operations We purposely prefer using flag registers other than f0 -;; and f1 to allow the setcc operations not add to the register pressure on -;; f0/f1. -(define_insn "*setcc_internal" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,!*d") - (eq:SI (match_operand:CC 1 "flag_operand" "z,!b,!*d") - (const_int 1)))] - "" - "@ - mvfsys %0,%1 - mvfsys %0,%1 - or %0,%.,%1" - [(set_attr "length" "4") - (set_attr "type" "either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Operations on flags -;; :: -;; :::::::::::::::::::: - -(define_insn "andcc3" - [(set (match_operand:CC 0 "flag_operand" "=f") - (and:CC (match_operand:CC 1 "flag_operand" "f") - (match_operand:CC 2 "flag_operand" "f")))] - "" - "andfg %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "iorcc3" - [(set (match_operand:CC 0 "flag_operand" "=f") - (ior:CC (match_operand:CC 1 "flag_operand" "f") - (match_operand:CC 2 "flag_operand" "f")))] - "" - "orfg %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "xorcc3" - [(set (match_operand:CC 0 "flag_operand" "=f") - (xor:CC (match_operand:CC 1 "flag_operand" "f") - (match_operand:CC 2 "flag_operand" "f")))] - "" - "xorfg %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; This is the canonical form produced by combine. - -(define_insn "incscc" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (plus:SI (eq:SI (match_operand:CC 1 "br_flag_operand" "b") - (const_int 1)) - (match_operand:SI 2 "gpr_operand" "d")))] - "" - "add%T1 %0,%2,1" -[(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "decscc" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (minus:SI (match_operand:SI 1 "gpr_operand" "d") - (eq:SI (match_operand:CC 2 "br_flag_operand" "b") - (const_int 1))))] - "" - "sub%T2 %0,%1,1" -[(set_attr "length" "4") - (set_attr "type" "either")]) - -;; :::::::::::::::::::: -;; :: -;; :: Call and branch instructions -;; :: -;; :::::::::::::::::::: - -;; Subroutine call instruction returning no value. Operand 0 is the function -;; to call; operand 1 is the number of bytes of arguments pushed (in mode -;; `SImode', except it is normally a `const_int'); operand 2 is the number of -;; registers used as operands. - -;; On most machines, operand 2 is not actually stored into the RTL pattern. It -;; is supplied for the sake of some RISC machines which need to put this -;; information into the assembler code; they can put it in the RTL instead of -;; operand 1. - -(define_expand "call" - [(parallel [(call (match_operand 0 "call_operand" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (clobber (match_dup 3))])] - "" - " -{ - if (GET_CODE (XEXP (operands[0], 0)) == SUBREG) - XEXP (operands[0], 0) = copy_addr_to_reg (XEXP (operands[0], 0)); - - if (!operands[2]) - operands[2] = const0_rtx; - - operands[3] = gen_rtx (REG, Pmode, GPR_LINK); -}") - -(define_insn "*call_internal" - [(call (match_operand 0 "call_operand" "R,S") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (clobber (match_operand 3 "" "=d,d"))] - "" - "@ - jsr %0 - bsr %0" - [(set_attr "length" "4,8") - (set_attr "type" "mu,long")]) - -;; Subroutine call instruction returning a value. Operand 0 is the hard -;; register in which the value is returned. There are three more operands, the -;; same as the three operands of the `call' instruction (but with numbers -;; increased by one). - -;; Subroutines that return `BLKmode' objects use the `call' insn. - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "gpr_operand" "") - (call (match_operand 1 "call_operand" "") - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (clobber (match_dup 4))])] - "" - " -{ - if (GET_CODE (XEXP (operands[1], 0)) == SUBREG) - XEXP (operands[1], 0) = copy_addr_to_reg (XEXP (operands[1], 0)); - - if (!operands[3]) - operands[3] = const0_rtx; - - operands[4] = gen_rtx (REG, Pmode, GPR_LINK); -}") - -(define_insn "*call_value_internal" - [(set (match_operand 0 "gpr_operand" "=d,d") - (call (match_operand 1 "call_operand" "R,S") - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (clobber (match_operand 4 "" "=d,d"))] - "" - "@ - jsr %1 - bsr %1" - [(set_attr "length" "4,8") - (set_attr "type" "mu,long")]) - -;; Subroutine return -(define_insn "return" - [(return)] - "direct_return ()" - "jmp link" - [(set_attr "length" "4")]) - -;; Normal unconditional jump -(define_insn "jump" - [(set (pc) (label_ref (match_operand 0 "" "")))] - "" - "bra %l0" - [(set_attr "type" "br")]) - -;; Indirect jump through a register -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "gpr_operand" "d"))] - "" - "jmp %0" - [(set_attr "length" "4") - (set_attr "type" "mu")]) - -;; Instruction to jump to a variable address. This is a low-level capability -;; which can be used to implement a dispatch table when there is no `casesi' -;; pattern. - -;; This pattern requires two operands: the address or offset, and a label which -;; should immediately precede the jump table. If the macro -;; `CASE_VECTOR_PC_RELATIVE' is defined then the first operand is an offset -;; which counts from the address of the table; otherwise, it is an absolute -;; address to jump to. In either case, the first operand has mode `Pmode'. - -;; The `tablejump' insn is always the last insn before the jump table it uses. -;; Its assembler code normally has no need to use the second operand, but you -;; should incorporate it in the RTL pattern so that the jump optimizer will not -;; delete the table as unreachable code. - -(define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "gpr_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] - "" - "jmp %0" - [(set_attr "length" "4") - (set_attr "type" "mu")]) - - - -;; :::::::::::::::::::: -;; :: -;; :: Prologue and Epilogue instructions -;; :: -;; :::::::::::::::::::: - -;; Called after register allocation to add any instructions needed for the -;; prologue. Using a prologue insn is favored compared to putting all of the -;; instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler -;; to intermix instructions with the saves of the caller saved registers. In -;; some cases, it might be necessary to emit a barrier instruction as the last -;; insn to prevent such scheduling. - -(define_expand "prologue" - [(const_int 1)] - "" - " -{ - d30v_expand_prologue (); - DONE; -}") - -;; Called after register allocation to add any instructions needed for the -;; epilogue. Using a epilogue insn is favored compared to putting all of the -;; instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler -;; to intermix instructions with the saves of the caller saved registers. In -;; some cases, it might be necessary to emit a barrier instruction as the last -;; insn to prevent such scheduling. - -(define_expand "epilogue" - [(const_int 2)] - "" - " -{ - d30v_expand_epilogue (); - DONE; -}") - -(define_expand "eh_epilogue" - [(use (match_operand:DI 0 "register_operand" "r")) - (use (match_operand:DI 1 "register_operand" "r")) - (use (match_operand:DI 2 "register_operand" "r"))] - "" - " -{ - d30v_eh_epilogue_sp_ofs = operands[1]; - if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != GPR_LINK) - { - rtx ra = gen_rtx_REG (Pmode, GPR_LINK); - emit_move_insn (ra, operands[2]); - operands[2] = ra; - } -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Conditional move instructions -;; :: -;; :::::::::::::::::::: - -;; Conditionally move operand 2 or operand 3 into operand 0 according to the -;; comparison in operand 1. If the comparison is true, operand 2 is moved into -;; operand 0, otherwise operand 3 is moved. - -;; The mode of the operands being compared need not be the same as the operands -;; being moved. Some machines, sparc64 for example, have instructions that -;; conditionally move an integer value based on the floating point condition -;; codes and vice versa. - -;; If the machine does not have conditional move instructions, do not -;; define these patterns. - -(define_expand "movqicc" - [(set (match_operand:QI 0 "cond_move_operand" "") - (if_then_else:QI (match_operand 1 "" "") - (match_operand:QI 2 "cond_move_operand" "") - (match_operand:QI 3 "cond_move_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!d30v_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movqicc_internal" - [(set (match_operand:QI 0 "cond_move_operand" "=d,d,d,d,&d,Q,m") - (if_then_else:QI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "b,b,b,b,b,b,b") - (const_int 0)]) - (match_operand:QI 3 "cond_move_operand" "0,dIQ,0,im,dim,dO,dO") - (match_operand:QI 4 "cond_move_operand" "dIQ,0,im,0,dim,dO,dO")))] - "TARGET_COND_MOVE - && (GET_CODE (operands[0]) != MEM - || (reg_or_0_operand (operands[2], QImode) - && reg_or_0_operand (operands[3], QImode)))" - "* return d30v_cond_move (operands, insn, \"ldbu\", \"stb\");" - [(set_attr "type" "either,either,long,long,multi,multi,multi") - (set_attr "length" "4,4,8,8,16,8,16")]) - -(define_expand "movhicc" - [(set (match_operand:HI 0 "cond_move_operand" "") - (if_then_else:HI (match_operand 1 "" "") - (match_operand:HI 2 "cond_move_operand" "") - (match_operand:HI 3 "cond_move_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!d30v_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movhicc_internal" - [(set (match_operand:HI 0 "cond_move_operand" "=d,d,d,d,&d,Q,m") - (if_then_else:HI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "b,b,b,b,b,b,b") - (const_int 0)]) - (match_operand:HI 3 "cond_move_operand" "0,dIQ,0,im,dim,dO,dO") - (match_operand:HI 4 "cond_move_operand" "dIQ,0,im,0,dim,dO,dO")))] - "TARGET_COND_MOVE - && (GET_CODE (operands[0]) != MEM - || (reg_or_0_operand (operands[2], HImode) - && reg_or_0_operand (operands[3], HImode)))" - "* return d30v_cond_move (operands, insn, \"ldhu\", \"sth\");" - [(set_attr "type" "either,either,long,long,multi,multi,multi") - (set_attr "length" "4,4,8,8,16,8,16")]) - -(define_expand "movsicc" - [(set (match_operand:SI 0 "cond_move_operand" "") - (if_then_else:SI (match_operand 1 "" "") - (match_operand:SI 2 "cond_move_operand" "") - (match_operand:SI 3 "cond_move_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!d30v_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movsicc_internal" - [(set (match_operand:SI 0 "cond_move_operand" "=d,d,d,d,&d,Q,m") - (if_then_else:SI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "b,b,b,b,b,b,b") - (const_int 0)]) - (match_operand:SI 3 "cond_move_operand" "0,dIQ,0,im,dim,dO,dO") - (match_operand:SI 4 "cond_move_operand" "dIQ,0,im,0,dim,dO,dO")))] - "TARGET_COND_MOVE - && (GET_CODE (operands[0]) != MEM - || (reg_or_0_operand (operands[2], SImode) - && reg_or_0_operand (operands[3], SImode)))" - "* return d30v_cond_move (operands, insn, \"ldw\", \"stw\");" - [(set_attr "type" "either,either,long,long,multi,multi,multi") - (set_attr "length" "4,4,8,8,16,8,16")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Conditional execution -;; :: -;; :::::::::::::::::::: - -(define_insn "*cond_exec_qi_store_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (set (match_operand:QI 0 "memory_operand" "=Q,Q,m,m") - (match_operand:QI 1 "reg_or_0_operand" "d,O,d,O")) - (const_int 0))] - "" - "@ - stb%T2 %1,%M0 - stb%T2 %.,%M0 - stb%T2 %1,%M0 - stb%T2 %.,%M0" - [(set_attr "length" "4,4,8,8") - (set_attr "type" "mu,mu,long,long")]) - -(define_insn "*cond_exec_qi_store_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:QI 0 "memory_operand" "=Q,Q,m,m") - (match_operand:QI 1 "reg_or_0_operand" "d,O,d,O")))] - "" - "@ - stb%F2 %1,%M0 - stb%F2 %.,%M0 - stb%F2 %1,%M0 - stb%F2 %.,%M0" - [(set_attr "length" "4,4,8,8") - (set_attr "type" "mu,mu,long,long")]) - -(define_insn "*cond_exec_qi_load_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (set (match_operand:QI 0 "gpr_operand" "=d,d,d,d") - (match_operand:QI 1 "cond_exec_operand" "dI,i,Q,m")) - (const_int 0))] - "" - "@ - or%T2 %0,%.,%1 - or%T2 %0,%.,%1 - ldb%T2 %0,%M1 - ldb%T2 %0,%M1" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,sload,lload")]) - -(define_insn "*cond_exec_qi_load_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:QI 0 "gpr_operand" "=d,d,d,d") - (match_operand:QI 1 "cond_exec_operand" "dI,i,Q,m")))] - "" - "@ - or%F2 %0,%.,%1 - or%F2 %0,%.,%1 - ldb%F2 %0,%M1 - ldb%F2 %0,%M1" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,sload,lload")]) - -(define_insn "*cond_exec_hi_store_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (set (match_operand:HI 0 "memory_operand" "=Q,Q,m,m") - (match_operand:HI 1 "reg_or_0_operand" "d,O,d,O")) - (const_int 0))] - "" - "@ - sth%T2 %1,%M0 - sth%T2 %.,%M0 - sth%T2 %1,%M0 - sth%T2 %.,%M0" - [(set_attr "length" "4,4,8,8") - (set_attr "type" "mu,mu,long,long")]) - -(define_insn "*cond_exec_hi_store_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:HI 0 "memory_operand" "=Q,Q,m,m") - (match_operand:HI 1 "reg_or_0_operand" "d,O,d,O")))] - "" - "@ - sth%F2 %1,%M0 - sth%F2 %.,%M0 - sth%F2 %1,%M0 - sth%F2 %.,%M0" - [(set_attr "length" "4,4,8,8") - (set_attr "type" "mu,mu,long,long")]) - -(define_insn "*cond_exec_hi_load_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (set (match_operand:HI 0 "gpr_operand" "=d,d,d,d") - (match_operand:HI 1 "cond_exec_operand" "dI,i,Q,m")) - (const_int 0))] - "" - "@ - or%T2 %0,%.,%1 - or%T2 %0,%.,%1 - ldh%T2 %0,%M1 - ldh%T2 %0,%M1" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,sload,lload")]) - -(define_insn "*cond_exec_hi_load_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:HI 0 "gpr_operand" "=d,d,d,d") - (match_operand:HI 1 "cond_exec_operand" "dI,i,Q,m")))] - "" - "@ - or%F2 %0,%.,%1 - or%F2 %0,%.,%1 - ldh%F2 %0,%M1 - ldh%F2 %0,%M1" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,sload,lload")]) - -(define_insn "*cond_exec_hi_extend_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b") - (const_int 0)]) - (set (match_operand:HI 0 "gpr_operand" "=d,d") - (match_operator:HI 4 "condexec_extend_operator" - [(match_operand 1 "d30v_memory_operand" "Q,m")])) - (const_int 0))] - "" - "ldb%E4%T2 %0,%M1" - [(set_attr "length" "4,8") - (set_attr "type" "sload,lload")]) - -(define_insn "*cond_exec_hi_extend_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:HI 0 "gpr_operand" "=d,d") - (match_operator:HI 4 "condexec_extend_operator" - [(match_operand 1 "d30v_memory_operand" "Q,m")])))] - "" - "ldb%E4%F2 %0,%M1" - [(set_attr "length" "4,8") - (set_attr "type" "sload,lload")]) - -(define_insn "*cond_exec_hi_extend2_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b") - (const_int 0)]) - (set (match_operand:HI 0 "gpr_operand" "=d") - (zero_extend:HI (match_operand:QI 1 "gpr_operand" "d"))) - (const_int 0))] - "" - "and%T2 %0,%1,0xff" - [(set_attr "length" "8") - (set_attr "type" "long")]) - -(define_insn "*cond_exec_hi_extend2_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b") - (const_int 0)]) - (const_int 0) - (set (match_operand:HI 0 "gpr_operand" "=d") - (zero_extend:HI (match_operand:QI 1 "gpr_operand" "d"))))] - "" - "and%F2 %0,%1,0xff" - [(set_attr "length" "8") - (set_attr "type" "long")]) - -(define_insn "*cond_exec_si_store_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (set (match_operand:SI 0 "memory_operand" "=Q,Q,m,m") - (match_operand:SI 1 "reg_or_0_operand" "d,O,d,O")) - (const_int 0))] - "" - "@ - stw%T2 %1,%M0 - stw%T2 %.,%M0 - stw%T2 %1,%M0 - stw%T2 %.,%M0" - [(set_attr "length" "4,4,8,8") - (set_attr "type" "mu,mu,long,long")]) - -(define_insn "*cond_exec_si_store_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "memory_operand" "=Q,Q,m,m") - (match_operand:SI 1 "reg_or_0_operand" "d,O,d,O")))] - "" - "@ - stw%F2 %1,%M0 - stw%F2 %.,%M0 - stw%F2 %1,%M0 - stw%F2 %.,%M0" - [(set_attr "length" "4,4,8,8") - (set_attr "type" "mu,mu,long,long")]) - -(define_insn "*cond_exec_si_load_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (match_operand:SI 1 "cond_exec_operand" "dI,i,Q,m")) - (const_int 0))] - "" - "@ - or%T2 %0,%.,%1 - or%T2 %0,%.,%1 - ldw%T2 %0,%M1 - ldw%T2 %0,%M1" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,sload,lload")]) - -(define_insn "*cond_exec_si_load_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (match_operand:SI 1 "cond_exec_operand" "dI,i,Q,m")))] - "" - "@ - or%F2 %0,%.,%1 - or%F2 %0,%.,%1 - ldw%F2 %0,%M1 - ldw%F2 %0,%M1" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,sload,lload")]) - -(define_insn "*cond_exec_si_unary_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=d") - (match_operator:SI 4 "condexec_unary_operator" - [(match_operand:SI 1 "gpr_operand" "d")])) - (const_int 0))] - "" - "* -{ - switch (GET_CODE (operands[4])) - { - default: - fatal_insn (\"cond_exec_si_unary_true:\", insn); - - case ABS: return \"abs%T2 %0,%1\"; - case NOT: return \"not%T2 %0,%1\"; - case NEG: return \"sub%T2 %0,%.,%1\"; - } -}" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*cond_exec_si_unary_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=d") - (match_operator:SI 4 "condexec_unary_operator" - [(match_operand:SI 1 "gpr_operand" "d")])))] - "" - "* -{ - switch (GET_CODE (operands[4])) - { - default: - fatal_insn (\"cond_exec_si_unary_false:\", insn); - - case ABS: return \"abs%F2 %0,%1\"; - case NOT: return \"not%F2 %0,%1\"; - case NEG: return \"sub%F2 %0,%.,%1\"; - } -}" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*cond_exec_si_extend_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=d,d") - (match_operator:SI 4 "condexec_extend_operator" - [(match_operand 1 "d30v_memory_operand" "Q,m")])) - (const_int 0))] - "" - "* -{ - return ((GET_MODE (operands[1]) == QImode) - ? \"ldb%E4%T2 %0,%M1\" - : \"ldh%E4%T2 %0,%M1\"); -}" - [(set_attr "length" "4,8") - (set_attr "type" "sload,lload")]) - -(define_insn "*cond_exec_si_extend_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=d,d") - (match_operator:SI 4 "condexec_extend_operator" - [(match_operand 1 "d30v_memory_operand" "Q,m")])))] - "" - "* -{ - return ((GET_MODE (operands[1]) == QImode) - ? \"ldb%E4%F2 %0,%M1\" - : \"ldh%E4%F2 %0,%M1\"); -}" - [(set_attr "length" "4,8") - (set_attr "type" "sload,lload")]) - -(define_insn "*cond_exec_si_extend2_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=d") - (zero_extend:SI (match_operand:QI 1 "gpr_operand" "d"))) - (const_int 0))] - "" - "and%T2 %0,%1,0xff" - [(set_attr "length" "8") - (set_attr "type" "long")]) - -(define_insn "*cond_exec_si_extend2_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=d") - (zero_extend:SI (match_operand:QI 1 "gpr_operand" "d"))))] - "" - "and%F2 %0,%1,0xff" - [(set_attr "length" "8") - (set_attr "type" "long")]) - -(define_insn "*cond_exec_si_extend3_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=d") - (zero_extend:SI (match_operand:HI 1 "gpr_operand" "d"))) - (const_int 0))] - "" - "and%T2 %0,%1,0xffff" - [(set_attr "length" "8") - (set_attr "type" "long")]) - -(define_insn "*cond_exec_si_extend3_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=d") - (zero_extend:SI (match_operand:HI 1 "gpr_operand" "d"))))] - "" - "and%F2 %0,%1,0xffff" - [(set_attr "length" "8") - (set_attr "type" "long")]) - -(define_insn "*cond_exec_si_addsub_true" - [(if_then_else (match_operator 6 "condexec_test_operator" - [(match_operand:CC 7 "br_flag_operand" "b,b") - (const_int 0)]) - (parallel [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (match_operator:SI 8 "condexec_addsub_operator" - [(match_operand:SI 1 "gpr_operand" "d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i")])) - (clobber (match_operand:CC 3 "flag_operand" "")) - (clobber (match_operand:CC 4 "flag_operand" "")) - (clobber (match_operand:CC 5 "flag_operand" ""))]) - (const_int 0))] - "" - "* -{ - switch (GET_CODE (operands[8])) - { - default: - fatal_insn (\"cond_exec_si_addsub_true:\", insn); - - case PLUS: return \"add%T6 %0,%1,%2\"; - case MINUS: return \"sub%T6 %0,%1,%2\"; - } -}" - [(set_attr "length" "4,8") - (set_attr "type" "either,long")]) - -(define_insn "*cond_exec_si_addsub_false" - [(if_then_else (match_operator 6 "condexec_test_operator" - [(match_operand:CC 7 "br_flag_operand" "b,b") - (const_int 0)]) - (const_int 0) - (parallel [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (match_operator:SI 8 "condexec_addsub_operator" - [(match_operand:SI 1 "gpr_operand" "d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i")])) - (clobber (match_operand:CC 3 "flag_operand" "")) - (clobber (match_operand:CC 4 "flag_operand" "")) - (clobber (match_operand:CC 5 "flag_operand" ""))]))] - "" - "* -{ - switch (GET_CODE (operands[8])) - { - default: - fatal_insn (\"cond_exec_si_addsub_false:\", insn); - - case PLUS: return \"add%F6 %0,%1,%2\"; - case MINUS: return \"sub%F6 %0,%1,%2\"; - } -}" - [(set_attr "length" "4,8") - (set_attr "type" "either,long")]) - -(define_insn "*cond_exec_si_binary_true" - [(if_then_else (match_operator 3 "condexec_test_operator" - [(match_operand:CC 4 "br_flag_operand" "b,b") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=d,d") - (match_operator:SI 5 "condexec_binary_operator" - [(match_operand:SI 1 "gpr_operand" "d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i")])) - (const_int 0))] - "" - "* -{ - switch (GET_CODE (operands[5])) - { - default: - fatal_insn (\"cond_exec_si_binary_true:\", insn); - - case AND: return \"and%T3 %0,%1,%2\"; - case IOR: return \"or%T3 %0,%1,%2\"; - case XOR: return \"xor%T3 %0,%1,%2\"; - case ASHIFT: return \"sra%T3 %0,%1,%n2\"; - case ASHIFTRT: return \"sra%T3 %0,%1,%2\"; - case LSHIFTRT: return \"srl%T3 %0,%1,%2\"; - case ROTATE: return \"rot%T3 %0,%1,%n2\"; - case ROTATERT: return \"rot%T3 %0,%1,%2\"; - } -}" - [(set_attr "length" "4,8") - (set_attr "type" "either,long")]) - -(define_insn "*cond_exec_si_binary_false" - [(if_then_else (match_operator 3 "condexec_test_operator" - [(match_operand:CC 4 "br_flag_operand" "b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=d,d") - (match_operator:SI 5 "condexec_binary_operator" - [(match_operand:SI 1 "gpr_operand" "d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i")])))] - "" - "* -{ - switch (GET_CODE (operands[5])) - { - default: - fatal_insn (\"cond_exec_si_binary_false:\", insn); - - case AND: return \"and%F3 %0,%1,%2\"; - case IOR: return \"or%F3 %0,%1,%2\"; - case XOR: return \"xor%F3 %0,%1,%2\"; - case ASHIFT: return \"sra%F3 %0,%1,%n2\"; - case ASHIFTRT: return \"sra%F3 %0,%1,%2\"; - case LSHIFTRT: return \"srl%F3 %0,%1,%2\"; - case ROTATE: return \"rot%F3 %0,%1,%n2\"; - case ROTATERT: return \"rot%F3 %0,%1,%2\"; - } -}" - [(set_attr "length" "4,8") - (set_attr "type" "either,long")]) - -(define_insn "*cond_exec_si_shiftl_true" - [(if_then_else (match_operator 3 "condexec_test_operator" - [(match_operand:CC 4 "br_flag_operand" "b") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=d") - (match_operator:SI 5 "condexec_shiftl_operator" - [(match_operand:SI 1 "gpr_operand" "d") - (neg:SI (match_operand:SI 2 "gpr_operand" "d"))])) - (const_int 0))] - "" - "* -{ - switch (GET_CODE (operands[5])) - { - default: - fatal_insn (\"cond_exec_si_shiftl_true:\", insn); - - case ASHIFT: return \"sra%T3 %0,%1,%2\"; - case ROTATE: return \"rot%T3 %0,%1,%2\"; - } -}" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*cond_exec_si_shiftl_false" - [(if_then_else (match_operator 3 "condexec_test_operator" - [(match_operand:CC 4 "br_flag_operand" "b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=d") - (match_operator:SI 5 "condexec_shiftl_operator" - [(match_operand:SI 1 "gpr_operand" "d") - (neg:SI (match_operand:SI 2 "gpr_operand" "d"))])))] - "" - "* -{ - switch (GET_CODE (operands[5])) - { - default: - fatal_insn (\"cond_exec_si_shiftl_false:\", insn); - - case ASHIFT: return \"sra%F3 %0,%1,%2\"; - case ROTATE: return \"rot%F3 %0,%1,%2\"; - } -}" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*cond_exec_si_mul_true" - [(if_then_else (match_operator 3 "condexec_test_operator" - [(match_operand:CC 4 "br_flag_operand" "b") - (const_int 0)]) - (set (match_operand:SI 0 "gpr_operand" "=d") - (mult:SI (match_operand:SI 1 "gpr_operand" "%d") - (match_operand:SI 2 "gpr_or_signed6_operand" "dI"))) - (const_int 0))] - "" - "mul%T3 %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "iu")]) - -(define_insn "*cond_exec_si_mul_false" - [(if_then_else (match_operator 3 "condexec_test_operator" - [(match_operand:CC 4 "br_flag_operand" "b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SI 0 "gpr_operand" "=d") - (mult:SI (match_operand:SI 1 "gpr_operand" "%d") - (match_operand:SI 2 "gpr_or_signed6_operand" "dI"))))] - "" - "mul%F3 %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "iu")]) - -(define_insn "*cond_exec_sf_store_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (set (match_operand:SF 0 "memory_operand" "=Q,Q,m,m") - (match_operand:SF 1 "reg_or_0_operand" "d,G,d,G")) - (const_int 0))] - "" - "@ - stw%T2 %1,%M0 - stw%T2 %.,%M0 - stw%T2 %1,%M0 - stw%T2 %.,%M0" - [(set_attr "length" "4,4,8,8") - (set_attr "type" "mu,mu,long,long")]) - -(define_insn "*cond_exec_sf_store_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SF 0 "memory_operand" "=Q,Q,m,m") - (match_operand:SF 1 "reg_or_0_operand" "d,G,d,G")))] - "" - "@ - stw%F2 %1,%M0 - stw%F2 %.,%M0 - stw%F2 %1,%M0 - stw%F2 %.,%M0" - [(set_attr "length" "4,4,8,8") - (set_attr "type" "mu,mu,long,long")]) - -(define_insn "*cond_exec_sf_load_true" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (set (match_operand:SF 0 "gpr_operand" "=d,d,d,d") - (match_operand:SF 1 "cond_exec_operand" "d,F,Q,m")) - (const_int 0))] - "" - "@ - or%T2 %0,%.,%1 - or%T2 %0,%.,%f1 - ldw%T2 %0,%M1 - ldw%T2 %0,%M1" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,sload,lload")]) - -(define_insn "*cond_exec_sf_load_false" - [(if_then_else (match_operator 2 "condexec_test_operator" - [(match_operand:CC 3 "br_flag_operand" "b,b,b,b") - (const_int 0)]) - (const_int 0) - (set (match_operand:SF 0 "gpr_operand" "=d,d,d,d") - (match_operand:SF 1 "cond_exec_operand" "d,F,Q,m")))] - "" - "@ - or%F2 %0,%.,%1 - or%F2 %0,%.,%f1 - ldw%F2 %0,%M1 - ldw%F2 %0,%M1" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,sload,lload")]) - -(define_insn "*cond_exec_call_true" - [(if_then_else (match_operator 4 "condexec_test_operator" - [(match_operand:CC 5 "br_flag_operand" "b,b") - (const_int 0)]) - (parallel [(call (match_operand 0 "call_operand" "R,S") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (clobber (match_operand 3 "" ""))]) ;; return address, r63 - (const_int 0))] - "" - "jsr%T4 %0" - [(set_attr "length" "4,8") - (set_attr "type" "mu,long")]) - -(define_insn "*cond_exec_call_false" - [(if_then_else (match_operator 4 "condexec_test_operator" - [(match_operand:CC 5 "br_flag_operand" "b,b") - (const_int 0)]) - (const_int 0) ;; return address, r63 - (parallel [(call (match_operand 0 "call_operand" "R,S") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (clobber (match_operand 3 "" ""))]))] - "" - "jsr%F4 %0" - [(set_attr "length" "4,8") - (set_attr "type" "mu,long")]) - -(define_insn "*cond_exec_call_value_true" - [(if_then_else (match_operator 5 "condexec_test_operator" - [(match_operand:CC 6 "br_flag_operand" "b,b") - (const_int 0)]) - (parallel [(set (match_operand 0 "gpr_operand" "=d,d") - (call (match_operand 1 "call_operand" "R,S") - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (clobber (match_operand 4 "" ""))]) ;; return address, r63 - (const_int 0))] - "" - "jsr%T5 %1" - [(set_attr "length" "4,8") - (set_attr "type" "mu,long")]) - -(define_insn "*cond_exec_call_value_false" - [(if_then_else (match_operator 5 "condexec_test_operator" - [(match_operand:CC 6 "br_flag_operand" "b,b") - (const_int 0)]) - (const_int 0) ;; return address, r63 - (parallel [(set (match_operand 0 "gpr_operand" "=d,d") - (call (match_operand 1 "call_operand" "R,S") - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (clobber (match_operand 4 "" ""))]))] - "" - "jsr%F5 %1" - [(set_attr "length" "4,8") - (set_attr "type" "mu,long")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Miscellaneous instructions -;; :: -;; :::::::::::::::::::: - -;; No operation, needed in case the user uses -g but not -O. -(define_insn "nop" - [(const_int 0)] - "" - "nop || nop" - [(set_attr "length" "8") - (set_attr "type" "long")]) - -;; Pseudo instruction that prevents the scheduler from moving code above this -;; point. -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "" - [(set_attr "length" "0") - (set_attr "type" "unknown")]) - - -;; END CYGNUS LOCAL -- meissner/d30v diff --git a/gcc/config/d30v/libgcc1.asm b/gcc/config/d30v/libgcc1.asm deleted file mode 100755 index dd18248..0000000 --- a/gcc/config/d30v/libgcc1.asm +++ /dev/null @@ -1,193 +0,0 @@ -/* CYGNUS LOCAL -- meissner/d30v */ -/* Assembly support functions for libgcc1. - * - * Copyright (C) 1997 Free Software Foundation, Inc. - * Contributed by Cygnus Support - * - * This file is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * In addition to the permissions in the GNU General Public License, the - * Free Software Foundation gives you unlimited permission to link the - * compiled version of this file 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, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, 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. - */ - - -#ifdef L_udivsi3 - -/* For division, we use the following algorithm: - * - * unsigned - * __divsi3 (unsigned a, unsigned b) - * { - * unsigned al = a; - * unsigned ah = 0; - * unsigned tmpf; - * int i; - * - * for (i = 32; i > 0; i--) - * { - * ah = (ah << 1) | (al >> 31); - * tmpf = (ah >= b) ? 1 : 0; - * ah -= ((tmpf) ? b : 0); - * al = (al << 1) | tmpf; - * } - * - * return al; // for __udivsi3 - * return ah; // for __umodsi3 - * } - */ - - .file "_udivsi3" - .text - .globl __umodsi3 - .globl __udivsi3 - .type __umodsi3,@function - .type __udivsi3,@function - .stabs "libgcc1.asm",100,0,0,__umodsi3 - .stabs "int:t(0,1)=r(0,1);-2147483648;2147483647;",128,0,0,0 - .stabs "__umodsi3:F(0,1)",36,0,1,__umodsi3 - .stabs "a:P(0,1)",64,0,1,2 - .stabs "b:P(0,1)",64,0,1,3 - -__umodsi3: - bra.s .Lmerge || orfg f1,f1,1 ; indicate this is __umodsi3 -.Lumod: - .size __umodsi3,.Lumod-__umodsi3 - .stabs "",36,0,0,.Lumod-__umodsi3 - - .stabs "__udivsi3:F(0,1)",36,0,1,__udivsi3 - .stabs "a:P(0,1)",64,0,1,2 - .stabs "b:P(0,1)",64,0,1,3 -__udivsi3: - andfg f1,f1,0 || nop ; indicate this is __udivsi3 - -.Lmerge: - ; r2 = al - ; r3 = b - ; r4 = ah - ; r5 = loop counter - ; f0 = tmpf - ; f1 = 1 if this is mod, 0 if this is div - or r4,r0,0 || sub r5,r0,-32 ; ah = 0, loop = 32 - -.Lloop: - src r4,r2,-1 || sub r5,r5,1 ; ah = (ah << 1) | (al >> 31); decrement loop count - cmpuge f0,r4,r3 || sra r2,r2,-1 ; f0 = (ah >= b); al <<= 1 - sub/tx r4,r4,r3 || or/tx r2,r2,1 ; ah -= (tmpf) ? b : 0; al |= tmpf - bratnz.s r5,.Lloop || nop ; loop back if not done - jmp link || or/xt r2,r0,r4 ; if mod, update register, then return to user -.Ludiv: - .size __udivsi3,.Ludiv-__udivsi3 - .stabs "",36,0,0,.Ludiv-__udivsi3 - -#endif /* L_udivsi3 */ - - -#ifdef L_divsi3 - -/* For division, we use the following algorithm: - * - * unsigned - * __divsi3 (unsigned a, unsigned b) - * { - * unsigned al = __builtin_abs (a); - * unsigned b2 = __builtin_abs (b); - * unsigned ah = 0; - * unsigned tmpf; - * int i; - * - * for (i = 32; i > 0; i--) - * { - * ah = (ah << 1) | (al >> 31); - * tmpf = (ah >= b2) ? 1 : 0; - * ah -= ((tmpf) ? b2 : 0); - * al = (al << 1) | tmpf; - * } - * - * if (a < 0) - * ah = -ah, al = -al; - * - * if (b < 0) - * al = -al; - * - * return al; // for __divsi3 - * return ah; // for __modsi3 - * } - */ - - .file "_divsi3" - .text - .globl __modsi3 - .globl __divsi3 - .type __modsi3,@function - .type __divsi3,@function - .stabs "libgcc1.asm",100,0,0,__modsi3 - .stabs "int:t(0,1)=r(0,1);-2147483648;2147483647;",128,0,0,0 - .stabs "__modsi3:F(0,1)",36,0,1,__modsi3 - .stabs "a:P(0,1)",64,0,1,2 - .stabs "b:P(0,1)",64,0,1,3 - -__modsi3: - bra.s .Lmerge || orfg f1,f1,1 ; indicate this is __modsi3 -.Lmod: - .size __modsi3,.Lmod-__modsi3 - .stabs "",36,0,0,.Lmod-__modsi3 - - .stabs "__divsi3:F(0,1)",36,0,1,__divsi3 - .stabs "a:P(0,1)",64,0,1,2 - .stabs "b:P(0,1)",64,0,1,3 -__divsi3: - andfg f1,f1,0 || nop ; indicate this is __divsi3 - -.Lmerge: - ; r2 = al - ; r3 = b2 - ; r4 = ah - ; r5 = loop counter - ; r6 = a - ; r7 = b - ; f0 = tmpf - ; f1 = 1 if this is mod, 0 if this is div - or r6,r0,r2 || or r7,r0,r3 ; copy original inputs - abs r2,r2 || abs r3,r3 ; make both postive - or r4,r0,0 || sub r5,r0,-32 ; ah = 0, loop = 32 - -.Lloop: - src r4,r2,-1 || sub r5,r5,1 ; ah = (ah << 1) | (al >> 31); decrement loop count - cmpuge f0,r4,r3 || sra r2,r2,-1 ; f0 = (ah >= b); al <<= 1 - sub/tx r4,r4,r3 || or/tx r2,r2,1 ; ah -= (tmpf) ? b : 0; al |= tmpf - bratnz.s r5,.Lloop || nop ; loop back if not done - cmplt f0,r6,0 || nop ; f0 = (a < 0) - - sub/tx r2,r0,r2 || sub/tx r4,r0,r4 ; negate both al, ah if (a < 0) - cmplt f0,r7,0 -> sub/tx r2,r0,r2 ; negate al if (b < 0) - jmp link || or/xt r2,r0,r4 ; update result if mod; return to user -.Ldiv: - .size __divsi3,.Ldiv-__divsi3 - .stabs "",36,0,0,.Ldiv-__divsi3 - -#endif /* L_divsi3 */ -/* END CYGNUS LOCAL -- meissner/d30v */ diff --git a/gcc/config/d30v/t-d30v b/gcc/config/d30v/t-d30v deleted file mode 100755 index feeb96f..0000000 --- a/gcc/config/d30v/t-d30v +++ /dev/null @@ -1,36 +0,0 @@ -# CYGNUS LOCAL -- meissner/d30v -# Build libgcc1 from assembler sources -LIBGCC1 = libgcc1-asm.a -CROSS_LIBGCC1 = libgcc1-asm.a -LIB1ASMSRC = d30v/libgcc1.asm -LIB1ASMFUNCS = _udivsi3 _divsi3 - -# Turn on full debug for libgcc.a. -LIBGCC2_DEBUG_CFLAGS = -g - -# These are really part of libgcc1, but this will cause them to be -# built correctly, so... -LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c - -dp-bit.c: $(srcdir)/config/fp-bit.c config.status - cat $(srcdir)/config/fp-bit.c > dp-bit.c - -fp-bit.c: $(srcdir)/config/fp-bit.c config.status - echo '#define FLOAT' > fp-bit.c - echo '#define _fpadd_parts _fpadd_parts_sf' >> fp-bit.c - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - -# For svr4 we build crtbegin.o and crtend.o which serve to add begin and -# end labels to the .ctors and .dtors section when we link using gcc. - -EXTRA_PARTS=crtbegin.o crtend.o - -# We need to use -fPIC when we are using gcc to compile the routines in -# crtstuff.c. This is only really needed when we are going to use gcc/g++ -# to produce a shared library, but since we don't know ahead of time when -# we will be doing that, we just always use -fPIC when compiling the -# routines in crtstuff.c. - -# Right now, disable, since we don't support shared libraries on d30v yet. -#CRTSTUFF_T_CFLAGS = -fPIC -# END CYGNUS LOCAL --meissner/d30v diff --git a/gcc/config/d30v/xm-d30v.h b/gcc/config/d30v/xm-d30v.h deleted file mode 100755 index 905d843..0000000 --- a/gcc/config/d30v/xm-d30v.h +++ /dev/null @@ -1,199 +0,0 @@ -/* CYGNUS LOCAL -- meissner/d30v */ -/* Definitions of target machine for use as an example. - Hack to fit. - Copyright (C) 1997 Free Software Foundation, Inc. - Contributed by Cygnus Solutions. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* Define this macro if the host system is System V. */ -/* #define USG */ - -/* Define this macro if the host system is VMS. */ -/* #define VMS */ - -/* A C expression for the status code to be returned when the compiler exits - after serious errors. */ -#define FATAL_EXIT_CODE 33 - -/* A C expression for the status code to be returned when the compiler exits - without serious errors. */ -#define SUCCESS_EXIT_CODE 0 - -/* Defined if the host machine stores words of multi-word values in big-endian - order. (GNU CC does not depend on the host byte ordering within a word.) */ -#define HOST_WORDS_BIG_ENDIAN - -/* Define this macro to be 1 if the host machine stores `DFmode', `XFmode' or - `TFmode' floating point numbers in memory with the word containing the sign - bit at the lowest address; otherwise, define it to be zero. - - This macro need not be defined if the ordering is the same as for multi-word - integers. */ -/* #define HOST_FLOAT_WORDS_BIG_ENDIAN */ - -/* A numeric code distinguishing the floating point format for the host - machine. See `TARGET_FLOAT_FORMAT' in *Note Storage Layout:: for the - alternatives and default. */ -/* #define HOST_FLOAT_FORMAT */ - -/* A C expression for the number of bits in `char' on the host machine. */ -#define HOST_BITS_PER_CHAR 8 - -/* A C expression for the number of bits in `short' on the host machine. */ -#define HOST_BITS_PER_SHORT 16 - -/* A C expression for the number of bits in `int' on the host machine. */ -#define HOST_BITS_PER_INT 32 - -/* A C expression for the number of bits in `long' on the host machine. */ -#define HOST_BITS_PER_LONG 32 - -/* Define this macro to indicate that the host compiler only supports `int' bit - fields, rather than other integral types, including `enum', as do most C - compilers. */ -/* #define ONLY_INT_FIELDS */ - -/* A C expression for the size of ordinary obstack chunks. If you don't define - this, a usually-reasonable default is used. */ -/* #define OBSTACK_CHUNK_SIZE */ - -/* The function used to allocate obstack chunks. If you don't define this, - `xmalloc' is used. */ -/* #define OBSTACK_CHUNK_ALLOC */ - -/* The function used to free obstack chunks. If you don't define this, `free' - is used. */ -/* #define OBSTACK_CHUNK_FREE */ - -/* Define this macro to indicate that the compiler is running with the `alloca' - implemented in C. This version of `alloca' can be found in the file - `alloca.c'; to use it, you must also alter the `Makefile' variable `ALLOCA'. - (This is done automatically for the systems on which we know it is needed.) - - If you do define this macro, you should probably do it as follows: - - #ifndef __GNUC__ - #define USE_C_ALLOCA - #else - #define alloca __builtin_alloca - #endif - - so that when the compiler is compiled with GNU CC it uses the more efficient - built-in `alloca' function. */ - -#ifndef __GNUC__ -#define USE_C_ALLOCA -#else -#define alloca __builtin_alloca -#endif - -/* Define this macro to indicate that the host compiler does not properly - handle converting a function value to a pointer-to-function when it is used - in an expression. */ -/* #define FUNCTION_CONVERSION_BUG */ - -/* Define this if the library function `vprintf' is available on your system. */ -/* #define HAVE_VPRINTF */ - -/* Define this macro to enable support for multibyte characters in the input to - GNU CC. This requires that the host system support the ANSI C library - functions for converting multibyte characters to wide characters. */ -/* #define MULTIBYTE_CHARS */ - -/* Define this if the library function `putenv' is available on your system. */ -/* #define HAVE_PUTENV */ - -/* Define this if your system is POSIX.1 compliant. */ -/* #define POSIX */ - -/* Define this if your system *does not* provide the variable `sys_siglist'. */ -/* #define NO_SYS_SIGLIST */ - -/* Define this if your system has the variable `sys_siglist', and there is - already a declaration of it in the system header files. */ -/* #define DONT_DECLARE_SYS_SIGLIST */ - -/* Define this to be 1 if you know that the host compiler supports prototypes, - even if it doesn't define __STDC__, or define it to be 0 if you do not want - any prototypes used in compiling GNU CC. If `USE_PROTOTYPES' is not - defined, it will be determined automatically whether your compiler supports - prototypes by checking if `__STDC__' is defined. */ -/* #define USE_PROTOTYPES */ - -/* Define this if you wish suppression of prototypes generated from the machine - description file, but to use other prototypes within GNU CC. If - `USE_PROTOTYPES' is defined to be 0, or the host compiler does not support - prototypes, this macro has no effect. */ -/* #define NO_MD_PROTOTYPES */ - -/* Define this if you wish to generate prototypes for the `gen_call' or - `gen_call_value' functions generated from the machine description file. If - `USE_PROTOTYPES' is defined to be 0, or the host compiler does not support - prototypes, or `NO_MD_PROTOTYPES' is defined, this macro has no effect. As - soon as all of the machine descriptions are modified to have the appropriate - number of arguments, this macro will be removed. - - Some systems do provide this variable, but with a different name such as - `_sys_siglist'. On these systems, you can define `sys_siglist' as a macro - which expands into the name actually provided. */ -/* #define MD_CALL_PROTOTYPES */ - -/* Define this macro to be a C character constant representing the character - used to separate components in paths. The default value is. the colon - character */ -/* #define PATH_SEPARATOR */ - -/* If your system uses some character other than slash to separate directory - names within a file specification, define this macro to be a C character - constant specifying that character. When GNU CC displays file names, the - character you specify will be used. GNU CC will test for both slash and the - character you specify when parsing filenames. */ -/* #define DIR_SEPARATOR */ - -/* Define this macro to be a C string representing the suffix for object files - on your machine. If you do not define this macro, GNU CC will use `.o' as - the suffix for object files. */ -/* #define OBJECT_SUFFIX */ - -/* Define this macro to be a C string representing the suffix for executable - files on your machine. If you do not define this macro, GNU CC will use the - null string as the suffix for object files. */ -/* #define EXECUTABLE_SUFFIX */ - -/* If defined, `collect2' will scan the individual object files specified on - its command line and create an export list for the linker. Define this - macro for systems like AIX, where the linker discards object files that are - not referenced from `main' and uses export lists. */ -/* #define COLLECT_EXPORT_LIST */ - -/* In addition, configuration files for system V define `bcopy', `bzero' and - `bcmp' as aliases. Some files define `alloca' as a macro when compiled with - GNU CC, in order to take advantage of the benefit of GNU CC's built-in - `alloca'. */ - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* end of xm-generic.h */ -/* END CYGNUS LOCAL -- meissner/d30v */ diff --git a/gcc/config/dbx.h b/gcc/config/dbx.h deleted file mode 100755 index c5cd3b5..0000000 --- a/gcc/config/dbx.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Prefer DBX (stabs) debugging information. - Copyright (C) 1996 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* This file causes gcc to prefer using DBX (stabs) debugging - information. The configure script will add a #include of this file - to tm.h when --with-stabs is used for certain targets. */ - -#ifndef DBX_DEBUGGING_INFO -#define DBX_DEBUGGING_INFO -#endif - -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG diff --git a/gcc/config/dbxcoff.h b/gcc/config/dbxcoff.h deleted file mode 100755 index 9497a70..0000000 --- a/gcc/config/dbxcoff.h +++ /dev/null @@ -1,87 +0,0 @@ -/* Definitions needed when using stabs embedded in COFF sections. - Copyright (C) 1996 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* This file may be included by any COFF target which wishes to - support -gstabs generating stabs in sections, as produced by gas - and understood by gdb. */ - -/* Output DBX (stabs) debugging information if doing -gstabs. */ - -#undef DBX_DEBUGGING_INFO -#define DBX_DEBUGGING_INFO - -/* Generate SDB debugging information by default. */ - -#ifndef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG -#endif - -/* 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) \ - fprintf (FILE, \ - "\t.text\n\t.stabs \"\",%d,0,0,Letext\nLetext:\n", N_SO) - -/* Like block addresses, stabs line numbers are relative to the - current function. */ - -#undef ASM_OUTPUT_SOURCE_LINE -#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \ -{ 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) { \ - static int sym_lineno = 1; \ - char buffer[256]; \ - ASM_GENERATE_INTERNAL_LABEL (buffer, "LM", sym_lineno); \ - 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); \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, "LM", sym_lineno); \ - sym_lineno++; \ - } } - -/* 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. */ - -#ifndef DBX_CONTIN_LENGTH -#define DBX_CONTIN_LENGTH 0 -#endif diff --git a/gcc/config/dsp16xx/dsp16xx.c b/gcc/config/dsp16xx/dsp16xx.c deleted file mode 100755 index e7bcdce..0000000 --- a/gcc/config/dsp16xx/dsp16xx.c +++ /dev/null @@ -1,2241 +0,0 @@ -/* Subroutines for assembler code output on the DSP1610. - Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. - Contributed by Michael Collison (collison@world.std.com). - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Some output-actions in dsp1600.md need these. */ -#include "config.h" -#include -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "tree.h" -#include "expr.h" -#include "flags.h" - -char *text_seg_name; -char *rsect_text; -char *data_seg_name; -char *rsect_data; -char *bss_seg_name; -char *rsect_bss; -char *const_seg_name; -char *rsect_const; - -char *chip_name; -char *save_chip_name; - -/* Save the operands of a compare. The 16xx has not lt or gt, so - in these cases we swap the operands and reverse the condition */ - -rtx dsp16xx_compare_op0; -rtx dsp16xx_compare_op1; -struct rtx_def *(*dsp16xx_compare_gen)(); - -static char *fp; -static char *sp; -static char *rr; -static char *a1h; - -struct dsp16xx_frame_info current_frame_info; -struct dsp16xx_frame_info zero_frame_info; - -rtx dsp16xx_addhf3_libcall = (rtx) 0; -rtx dsp16xx_subhf3_libcall = (rtx) 0; -rtx dsp16xx_mulhf3_libcall = (rtx) 0; -rtx dsp16xx_divhf3_libcall = (rtx) 0; -rtx dsp16xx_cmphf3_libcall = (rtx) 0; -rtx dsp16xx_fixhfhi2_libcall = (rtx) 0; -rtx dsp16xx_floathihf2_libcall = (rtx) 0; -rtx dsp16xx_neghf2_libcall = (rtx) 0; - -rtx dsp16xx_mulhi3_libcall = (rtx) 0; -rtx dsp16xx_udivqi3_libcall = (rtx) 0; -rtx dsp16xx_udivhi3_libcall = (rtx) 0; -rtx dsp16xx_divqi3_libcall = (rtx) 0; -rtx dsp16xx_divhi3_libcall = (rtx) 0; -rtx dsp16xx_modqi3_libcall = (rtx) 0; -rtx dsp16xx_modhi3_libcall = (rtx) 0; -rtx dsp16xx_umodqi3_libcall = (rtx) 0; -rtx dsp16xx_umodhi3_libcall = (rtx) 0; -rtx dsp16xx_ashrhi3_libcall = (rtx) 0; -rtx dsp16xx_ashlhi3_libcall = (rtx) 0; -rtx dsp16xx_ucmphi2_libcall = (rtx) 0; -rtx dsp16xx_lshrhi3_libcall = (rtx) 0; - -char *himode_reg_name[] = HIMODE_REGISTER_NAMES; - -#define SHIFT_INDEX_1 0 -#define SHIFT_INDEX_4 1 -#define SHIFT_INDEX_8 2 -#define SHIFT_INDEX_16 3 - -static char *ashift_right_asm[] = -{ - "%0=%0>>1", - "%0=%0>>4", - "%0=%0>>8", - "%0=%0>>16" -}; - -static char *ashift_right_asm_first[] = -{ - "%0=%1>>1", - "%0=%1>>4", - "%0=%1>>8", - "%0=%1>>16" -}; - -static char *ashift_left_asm[] = -{ - "%0=%0<<1", - "%0=%0<<4", - "%0=%0<<8", - "%0=%0<<16" -}; - -static char *ashift_left_asm_first[] = -{ - "%0=%1<<1", - "%0=%1<<4", - "%0=%1<<8", - "%0=%1<<16" -}; - -static char *lshift_right_asm[] = -{ - "%0=%0>>1\n\t%0=%b0&0x7fff", - "%0=%0>>4\n\t%0=%b0&0x0fff", - "%0=%0>>8\n\t%0=%b0&0x00ff", - "%0=%0>>16\n\t%0=%b0&0x0000" -}; - -static char *lshift_right_asm_first[] = -{ - "%0=%1>>1\n\t%0=%b0&0x7fff", - "%0=%1>>4\n\t%0=%b0&0x0fff", - "%0=%1>>8\n\t%0=%b0&0x00ff", - "%0=%1>>16\n\t%0=%b0&0x0000" -}; - -int -hard_regno_mode_ok (regno, mode) -int regno; -enum machine_mode mode; -{ - switch ((int) mode) - { - case VOIDmode: - return 1; - - /* - We can't use the c0-c2 for QImode, since they are only - 8 bits in length */ - - case QImode: - if (regno != REG_C0 && regno != REG_C1 && regno != REG_C2) - return 1; - else - return 0; - - /* We only allow a0, a1, y, and p to be allocated for 32-bit modes. - Additionally we allow the virtual ybase registers to be used for 32-bit - modes. */ - - case HFmode: - case SFmode: - case DFmode: - case XFmode: - case HImode: - case SImode: - case DImode: - if (regno == REG_A0 || regno == REG_A1 || regno == REG_Y || regno == REG_PROD - || (IS_YBASE_REGISTER_WINDOW(regno) && ((regno & 1) == 0))) - return 1; - else - return 0; - - default: - return 0; - } -} - -enum reg_class -dsp16xx_reg_class_from_letter (c) -int c; -{ - switch (c) - { - case 'A': - return ACCUM_REGS; - - case 'h': - return ACCUM_HIGH_REGS; - - case 'j': - return A0H_REG; - - case 'k': - return A0L_REG; - - case 'q': - return A1H_REG; - - case 'u': - return A1L_REG; - - case 'x': - return X_REG; - - case 'y': - return YH_REG; - - case 'z': - return YL_REG; - - case 't': - return P_REG; - - case 'Z': - return Y_OR_P_REGS; - - case 'd': - return ACCUM_Y_OR_P_REGS; - - case 'C': - return NO_FRAME_Y_ADDR_REGS; - - case 'a': - return Y_ADDR_REGS; - - case 'B': - return (TARGET_BMU ? BMU_REGS : NO_REGS); - - case 'Y': - return YBASE_VIRT_REGS; - - case 'v': - return PH_REG; - - case 'w': - return PL_REG; - - case 'W': - return J_REG; - - case 'e': - return YBASE_ELIGIBLE_REGS; - - case 'b': - return ACCUM_LOW_REGS; - - case 'c': - return NON_YBASE_REGS; - - case 'f': - return Y_REG; - - case 'D': - return SLOW_MEM_LOAD_REGS; - - default: - fatal ("Invalid register class letter %c", c); - return NO_REGS; - } -} -/* Return the class number of the smallest class containing - reg number REGNO. */ - -int -regno_reg_class(regno) -int regno; -{ - switch (regno) - { - case REG_A0L: - return (int) A0L_REG; - case REG_A1L: - return (int) A1L_REG; - - case REG_A0: - return (int) A0H_REG; - case REG_A1: - return (int) A1H_REG; - - case REG_X: - return (int) X_REG; - - case REG_Y: - return (int) YH_REG; - case REG_YL: - return (int) YL_REG; - - case REG_PROD: - return (int) PH_REG; - case REG_PRODL: - return (int) PL_REG; - - case REG_R0: case REG_R1: case REG_R2: case REG_R3: - return (int) Y_ADDR_REGS; - - case REG_J: - return (int) J_REG; - case REG_K: - return (int) GENERAL_REGS; - - case REG_YBASE: - return (int) GENERAL_REGS; - - case REG_PT: - return (int) GENERAL_REGS; - - case REG_AR0: case REG_AR1: case REG_AR2: case REG_AR3: - return (int) BMU_REGS; - - case REG_C0: case REG_C1: case REG_C2: - return (int) GENERAL_REGS; - - case REG_PR: - return (int) GENERAL_REGS; - - case REG_RB: - return (int) GENERAL_REGS; - - case REG_YBASE0: case REG_YBASE1: case REG_YBASE2: case REG_YBASE3: - case REG_YBASE4: case REG_YBASE5: case REG_YBASE6: case REG_YBASE7: - case REG_YBASE8: case REG_YBASE9: case REG_YBASE10: case REG_YBASE11: - case REG_YBASE12: case REG_YBASE13: case REG_YBASE14: case REG_YBASE15: - case REG_YBASE16: case REG_YBASE17: case REG_YBASE18: case REG_YBASE19: - case REG_YBASE20: case REG_YBASE21: case REG_YBASE22: case REG_YBASE23: - case REG_YBASE24: case REG_YBASE25: case REG_YBASE26: case REG_YBASE27: - case REG_YBASE28: case REG_YBASE29: case REG_YBASE30: case REG_YBASE31: - return (int) YBASE_VIRT_REGS; - - default: - return (int) NO_REGS; - } -} - -/* A C expression for the maximum number of consecutive registers of class CLASS - needed to hold a value of mode MODE */ - -int -class_max_nregs(class, mode) -enum reg_class class; -enum machine_mode mode; -{ - return (GET_MODE_SIZE(mode)); -} - -enum reg_class -limit_reload_class (mode, class) -enum machine_mode mode; -enum reg_class class; -{ - switch ((int) class) - { - case NO_REGS: - case A0H_REG: - case A0L_REG: - case A0_REG: - case A1H_REG: - return class; - - case ACCUM_HIGH_REGS: - fatal ("ACCUM_HIGH_REGS class in limit_reload_class"); - - case A1L_REG: - case ACCUM_LOW_REGS: - case A1_REG: - return class; - - case ACCUM_REGS: - if (GET_MODE_SIZE(mode) == 1) - return ACCUM_LOW_REGS; - else - return class; - - case X_REG: - case X_OR_ACCUM_LOW_REGS: - return class; - - case X_OR_ACCUM_REGS: - if (GET_MODE_SIZE(mode) == 1) - return X_OR_ACCUM_LOW_REGS; - else - return class; - - case YH_REG: - return class; - - case YH_OR_ACCUM_HIGH_REGS: - fatal ("YH_OR_ACCUM_HIGH_REGS found in limit_reload_class"); - - case X_OR_YH_REGS: - return class; - - case YL_REG: - /* Register 'yl' is invalid for QImode, so we should never - see it. */ - - fatal ("YL found in limit_reload_class"); - - case YL_OR_ACCUM_LOW_REGS: - case X_OR_YL_REGS: - return class; - - case Y_REG: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return YH_REG; - - case ACCUM_OR_Y_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return YL_OR_ACCUM_LOW_REGS; - - case PH_REG: - case X_OR_PH_REGS: - case PL_REG: - case PL_OR_ACCUM_LOW_REGS: - case X_OR_PL_REGS: - return class; - - case P_REG: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return PL_REG; - - case ACCUM_OR_P_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return PL_OR_ACCUM_LOW_REGS; - - case YL_OR_P_REGS: - case ACCUM_LOW_OR_YL_OR_P_REGS: - return class; - - case Y_OR_P_REGS: - return class; - - case ACCUM_Y_OR_P_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return ACCUM_LOW_OR_YL_OR_P_REGS; - - case NO_FRAME_Y_ADDR_REGS: - case Y_ADDR_REGS: - case ACCUM_LOW_OR_Y_ADDR_REGS: - return class; - - case ACCUM_OR_Y_ADDR_REGS: - if (GET_MODE_SIZE(mode) > 1) - return ACCUM_REGS; - else - return ACCUM_LOW_OR_Y_ADDR_REGS; - - case X_OR_Y_ADDR_REGS: - return class; - - case Y_OR_Y_ADDR_REGS: - case P_OR_Y_ADDR_REGS: - case NON_HIGH_YBASE_ELIGIBLE_REGS: - - case J_REG: - return class; - - case YBASE_ELIGIBLE_REGS: - if (GET_MODE_SIZE(mode) > 1) - return ACCUM_Y_P_OR_YBASE_REGS; - else - return NON_HIGH_YBASE_ELIGIBLE_REGS; - - case J_OR_DAU_16_BIT_REGS: - if (GET_MODE_SIZE(mode) == 1) - return J_REG; - else - return class; - - case BMU_REGS: - case NOHIGH_NON_ADDR_REGS: - return class; - - case NON_ADDR_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return NOHIGH_NON_ADDR_REGS; - - case NOHIGH_NON_YBASE_REGS: - return class; - - case NON_YBASE_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return NOHIGH_NON_YBASE_REGS; - - case YBASE_VIRT_REGS: - case ACCUM_LOW_OR_YBASE_REGS: - return class; - - case ACCUM_OR_YBASE_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return ACCUM_LOW_OR_YBASE_REGS; - - case X_OR_YBASE_REGS: - return class; - - case Y_OR_YBASE_REGS: - case ACCUM_LOW_YL_PL_OR_YBASE_REGS: - case P_OR_YBASE_REGS: - return class; - - case ACCUM_Y_P_OR_YBASE_REGS: - return ACCUM_LOW_YL_PL_OR_YBASE_REGS; - - case Y_ADDR_OR_YBASE_REGS: - case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS: - return class; - - case YBASE_OR_YBASE_ELIGIBLE_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS; - - case NO_HIGH_ALL_REGS: - return class; - - case ALL_REGS: - if (GET_MODE_SIZE(mode) > 1) - return class; - else - return NO_HIGH_ALL_REGS; - - default: - return class; - } -} - -int -dsp16xx_register_move_cost (from, to) -enum reg_class from, to; -{ -#if 0 - if (from == NO_REGS || to == NO_REGS || (from == to)) - return 2; -#endif - - if (from == A0H_REG || from == A0L_REG || from == A0_REG || - from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG || - from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS) - { - if (to == Y_REG || to == P_REG) - return 4; - else - return 2; - } - - if (to == A0H_REG || to == A0L_REG || to == A0_REG || - to == A1H_REG || to == ACCUM_HIGH_REGS || to == A1L_REG || - to == ACCUM_LOW_REGS || to == A1_REG || to == ACCUM_REGS) - { - return 2; - } - -#if 0 - if (from == YBASE_VIRT_REGS) - { - if (to == X_REG || to == YH_REG || to == YL_REG || - to == Y_REG || to == PL_REG || to == PH_REG || - to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS || - to == Y_OR_P_REGS) - { - return 2; - } - else - return 4; - } - - if (to == YBASE_VIRT_REGS) - { - if (from == X_REG || from == YH_REG || from == YL_REG || - from == Y_REG || from == PL_REG || from == PH_REG || - from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS || - from == Y_OR_P_REGS) - { - return 2; - } - else - return 4; - } -#endif - return 4; -} - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. - Also, we must ensure that a PLUS is reloaded either - into an accumulator or an address register. */ - -enum reg_class -preferred_reload_class (x, class) - rtx x; - enum reg_class class; -{ - /* The ybase registers cannot have constants copied directly - to them. */ - - if (CONSTANT_P (x)) - { - if (class == ALL_REGS) - return NON_YBASE_REGS; - } - - if (class == ALL_REGS && REG_P (x) && !TARGET_RESERVE_YBASE - && IS_YBASE_REGISTER_WINDOW (REGNO(x))) - return YBASE_ELIGIBLE_REGS; - - if (GET_CODE (x) == PLUS) - { - if (GET_MODE (x) == QImode - && REG_P (XEXP (x,0)) - && (XEXP (x,0) == frame_pointer_rtx - || XEXP (x,0) == stack_pointer_rtx) - && (GET_CODE (XEXP (x,1)) == CONST_INT)) - { - if (class == ACCUM_HIGH_REGS) - return class; - - if (reg_class_subset_p (ACCUM_HIGH_REGS, class)) - return ACCUM_HIGH_REGS; - - /* We will use accumulator 'a1l' for reloading a - PLUS. We can only use one accumulator because - 'reload_inqi' only allows one alternative to be - used. */ - - else if (class == ACCUM_LOW_REGS) - return A1L_REG; - else if (class == A0L_REG) - return NO_REGS; - else - return class; - } - - if (class == NON_YBASE_REGS || class == YBASE_ELIGIBLE_REGS) - return Y_ADDR_REGS; - else - return class; - } - else if (GET_CODE (x) == MEM) - { - if (class == ALL_REGS) - { -#if 0 - if (GET_MODE(x) == HImode) - return NO_ACCUM_NON_YBASE_REGS; - else -#endif - return NON_YBASE_REGS; - } - else - return class; - } - else - return class; -} - -/* Return the register class of a scratch register needed to copy IN into - or out of a register in CLASS in MODE. If it can be done directly, - NO_REGS is returned. */ - -enum reg_class -secondary_reload_class (class, mode, in) - enum reg_class class; - enum machine_mode mode; - rtx in; -{ - int regno = -1; - - if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) - regno = true_regnum (in); - - if (class == ACCUM_HIGH_REGS - || class == ACCUM_LOW_REGS - || class == A1L_REG - || class == A0L_REG - || class == A1H_REG - || class == A0H_REG) - { - if (GET_CODE (in) == PLUS && mode == QImode) - { - rtx addr0 = XEXP (in, 0); - rtx addr1 = XEXP (in, 1); - - /* If we are reloading a plus (reg:QI) (reg:QI) - we need an additional register. */ - if (REG_P (addr0) && REG_P (addr1)) - return NO_REGS; - } - } - - /* We can place anything into ACCUM_REGS and can put ACCUM_REGS - into anything. */ - - if ((class == ACCUM_REGS || class == ACCUM_HIGH_REGS || - class == ACCUM_LOW_REGS || class == A0H_REG || class == A0L_REG || - class == A1H_REG || class == A1_REG) || - (regno >= REG_A0 && regno < REG_A1L + 1)) - return NO_REGS; - - /* We can copy the ybase registers into: - r0-r3, a0-a1, y, p, & x or the union of - any of these. */ - - if (!TARGET_RESERVE_YBASE && IS_YBASE_REGISTER_WINDOW(regno)) - { - switch ((int) class) - { - case (int) X_REG: - case (int) X_OR_ACCUM_LOW_REGS: - case (int) X_OR_ACCUM_REGS: - case (int) YH_REG: - case (int) YH_OR_ACCUM_HIGH_REGS: - case (int) X_OR_YH_REGS: - case (int) YL_REG: - case (int) YL_OR_ACCUM_LOW_REGS: - case (int) X_OR_Y_REGS: - case (int) X_OR_YL_REGS: - case (int) Y_REG: - case (int) ACCUM_OR_Y_REGS: - case (int) PH_REG: - case (int) X_OR_PH_REGS: - case (int) PL_REG: - case (int) PL_OR_ACCUM_LOW_REGS: - case (int) X_OR_PL_REGS: - case (int) YL_OR_PL_OR_ACCUM_LOW_REGS: - case (int) P_REG: - case (int) ACCUM_OR_P_REGS: - case (int) YL_OR_P_REGS: - case (int) ACCUM_LOW_OR_YL_OR_P_REGS: - case (int) Y_OR_P_REGS: - case (int) ACCUM_Y_OR_P_REGS: - case (int) Y_ADDR_REGS: - case (int) ACCUM_LOW_OR_Y_ADDR_REGS: - case (int) ACCUM_OR_Y_ADDR_REGS: - case (int) X_OR_Y_ADDR_REGS: - case (int) Y_OR_Y_ADDR_REGS: - case (int) P_OR_Y_ADDR_REGS: - case (int) YBASE_ELIGIBLE_REGS: - return NO_REGS; - - default: - return ACCUM_HIGH_REGS; - } - } - - /* We can copy r0-r3, a0-a1, y, & p - directly to the ybase registers. In addition - we can use any of the ybase virtual registers - as the secondary reload registers when copying - between any of these registers. */ - - if (!TARGET_RESERVE_YBASE && regno != -1) - { - switch (regno) - { - case REG_A0: - case REG_A0L: - case REG_A1: - case REG_A1L: - case REG_X: - case REG_Y: - case REG_YL: - case REG_PROD: - case REG_PRODL: - case REG_R0: - case REG_R1: - case REG_R2: - case REG_R3: - if (class == YBASE_VIRT_REGS) - return NO_REGS; - else - { - switch ((int) class) - { - case (int) X_REG: - case (int) X_OR_ACCUM_LOW_REGS: - case (int) X_OR_ACCUM_REGS: - case (int) YH_REG: - case (int) YH_OR_ACCUM_HIGH_REGS: - case (int) X_OR_YH_REGS: - case (int) YL_REG: - case (int) YL_OR_ACCUM_LOW_REGS: - case (int) X_OR_Y_REGS: - case (int) X_OR_YL_REGS: - case (int) Y_REG: - case (int) ACCUM_OR_Y_REGS: - case (int) PH_REG: - case (int) X_OR_PH_REGS: - case (int) PL_REG: - case (int) PL_OR_ACCUM_LOW_REGS: - case (int) X_OR_PL_REGS: - case (int) YL_OR_PL_OR_ACCUM_LOW_REGS: - case (int) P_REG: - case (int) ACCUM_OR_P_REGS: - case (int) YL_OR_P_REGS: - case (int) ACCUM_LOW_OR_YL_OR_P_REGS: - case (int) Y_OR_P_REGS: - case (int) ACCUM_Y_OR_P_REGS: - case (int) Y_ADDR_REGS: - case (int) ACCUM_LOW_OR_Y_ADDR_REGS: - case (int) ACCUM_OR_Y_ADDR_REGS: - case (int) X_OR_Y_ADDR_REGS: - case (int) Y_OR_Y_ADDR_REGS: - case (int) P_OR_Y_ADDR_REGS: - case (int) YBASE_ELIGIBLE_REGS: - return YBASE_VIRT_REGS; - - default: - break; - } - } - } - } - - /* Memory or constants can be moved from or to any register - except the ybase virtual registers */ - if (regno == -1 && GET_CODE(in) != PLUS) - { - if (class == YBASE_VIRT_REGS) - return NON_YBASE_REGS; - else - return NO_REGS; - } - - if (GET_CODE (in) == PLUS && mode == QImode) - { - rtx addr0 = XEXP (in, 0); - rtx addr1 = XEXP (in, 1); - - /* If we are reloading a plus (reg:QI) (reg:QI) - we need a low accumulator, not a high one. */ - if (REG_P (addr0) && REG_P (addr1)) - return ACCUM_LOW_REGS; - } - -#if 0 - if (REG_P(in)) - return ACCUM_REGS; -#endif - - /* Otherwise, we need a high accumulator(s). */ - return ACCUM_HIGH_REGS; -} - -int -symbolic_address_operand (op, mode) -rtx op; -enum machine_mode mode; -{ - return (symbolic_address_p (op)); - -} - -int symbolic_address_p (op) -rtx op; -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF: - case LABEL_REF: - return 1; - - case CONST: - op = XEXP (op, 0); - return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF - || GET_CODE (XEXP (op, 0)) == LABEL_REF) - && GET_CODE (XEXP (op, 1)) == CONST_INT - && INTVAL (XEXP (op,1)) < 0x20); - - default: - return 0; - } -} - -/* For a Y address space operand we allow only *rn, *rn++, *rn--. - This routine only recognizes *rn, the '<>' constraints recognize - *rn++, *rn-- */ - -int -Y_address_operand (op, mode) -rtx op; -enum machine_mode mode; -{ - return (memory_address_p (mode, op) && !symbolic_address_p (op)); -} - -int -sp_operand (op, mode) -rtx op; -enum machine_mode mode; -{ - return (GET_CODE (op) == PLUS - && (XEXP (op, 0) == stack_pointer_rtx - || XEXP (op, 0) == frame_pointer_rtx) - && GET_CODE (XEXP (op,1)) == CONST_INT); -} - -int -sp_operand2 (op, mode) -rtx op; -enum machine_mode mode; -{ - if ((GET_CODE (op) == PLUS - && (XEXP (op, 0) == stack_pointer_rtx - || XEXP (op, 0) == frame_pointer_rtx) - && (REG_P (XEXP (op,1)) - && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1)))))) - return 1; - else if ((GET_CODE (op) == PLUS - && (XEXP (op, 1) == stack_pointer_rtx - || XEXP (op, 1) == frame_pointer_rtx) - && (REG_P (XEXP (op,0)) - && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1)))))) - return 1; - else - return 0; -} - -int -nonmemory_arith_operand (op, mode) -rtx op; -enum machine_mode mode; -{ - return (immediate_operand (op, mode) || arith_reg_operand (op, mode)); -} - -int -arith_reg_operand (op, mode) -rtx op; -enum machine_mode mode; -{ - return (register_operand (op, mode) - && (GET_CODE (op) != REG - || REGNO (op) >= FIRST_PSEUDO_REGISTER - || (!(IS_YBASE_REGISTER_WINDOW (REGNO (op))) - && REGNO (op) != FRAME_POINTER_REGNUM))); -} - -int -call_address_operand (op, mode) -rtx op; -enum machine_mode mode; -{ - if (symbolic_address_p (op) || REG_P(op)) - { - return 1; - } - - return 0; -} - -int -dsp16xx_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode; -{ - return ((mode == VOIDmode || GET_MODE (op) == mode) - && GET_RTX_CLASS (GET_CODE (op)) == '<' - && (GET_CODE(op) != GE && GET_CODE (op) != LT && - GET_CODE (op) != GEU && GET_CODE (op) != LTU)); -} - -void -notice_update_cc(exp) -rtx exp; -{ - if (GET_CODE (exp) == SET) - { - /* Jumps do not alter the cc's. */ - - if (SET_DEST (exp) == pc_rtx) - return; - - /* Moving register or memory into a register: - it doesn't alter the cc's, but it might invalidate - the RTX's which we remember the cc's came from. - (Note that moving a constant 0 or 1 MAY set the cc's). */ - if (REG_P (SET_DEST (exp)) - && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM)) - { - if (cc_status.value1 - && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) - cc_status.value1 = 0; - if (cc_status.value2 - && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) - cc_status.value2 = 0; - return; - } - /* Moving register into memory doesn't alter the cc's. - It may invalidate the RTX's which we remember the cc's came from. */ - if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp))) - { - if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM) - cc_status.value1 = 0; - if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM) - cc_status.value2 = 0; - return; - } - /* Function calls clobber the cc's. */ - else if (GET_CODE (SET_SRC (exp)) == CALL) - { - CC_STATUS_INIT; - return; - } - /* Tests and compares set the cc's in predictable ways. */ - else if (SET_DEST (exp) == cc0_rtx) - { - CC_STATUS_INIT; - cc_status.value1 = SET_SRC (exp); - return; - } - /* Certain instructions effect the condition codes. */ - else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp))) == MODE_INT) - switch( GET_CODE (SET_SRC (exp)) ) - { - case PLUS: - case MINUS: - if (REG_P (SET_DEST (exp))) - { - /* Address registers don't set the condition codes */ - if (IS_ADDRESS_REGISTER (REGNO (SET_DEST (exp)))) - { - CC_STATUS_INIT; - break; - } - } - case ASHIFTRT: - case LSHIFTRT: - case ASHIFT: - case AND: - case IOR: - case XOR: - case MULT: - case NEG: - case NOT: - cc_status.value1 = SET_SRC (exp); - cc_status.value2 = SET_DEST (exp); - break; - - default: - CC_STATUS_INIT; - } - else - { - CC_STATUS_INIT; - } - } - else if (GET_CODE (exp) == PARALLEL - && GET_CODE (XVECEXP (exp, 0, 0)) == SET) - { - if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) - return; - - if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) - { - CC_STATUS_INIT; - cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); - return; - } - - CC_STATUS_INIT; - } - else - { - CC_STATUS_INIT; - } -} - -int -dsp16xx_makes_calls () -{ - rtx insn; - - for (insn = get_insns (); insn; insn = next_insn (insn)) - if (GET_CODE (insn) == CALL_INSN) - return (1); - - return 0; -} - -long compute_frame_size (size) -int size; -{ - long total_size; - long var_size; - long args_size; - long extra_size; - long reg_size; - - reg_size = 0; - extra_size = 0; - var_size = size; - args_size = current_function_outgoing_args_size; - reg_size = reg_save_size (); - - total_size = var_size + args_size + extra_size + reg_size; - - - /* Save other computed information. */ - current_frame_info.total_size = total_size; - current_frame_info.var_size = var_size; - current_frame_info.args_size = args_size; - current_frame_info.extra_size = extra_size; - current_frame_info.reg_size = reg_size; - current_frame_info.initialized = reload_completed; - current_frame_info.reg_size = reg_size / UNITS_PER_WORD; - current_frame_info.function_makes_calls = dsp16xx_makes_calls (); - - if (reg_size) - { - unsigned long offset = args_size + var_size + reg_size; - current_frame_info.sp_save_offset = offset; - current_frame_info.fp_save_offset = offset - total_size; - } - - return total_size; -} - -int -dsp16xx_call_saved_register (regno) -int regno; -{ - return (regs_ever_live[regno] && !call_used_regs[regno] && - !IS_YBASE_REGISTER_WINDOW(regno)); - -} - -int -ybase_regs_ever_used () -{ - int regno; - int live = 0; - - for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++) - if (regs_ever_live[regno]) - { - live = 1; - break; - } - - return live; -} - -void -function_prologue (file, size) -FILE *file; -int size; -{ - int regno; - long total_size; - fp = reg_names[FRAME_POINTER_REGNUM]; - sp = reg_names[STACK_POINTER_REGNUM]; - rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */ - a1h = reg_names[REG_A1]; - - total_size = compute_frame_size (size); - - fprintf( file, "\t/* FUNCTION PROLOGUE: */\n" ); - fprintf (file, "\t/* total=%d, vars= %d, regs= %d, args=%d, extra= %d */\n", - current_frame_info.total_size, - current_frame_info.var_size, - current_frame_info.reg_size, - current_function_outgoing_args_size, - current_frame_info.extra_size); - - fprintf (file, "\t/* fp save offset= %d, sp save_offset= %d */\n\n", - current_frame_info.fp_save_offset, - current_frame_info.sp_save_offset); - /* Set up the 'ybase' register window. */ - - if (ybase_regs_ever_used()) - { - fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]); - if (TARGET_YBASE_HIGH) - fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h); - else - fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h); - fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h); - } - -#if 0 - if (current_frame_info.function_makes_calls) - fprintf( file, "\t*%s++=%s\n", sp, rr ); /* Push return address */ -#endif - - - if (current_frame_info.var_size) - { - if (current_frame_info.var_size == 1) - fprintf (file, "\t*%s++\n", sp); - else - { - if(SMALL_INTVAL(current_frame_info.var_size) && ((current_frame_info.var_size & 0x8000) == 0)) - fprintf (file, "\t%s=%d\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.var_size, sp, reg_names[REG_J]); - else - fatal ("Stack size > 32k"); - } - } - - /* Save any registers this function uses, unless they are - * used in a call, in which case we don't need to - */ - - for( regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno ) - if (dsp16xx_call_saved_register (regno)) - { -#if OLD_REGISTER_SAVE - fprintf( file, "\t*%s++=%s\n", sp, reg_names[regno] ); -#else - fprintf( file, "\tpush(*%s)=%s\n", sp, reg_names[regno] ); -#endif - } - - if (current_frame_info.args_size) - { - if (current_frame_info.args_size == 1) - fprintf (file, "\t*%s++\n", sp); - else - { - if(SMALL_INTVAL(current_frame_info.args_size) && ((current_frame_info.args_size & 0x8000) == 0)) - fprintf (file, "\t%s=%d\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.args_size, sp, reg_names[REG_J]); - else - fatal ("Stack size > 32k"); - } - } - - if (frame_pointer_needed) - { - fprintf( file, "\t%s=%s\n", a1h, sp ); - fprintf( file, "\t%s=%s\n", fp, a1h ); /* Establish new base frame */ - fprintf( file, "\t%s=%d\n", reg_names[REG_J], -total_size); - fprintf( file, "\t*%s++%s\n", fp, reg_names[REG_J]); - } - - fprintf( file, "\t/* END FUNCTION PROLOGUE: */\n\n" ); -} - -void -init_emulation_routines () -{ - dsp16xx_addhf3_libcall = (rtx) 0; - dsp16xx_subhf3_libcall = (rtx) 0; - dsp16xx_mulhf3_libcall = (rtx) 0; - dsp16xx_divhf3_libcall = (rtx) 0; - dsp16xx_cmphf3_libcall = (rtx) 0; - dsp16xx_fixhfhi2_libcall = (rtx) 0; - dsp16xx_floathihf2_libcall = (rtx) 0; - dsp16xx_neghf2_libcall = (rtx) 0; - - dsp16xx_mulhi3_libcall = (rtx) 0; - dsp16xx_udivqi3_libcall = (rtx) 0; - dsp16xx_udivhi3_libcall = (rtx) 0; - dsp16xx_divqi3_libcall = (rtx) 0; - dsp16xx_divhi3_libcall = (rtx) 0; - dsp16xx_modqi3_libcall = (rtx) 0; - dsp16xx_modhi3_libcall = (rtx) 0; - dsp16xx_umodqi3_libcall = (rtx) 0; - dsp16xx_umodhi3_libcall = (rtx) 0; - dsp16xx_ashrhi3_libcall = (rtx) 0; - dsp16xx_ashlhi3_libcall = (rtx) 0; - dsp16xx_ucmphi2_libcall = (rtx) 0; - dsp16xx_lshrhi3_libcall = (rtx) 0; - -} -void -function_epilogue (file, size) -FILE *file; -int size; -{ - int regno; - int initial_stack_dec = 0; - - fp = reg_names[FRAME_POINTER_REGNUM]; - sp = reg_names[STACK_POINTER_REGNUM]; - rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */ - a1h = reg_names[REG_A1]; - - fprintf( file, "\n\t/* FUNCTION EPILOGUE: */\n" ); - - if (current_frame_info.args_size) - { - if (current_frame_info.args_size == 1) - fprintf (file, "\t*%s--\n", sp); - else - { - fprintf (file, "\t%s=%d\n\t*%s++%s\n", - reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]); - } - } - - if (ybase_regs_ever_used()) - { - fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]); - if (TARGET_YBASE_HIGH) - fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h); - else - fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h); - fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h); - } - - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno) - if (dsp16xx_call_saved_register(regno)) - { -#if OLD_REGISTER_SAVE - if (!initial_stack_dec) - { - initial_stack_dec = 1; - fprintf (file, "\t*%s--\n", sp); - } -#endif - -#if OLD_REGISTER_SAVE - fprintf( file, "\t%s=*%s--\n", reg_names[regno], sp ); -#else - fprintf( file, "\t%s=pop(*%s)\n", reg_names[regno], sp ); -#endif - } - - /* If we restored any registers we have to account for the - initial pre-decrement. But only if we had any local variables - or spills. */ -#if OLD_REGISTER_SAVE - if (initial_stack_dec) - fprintf (file, "\t*%s++\n", sp); -#endif - - if (current_frame_info.var_size) - { - if (current_frame_info.var_size == 1) - fprintf (file, "\t*%s--\n", sp); - else - { - fprintf (file, "\t%s=%d\n\t*%s++%s\n", - reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]); - } - } - - fprintf (file, "\treturn\n"); - /* Reset the frame info for the next function */ - current_frame_info = zero_frame_info; - init_emulation_routines (); -} - -/* Emit insns to move operands[1] into operands[0]. - - Return 1 if we have written out everything that needs to be done to - do the move. Otherwise, return 0 and the caller will emit the move - normally. */ - -int -emit_move_sequence (operands, mode) - rtx *operands; - enum machine_mode mode; -{ - register rtx operand0 = operands[0]; - register rtx operand1 = operands[1]; - - /* We can only store registers to memory. */ - - if (GET_CODE (operand0) == MEM && GET_CODE (operand1) != REG) - operands[1] = force_reg (mode, operand1); - - return 0; -} - -void -double_reg_from_memory (operands) -rtx operands[]; -{ - rtx xoperands[4]; - - if (GET_CODE(XEXP(operands[1],0)) == POST_INC) - { - output_asm_insn ("%u0=%1", operands); - output_asm_insn ("%w0=%1", operands); - } - else if (GET_CODE(XEXP(operands[1],0)) == POST_DEC) - { - xoperands[1] = XEXP (XEXP (operands[1], 0), 0); - xoperands[0] = operands[0]; - - /* We can't use j anymore since the compiler can allocate it. */ -/* output_asm_insn ("j=-3\n\t%u0=*%1++\n\t%w0=*%1++j", xoperands); */ - output_asm_insn ("%u0=*%1++\n\t%w0=*%1--\n\t*%1--\n\t*%1--", xoperands); - } - else if (GET_CODE(XEXP(operands[1],0)) == PLUS) - { - rtx addr; - rtx base; - int offset; - - output_asm_insn ("%u0=%1", operands); - - - /* In order to print out the least significant word we must - use 'offset + 1'. */ - addr = XEXP (operands[1], 0); - if (GET_CODE (XEXP(addr,0)) == CONST_INT) - offset = INTVAL(XEXP(addr,0)) + 1; - else if (GET_CODE (XEXP(addr,1)) == CONST_INT) - offset = INTVAL(XEXP(addr,1)) + 1; - - fprintf (asm_out_file, "\t%s=*(%d)\n", reg_names[REGNO(operands[0]) + 1], offset + 31); - } - else - { - xoperands[1] = XEXP(operands[1],0); - xoperands[0] = operands[0]; - - output_asm_insn ("%u0=*%1++\n\t%w0=*%1--", xoperands); - } -} - - -void -double_reg_to_memory (operands) -rtx operands[]; -{ - rtx xoperands[4]; - - if (GET_CODE(XEXP(operands[0],0)) == POST_INC) - { - output_asm_insn ("%0=%u1", operands); - output_asm_insn ("%0=%w1", operands); - } - else if (GET_CODE(XEXP(operands[0],0)) == POST_DEC) - { - xoperands[0] = XEXP (XEXP (operands[0], 0), 0); - xoperands[1] = operands[1]; - - /* We can't use j anymore since the compiler can allocate it. */ - -/* output_asm_insn ("j=-3\n\t*%0++=%u1\n\t*%0++j=%w1", xoperands); */ - output_asm_insn ("*%0++=%u1\n\t*%0--=%w1\n\t*%0--\n\t*%0--", xoperands); - - } - else if (GET_CODE(XEXP(operands[0],0)) == PLUS) - { - rtx addr; - int offset; - - output_asm_insn ("%0=%u1", operands); - - /* In order to print out the least significant word we must - use 'offset + 1'. */ - addr = XEXP (operands[0], 0); - if (GET_CODE (XEXP(addr,0)) == CONST_INT) - offset = INTVAL(XEXP(addr,0)) + 1; - else if (GET_CODE (XEXP(addr,1)) == CONST_INT) - offset = INTVAL(XEXP(addr,1)) + 1; - else - fatal ("Invalid addressing mode"); - - fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]); - } - else - { - xoperands[0] = XEXP(operands[0],0); - xoperands[1] = operands[1]; - - output_asm_insn ("*%0++=%u1\n\t*%0--=%w1", xoperands); - } -} - -void -override_options () -{ - if (chip_name == (char *) 0) - chip_name = DEFAULT_CHIP_NAME; - - if (text_seg_name == (char *) 0) - text_seg_name = DEFAULT_TEXT_SEG_NAME; - - if (data_seg_name == (char *) 0) - data_seg_name = DEFAULT_DATA_SEG_NAME; - - if (bss_seg_name == (char *) 0) - bss_seg_name = DEFAULT_BSS_SEG_NAME; - - if (const_seg_name == (char *) 0) - const_seg_name = DEFAULT_CONST_SEG_NAME; - - save_chip_name = (char *) xmalloc (strlen(chip_name) + 1); - strcpy (save_chip_name, chip_name); - - rsect_text = (char *) xmalloc (strlen(".rsect ") + - strlen(text_seg_name) + 3); - rsect_data = (char *) xmalloc (strlen(".rsect ") + - strlen(data_seg_name) + 3); - rsect_bss = (char *) xmalloc (strlen(".rsect ") + - strlen(bss_seg_name) + 3); - rsect_const = (char *) xmalloc (strlen(".rsect ") + - strlen(const_seg_name) + 3); - - sprintf (rsect_text, ".rsect \"%s\"", text_seg_name); - sprintf (rsect_data, ".rsect \"%s\"", data_seg_name); - sprintf (rsect_bss, ".rsect \"%s\"", bss_seg_name); - sprintf (rsect_const, ".rsect \"%s\"", const_seg_name); - - if (optimize) - { - if (TARGET_OPTIMIZE_SPEED) - { - flag_unroll_loops = 1; - flag_inline_functions = 1; - } - } -} - -enum rtx_code -next_cc_user_code (insn) -rtx insn; -{ - if ( !(insn = next_cc0_user (insn))) - abort (); - else if (GET_CODE (insn) == JUMP_INSN - && GET_CODE (PATTERN (insn)) == SET - && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE) - return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)); - else if (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SET - && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode)) - return GET_CODE (SET_SRC (PATTERN (insn))); - else - abort (); -} - -int -next_cc_user_unsigned (insn) - rtx insn; -{ - switch (next_cc_user_code (insn)) - { - case GTU: - case GEU: - case LTU: - case LEU: - return 1; - default: - return 0; - } -} - -void -print_operand(file, op, letter) -FILE *file; -rtx op; -int letter; -{ - enum rtx_code code; - - code = GET_CODE(op); - - switch (letter) - { - case 'I': - code = reverse_condition (code); - /* Fallthrough */ - - case 'C': - if (code == EQ) - { - fputs ("eq", file); - return; - } - else if (code == NE) - { - fputs ("ne", file); - return; - } - else if (code == GT || code == GTU) - { - fputs ("gt", file); - return; - } - else if (code == LT || code == LTU) - { - fputs ("mi", file); - return; - } - else if (code == GE || code == GEU) - { - fputs ("pl", file); - return; - } - else if (code == LE || code == LEU) - { - fputs ("le", file); - return; - } - else - abort (); - break; - - default: - break; - } - - if( code == REG ) - { - /* Print the low half of a 32-bit register pair */ - if (letter == 'w') - fprintf( file, "%s", reg_names[REGNO(op)+1] ); - else if (letter == 'u' || !letter) - fprintf( file, "%s", reg_names[REGNO(op)]); - else if (letter == 'b') - fprintf ( file, "%sh", reg_names[REGNO(op)]); - else if (letter == 'm') - fprintf (file, "%s", himode_reg_name[REGNO(op)]); - else - fatal("Bad register extension code"); - } - else if( code == MEM ) - output_address( XEXP(op,0) ); - else if( code == CONST_INT ) - { - HOST_WIDE_INT val = INTVAL (op); - if( letter == 'H' ) - fprintf( file, HOST_WIDE_INT_PRINT_HEX, val & 0xffff); - else if (letter == 'h') - fprintf( file, HOST_WIDE_INT_PRINT_DEC, val); - else if( letter == 'U' ) - fprintf( file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff); - else - output_addr_const( file, op ); - } - else if( code == CONST_DOUBLE && GET_MODE(op) != DImode ) - { - union { double d; int i[2]; } u; - union { float f; int i; } u1; - u.i[0] = CONST_DOUBLE_LOW (op); - u.i[1] = CONST_DOUBLE_HIGH (op); - u1.f = u.d; - fprintf( file, "0x%x", u1.i ); - } - else output_addr_const( file, op); -} - - -void -print_operand_address(file, addr) -FILE *file; -rtx addr; -{ - rtx base; - int offset; - - switch (GET_CODE (addr)) - { - case REG: - fprintf (file, "*%s", reg_names[REGNO (addr)]); - break; - case POST_DEC: - fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]); - break; - case POST_INC: - fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]); - break; - case PLUS: - if (GET_CODE (XEXP(addr,0)) == CONST_INT) - offset = INTVAL(XEXP(addr,0)), base = XEXP(addr,1); - else if (GET_CODE (XEXP(addr,1)) == CONST_INT) - offset = INTVAL(XEXP(addr,1)), base = XEXP(addr,0); - if (GET_CODE (base) == REG && REGNO(base) == STACK_POINTER_REGNUM) - { - if (offset >= -31 && offset <= 0) - offset = 31 + offset; - else - fatal ("Invalid offset in ybase addressing"); - } - else - fatal ("Invalid register in ybase addressing"); - - fprintf (file, "*(%d)", offset); - break; - - default: - if( FITS_5_BITS( addr ) ) - fprintf( file, "*(0x%x)", (INTVAL(addr) & 0x20) ); - else - output_addr_const(file, addr); - } -} - -void -output_dsp16xx_float_const(operands) -rtx *operands; -{ - rtx dst = operands[0]; - rtx src = operands[1]; - -#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT - REAL_VALUE_TYPE d; - long value; - - REAL_VALUE_FROM_CONST_DOUBLE (d, src); - REAL_VALUE_TO_TARGET_SINGLE (d, value); - - operands[1] = GEN_INT (value); - output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands); -#else - fatal ("inline float constants not supported on this host"); -#endif -} - -int -reg_save_size () -{ - int reg_save_size = 0; - int regno; - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (dsp16xx_call_saved_register (regno)) - { - reg_save_size += UNITS_PER_WORD; - } - - return (reg_save_size); -} - -int -dsp16xx_starting_frame_offset() -{ - int reg_save_size = 0; - int regno; - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (dsp16xx_call_saved_register (regno)) - { - reg_save_size += UNITS_PER_WORD; - } - - return (reg_save_size); -} - -int -initial_frame_pointer_offset() -{ - int frame_size; - int regno; - int offset = 0; - - offset = compute_frame_size (get_frame_size()); - -#ifdef STACK_GROWS_DOWNWARD - return (offset); -#else - return (-offset); -#endif -} - -/* Generate the minimum number of 1600 core shift instructions - to shift by 'shift_amount'. */ - -#if 0 -void -emit_1600_core_shift (shift_op, operands, shift_amount, mode) -enum rtx_code shift_op; -rtx *operands; -int shift_amount; -enum machine_mode mode; -{ - int quotient; - int i; - int first_shift_emitted = 0; - - while (shift_amount != 0) - { - if (shift_amount/16) - { - quotient = shift_amount/16; - shift_amount = shift_amount - (quotient * 16); - for (i = 0; i < quotient; i++) - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (shift_op, mode, - first_shift_emitted ? operands[0] : operands[1], - GEN_INT (16)))); - first_shift_emitted = 1; - } - else if (shift_amount/8) - { - quotient = shift_amount/8; - shift_amount = shift_amount - (quotient * 8); - for (i = 0; i < quotient; i++) - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (shift_op, mode, - first_shift_emitted ? operands[0] : operands[1], - GEN_INT (8)))); - first_shift_emitted = 1; - } - else if (shift_amount/4) - { - quotient = shift_amount/4; - shift_amount = shift_amount - (quotient * 4); - for (i = 0; i < quotient; i++) - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (shift_op, mode, - first_shift_emitted ? operands[0] : operands[1], - GEN_INT (4)))); - first_shift_emitted = 1; - } - else if (shift_amount/1) - { - quotient = shift_amount/1; - shift_amount = shift_amount - (quotient * 1); - for (i = 0; i < quotient; i++) - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (shift_op, mode, - first_shift_emitted ? operands[0] : operands[1], - GEN_INT (1)))); - first_shift_emitted = 1; - } - } -} -#else -void -emit_1600_core_shift (shift_op, operands, shift_amount) -enum rtx_code shift_op; -rtx *operands; -int shift_amount; -{ - int quotient; - int i; - int first_shift_emitted = 0; - char **shift_asm_ptr; - char **shift_asm_ptr_first; - - if (shift_op == ASHIFT) - { - shift_asm_ptr = ashift_left_asm; - shift_asm_ptr_first = ashift_left_asm_first; - } - else if (shift_op == ASHIFTRT) - { - shift_asm_ptr = ashift_right_asm; - shift_asm_ptr_first = ashift_right_asm_first; - } - else if (shift_op == LSHIFTRT) - { - shift_asm_ptr = lshift_right_asm; - shift_asm_ptr_first = lshift_right_asm_first; - } - else - fatal ("Invalid shift operator in emit_1600_core_shift"); - - while (shift_amount != 0) - { - if (shift_amount/16) - { - quotient = shift_amount/16; - shift_amount = shift_amount - (quotient * 16); - for (i = 0; i < quotient; i++) - output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_16] - : shift_asm_ptr_first[SHIFT_INDEX_16]), operands); - first_shift_emitted = 1; - } - else if (shift_amount/8) - { - quotient = shift_amount/8; - shift_amount = shift_amount - (quotient * 8); - for (i = 0; i < quotient; i++) - output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_8] - : shift_asm_ptr_first[SHIFT_INDEX_8]), operands); - first_shift_emitted = 1; - } - else if (shift_amount/4) - { - quotient = shift_amount/4; - shift_amount = shift_amount - (quotient * 4); - for (i = 0; i < quotient; i++) - output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_4] - : shift_asm_ptr_first[SHIFT_INDEX_4]), operands); - first_shift_emitted = 1; - } - else if (shift_amount/1) - { - quotient = shift_amount/1; - shift_amount = shift_amount - (quotient * 1); - for (i = 0; i < quotient; i++) - output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_1] - : shift_asm_ptr_first[SHIFT_INDEX_1]), operands); - first_shift_emitted = 1; - } - } -} -#endif -void - asm_output_common(file, name, size, rounded) -FILE *file; -char *name; -int size; -int rounded; -{ - bss_section (); - ASM_GLOBALIZE_LABEL (file, name); - assemble_name (file, name); - fputs (":", file); - if (rounded > 1) - fprintf (file, "%d * int\n", rounded); - else - fprintf (file, "int\n"); -} - -void -asm_output_local(file, name, size, rounded) -FILE *file; -char *name; -int size; -int rounded; -{ - bss_section (); - assemble_name (file, name); - fputs (":", file); - if (rounded > 1) - fprintf (file, "%d * int\n", rounded); - else - fprintf (file, "int\n"); -} - -void -asm_output_float (file, fp_const) -FILE *file; -double fp_const; -{ -#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT - REAL_VALUE_TYPE d = fp_const; - long value; - - REAL_VALUE_TO_TARGET_SINGLE (d, value); - fputs ("\tint ", file); -#ifdef WORDS_BIG_ENDIAN - fprintf (file, "0x%-4.4x, 0x%-4.4x", (value >> 16) & 0xffff, (value & 0xffff)); -#else - fprintf (file, "0x%-4.4x, 0x%-4.4x", (value & 0xffff), (value >> 16) & 0xffff); -#endif - fputs ("\n", file); -#else - fatal ("inline float constants not supported on this host"); -#endif -} - -void -asm_output_long (file, value) -FILE *file; -long value; -{ - fputs ("\tint ", file); -#ifdef WORDS_BIG_ENDIAN - fprintf (file, "0x%-4.4x, 0x%-4.4x", (value >> 16) & 0xffff, (value & 0xffff)); -#else - fprintf (file, "0x%-4.4x, 0x%-4.4x", (value & 0xffff), (value >> 16) & 0xffff); -#endif - fputs ("\n", file); -} - -int -dsp16xx_address_cost (addr) -rtx addr; -{ - switch (GET_CODE (addr)) - { - default: - break; - - case REG: - return 1; - - case CONST: - { - rtx offset = const0_rtx; - addr = eliminate_constant_term (addr, &offset); - - if (GET_CODE (addr) == LABEL_REF) - return 2; - - if (GET_CODE (addr) != SYMBOL_REF) - return 4; - - if (INTVAL (offset) == 0) - return 2; - } - /* fall through */ - - case POST_INC: case POST_DEC: - return (GET_MODE (addr) == QImode ? 1 : 2); - - case SYMBOL_REF: case LABEL_REF: - return 2; - - case PLUS: - { - register rtx plus0 = XEXP (addr, 0); - register rtx plus1 = XEXP (addr, 1); - - if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG) - { - plus0 = XEXP (addr, 1); - plus1 = XEXP (addr, 0); - } - - if (GET_CODE (plus0) != REG) - break; - - switch (GET_CODE (plus1)) - { - default: - break; - - case CONST_INT: - return 4; - - case CONST: - case SYMBOL_REF: - case LABEL_REF: - return dsp16xx_address_cost (plus1) + 1; - } - } - } - - return 4; -} - - -/* Determine whether a function argument is passed in a register, and - which register. - - The arguments are CUM, which summarizes all the previous - arguments; MODE, the machine mode of the argument; TYPE, - the data type of the argument as a tree node or 0 if that is not known - (which happens for C support library functions); and NAMED, - which is 1 for an ordinary argument and 0 for nameless arguments that - correspond to `...' in the called function's prototype. - - The value of the expression should either be a `reg' RTX for the - hard register in which to pass the argument, or zero to pass the - argument on the stack. - - On the dsp1610 the first four words of args are normally in registers - and the rest are pushed. If we a long or on float mode, the argument - must begin on a even register boundary - - Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different. - For structures that are passed in memory, but could have been - passed in registers, we first load the structure into the - register, and then when the last argument is passed, we store - the registers into the stack locations. This fixes some bugs - where GCC did not expect to have register arguments, followed */ - - -struct rtx_def * -dsp16xx_function_arg (args_so_far, mode, type, named) - CUMULATIVE_ARGS args_so_far; - enum machine_mode mode; - tree type; - int named; -{ - if (TARGET_REGPARM) - { - if ((args_so_far & 1) != 0 - && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT)) - args_so_far++; - - if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type)) - return gen_rtx (REG, mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG); - else - return (struct rtx_def *) 0; - } - else - return (struct rtx_def *) 0; -} - -/* Advance the argument to the next argument position. */ - -void -dsp16xx_function_arg_advance (cum, mode, type, named) - CUMULATIVE_ARGS *cum; /* current arg information */ - enum machine_mode mode; /* current arg mode */ - tree type; /* type of the argument or 0 if lib support */ - int named; /* whether or not the argument was named */ -{ - if (TARGET_REGPARM) - { - if ((*cum & 1) != 0 - && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT)) - *cum += 1; - - if (mode != BLKmode) - *cum += GET_MODE_SIZE (mode); - else - *cum += int_size_in_bytes (type); - } -} - -void -dsp16xx_file_start () -{ - fprintf (asm_out_file, "#include <%s.h>\n", save_chip_name); -#if 0 - if (TARGET_BMU) - fprintf (asm_out_file, "#include <1610.h>\n"); -#endif -} - -rtx -gen_tst_reg (x) - rtx x; -{ - enum machine_mode mode; - - mode = GET_MODE (x); - - if (mode == QImode) - { - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, - gen_rtx (SET, VOIDmode, cc0_rtx, x), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (SCRATCH, QImode, 0))))); - } - else if (mode == HImode) - emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, x)); - else - fatal ("Invalid mode for gen_tst_reg"); - - return cc0_rtx; -} - -rtx -gen_compare_reg (code, x, y) - enum rtx_code code; - rtx x, y; -{ - enum machine_mode mode; - - mode = GET_MODE (x); - /* For floating point compare insns, a call is generated so don't - do anything here. */ - - if (GET_MODE_CLASS (mode) == MODE_FLOAT) - return cc0_rtx; - - if (mode == QImode) - { - if (code == GTU || code == GEU || - code == LTU || code == LEU) - { - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (3, - gen_rtx (SET, VOIDmode, cc0_rtx, - gen_rtx (COMPARE, mode, x, y)), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (SCRATCH, QImode, 0)), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (SCRATCH, QImode, 0))))); - } - else - { - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (3, - gen_rtx (SET, VOIDmode, cc0_rtx, - gen_rtx (COMPARE, mode, x, y)), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (SCRATCH, QImode, 0)), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (SCRATCH, QImode, 0))))); - } - } - else if (mode == HImode) - { - if (code == GTU || code == GEU || - code == LTU || code == LEU) - { -#if 1 - emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (5, - gen_rtx (SET, VOIDmode, cc0_rtx, gen_rtx (COMPARE, VOIDmode, x, y)), - gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)), - gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)), - gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0)), - gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0))))); -#else - if (!dsp16xx_ucmphi2_libcall) - dsp16xx_ucmphi2_libcall = gen_rtx (SYMBOL_REF, Pmode, UCMPHI2_LIBCALL); - emit_library_call (dsp16xx_ucmphi2_libcall, 1, HImode, 2, - x, HImode, y, HImode); - emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode)))); -#endif - } - else - emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, - gen_rtx (COMPARE, VOIDmode, force_reg(HImode, x), - force_reg(HImode,y)))); - } - else - fatal ("Invalid mode for integer comparison in gen_compare_reg"); - - return cc0_rtx; -} - -char * -output_block_move (operands) - rtx operands[]; -{ - int loop_count = INTVAL(operands[2]); - rtx xoperands[4]; - - fprintf (asm_out_file, "\tdo %d {\n", loop_count); - xoperands[0] = operands[4]; - xoperands[1] = operands[1]; - output_asm_insn ("%0=*%1++", xoperands); - - xoperands[0] = operands[0]; - xoperands[1] = operands[4]; - output_asm_insn ("*%0++=%1", xoperands); - - fprintf (asm_out_file, "\t}\n"); - return ""; -} diff --git a/gcc/config/dsp16xx/dsp16xx.h b/gcc/config/dsp16xx/dsp16xx.h deleted file mode 100755 index f71ed37..0000000 --- a/gcc/config/dsp16xx/dsp16xx.h +++ /dev/null @@ -1,1972 +0,0 @@ -/* Definitions of target machine for GNU compiler. AT&T DSP1600. - Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. - Contributed by Michael Collison (collison@world.std.com). - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -extern char *low_reg_names[]; -extern char *text_seg_name; -extern char *rsect_text; -extern char *data_seg_name; -extern char *rsect_data; -extern char *bss_seg_name; -extern char *rsect_bss; -extern char *const_seg_name; -extern char *rsect_const; -extern char *chip_name; -extern char *save_chip_name; -extern struct rtx_def *dsp16xx_compare_op0, *dsp16xx_compare_op1; -extern struct rtx_def *(*dsp16xx_compare_gen)(); -extern struct rtx_def *gen_compare_reg(); -extern struct rtx_def *dsp16xx_addhf3_libcall; -extern struct rtx_def *dsp16xx_subhf3_libcall; -extern struct rtx_def *dsp16xx_mulhf3_libcall; -extern struct rtx_def *dsp16xx_divhf3_libcall; -extern struct rtx_def *dsp16xx_cmphf3_libcall; -extern struct rtx_def *dsp16xx_fixhfhi2_libcall; -extern struct rtx_def *dsp16xx_floathihf2_libcall; -extern struct rtx_def *dsp16xx_neghf2_libcall; -extern struct rtx_def *dsp16xx_umulhi3_libcall; -extern struct rtx_def *dsp16xx_mulhi3_libcall; -extern struct rtx_def *dsp16xx_udivqi3_libcall; -extern struct rtx_def *dsp16xx_udivhi3_libcall; -extern struct rtx_def *dsp16xx_divqi3_libcall; -extern struct rtx_def *dsp16xx_divhi3_libcall; -extern struct rtx_def *dsp16xx_modqi3_libcall; -extern struct rtx_def *dsp16xx_modhi3_libcall; -extern struct rtx_def *dsp16xx_umodqi3_libcall; -extern struct rtx_def *dsp16xx_umodhi3_libcall; - -extern struct rtx_def *dsp16xx_ashrhi3_libcall; -extern struct rtx_def *dsp16xx_ashlhi3_libcall; -extern struct rtx_def *dsp16xx_lshrhi3_libcall; - - -extern int hard_regno_mode_ok (); -extern enum reg_class dsp16xx_reg_class_from_letter (); -extern enum reg_class dsp16xx_limit_reload_class (); -extern int hard_regno_nregs (); -extern int regno_reg_class (); -extern int move_operand (); -extern int symbolic_address_p (); -extern int Y_address (); -extern int call_address_operand (); -extern void notice_update_cc(); -extern void function_prologue (); -extern void function_epilogue (); -extern int dsp1600_comparison_reverse (); -extern void double_reg_from_memory (); -extern void double_reg_to_memory (); -extern void bss_section (); -extern struct rtx_def *dsp16xx_function_arg (); -extern void dsp16xx_function_arg_advance (); -extern enum rtx_code next_cc_user_code (); -extern int next_cc_user_unsigned (); -extern struct rtx_def *gen_tst_reg (); -extern char *output_block_move(); - -/* RUN-TIME TARGET SPECIFICATION */ -#define DSP16XX 1 - -/* Name of the AT&T assembler */ - -#define ASM_PROG "as1600" - -/* Name of the AT&T linker */ - -#define LD_PROG "ld1600" - -/* Define which switches take word arguments */ -#define WORD_SWITCH_TAKES_ARG(STR) \ - (!strcmp (STR, "ifile") ? 1 : \ - 0) - -#ifdef CC1_SPEC -#undef CC1_SPEC -#endif -#define CC1_SPEC "" - -/* Define this as a spec to call the AT&T assembler */ - -#define CROSS_ASM_SPEC "%{!S:as1600 %a %i\n }" - -/* Define this as a spec to call the AT&T linker */ - -#define CROSS_LINK_SPEC "%{!c:%{!M:%{!MM:%{!E:%{!S:ld1600 %l %X %{o*} %{m} \ - %{r} %{s} %{t} %{u*} %{x}\ - %{!A:%{!nostdlib:%{!nostartfiles:%S}}} %{static:}\ - %{L*} %D %o %{!nostdlib:-le1600 %L -le1600}\ - %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\n }}}}}" - -/* Nothing complicated here, just link with libc.a under normal - circumstances */ -#define LIB_SPEC "-lc" - -/* Specify the startup file to link with. */ -#define STARTFILE_SPEC "%{mmap1:m1_crt0.o%s} \ -%{mmap2:m2_crt0.o%s} \ -%{mmap3:m3_crt0.o%s} \ -%{mmap4:m4_crt0.o%s} \ -%{!mmap*: %{!ifile*: m4_crt0.o%s} %{ifile*: \ -%eA -ifile option requires a -map option}}" - -/* Specify the end file to link with */ - -#define ENDFILE_SPEC "%{mmap1:m1_crtn.o%s} \ -%{mmap2:m2_crtn.o%s} \ -%{mmap3:m3_crtn.o%s} \ -%{mmap4:m4_crtn.o%s} \ -%{!mmap*: %{!ifile*: m4_crtn.o%s} %{ifile*: \ -%eA -ifile option requires a -map option}}" - - -/* Tell gcc where to look for the startfile */ -#define STANDARD_STARTFILE_PREFIX "/d1600/lib" - -/* Tell gcc where to look for its executables */ -#define STANDARD_EXEC_PREFIX "/d1600/bin" - -/* Command line options to the AT&T assembler */ -#define ASM_SPEC "%{v:-V} %{g*:-g}" - -/* Command line options for the AT&T linker */ -#define LINK_SPEC "%{v:-V} %{minit:-i} \ -%{!ifile*:%{mmap1:-ifile m1_deflt.if%s} \ - %{mmap2:-ifile m2_deflt.if%s} \ - %{mmap3:-ifile m3_deflt.if%s} \ - %{mmap4:-ifile m4_deflt.if%s} \ - %{!mmap*:-ifile m4_deflt.if%s}} \ -%{ifile*} %{!r:-a}" - -/* Names to predefine in the preprocessor for this target machine. */ -#ifdef __MSDOS__ -#define CPP_PREDEFINES "-Ddsp1600 -DDSP1600 -DMSDOS" -#else -#define CPP_PREDEFINES "-Ddsp1600 -DDSP1600 -Ddsp1610 -DDSP1610" -#endif - -/* Run-time compilation parameters selecting different hardware subsets. */ - -extern int target_flags; - -/* Macros used in the machine description to test the flags. */ - -#define MASK_REGPARM 0x00000001 /* Pass parameters in registers */ -#define MASK_NEAR_CALL 0x00000002 /* The call is on the same 4k page */ -#define MASK_NEAR_JUMP 0x00000004 /* The jump is on the same 4k page */ -#define MASK_BMU 0x00000008 /* Use the 'bmu' shift instructions */ -#define MASK_OPTIMIZE_MEMORY 0x00000010 /* Optimize to conserve memory */ -#define MASK_OPTIMIZE_SPEED 0x00000020 /* Optimize for speed */ -#define MASK_MAP1 0x00000040 /* Link with map1 */ -#define MASK_MAP2 0x00000080 /* Link with map2 */ -#define MASK_MAP3 0x00000100 /* Link with map3 */ -#define MASK_MAP4 0x00000200 /* Link with map4 */ -#define MASK_YBASE_HIGH 0x00000400 /* The ybase register window starts high */ -#define MASK_INIT 0x00000800 /* Have the linker generate tables to - initialize data at startup */ -#define MASK_INLINE_MULT 0x00001000 /* Inline 32 bit multiplies */ -#define MASK_RESERVE_YBASE 0x00002000 /* Reserved the ybase registers */ - -/* Compile passing first two args in regs 0 and 1. - This exists only to test compiler features that will - be needed for RISC chips. It is not usable - and is not intended to be usable on this cpu. */ -#define TARGET_REGPARM (target_flags & MASK_REGPARM) - -/* The call is on the same 4k page, so instead of loading - the 'pt' register and branching, we can branch directly */ - -#define TARGET_NEAR_CALL (target_flags & MASK_NEAR_CALL) - -/* The jump is on the same 4k page, so instead of loading - the 'pt' register and branching, we can branch directly */ - -#define TARGET_NEAR_JUMP (target_flags & MASK_NEAR_JUMP) - -/* Generate shift instructions to use the 1610 Bit Manipulation - Unit. */ -#define TARGET_BMU (target_flags & MASK_BMU) - -/* Optimize to conserve memory */ -#define TARGET_OPTIMIZE_MEMORY (target_flags & MASK_OPTIMIZE_MEMORY) - -/* Optimize for maximum speed */ -#define TARGET_OPTIMIZE_SPEED (target_flags & MASK_OPTIMIZE_SPEED) - -#define TARGET_YBASE_HIGH (target_flags & MASK_YBASE_HIGH) - -/* Direct the linker to output extra info for initialized data */ -#define TARGET_MASK_INIT (target_flags & MASK_INIT) - -#define TARGET_INLINE_MULT (target_flags & MASK_INLINE_MULT) - -/* Reserve the ybase registers *(0) - *(31) */ -#define TARGET_RESERVE_YBASE (target_flags & MASK_RESERVE_YBASE) - -/* Macro to define tables used to set the flags. - This is a list in braces of pairs in braces, - each pair being { "NAME", VALUE } - where VALUE is the bits to set or minus the bits to clear. - An empty string NAME is used to identify the default VALUE. */ - - -#define TARGET_SWITCHES \ - { \ - { "regparm", MASK_REGPARM}, \ - { "no-regparm", -MASK_REGPARM}, \ - { "no-near-call", -MASK_NEAR_CALL}, \ - { "near-jump", MASK_NEAR_JUMP}, \ - { "no-near-jump", -MASK_NEAR_JUMP}, \ - { "bmu", MASK_BMU}, \ - { "no-bmu", -MASK_BMU}, \ - { "Om", MASK_OPTIMIZE_MEMORY}, \ - { "Os", MASK_OPTIMIZE_SPEED}, \ - { "map1", MASK_MAP1}, \ - { "map2", MASK_MAP2}, \ - { "map3", MASK_MAP3}, \ - { "map4", MASK_MAP4}, \ - { "ybase-high", MASK_YBASE_HIGH}, \ - { "init", MASK_INIT}, \ - { "inline-mult", MASK_INLINE_MULT}, \ - { "reserve-ybase", MASK_RESERVE_YBASE}, \ - { "", TARGET_DEFAULT} \ - } - -/* Default target_flags if no switches are specified */ -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT MASK_OPTIMIZE_MEMORY|MASK_REGPARM|MASK_YBASE_HIGH -#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. - - Each subgrouping contains a string constant, that defines the - fixed part of the option name, and the address of a variable. - The variable, type `char *', is set to the variable part of the - given option if the fixed part matches. The actual option name - is made by appending `-m' to the specified name. - - Here is an example which defines `-mshort-data-NUMBER'. If the - given option is `-mshort-data-512', the variable `m88k_short_data' - will be set to the string `"512"'. - - extern char *m88k_short_data; - #define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */ - -#define TARGET_OPTIONS \ -{ \ - { "text=", &text_seg_name }, \ - { "data=", &data_seg_name }, \ - { "bss=", &bss_seg_name }, \ - { "const=", &const_seg_name }, \ - { "chip=", &chip_name } \ -} - -/* Sometimes certain combinations of command options do not make sense - on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. - - Don't use this macro to turn on various extra optimizations for - `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ - -#define OVERRIDE_OPTIONS override_options () - -#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ -do \ - { \ - flag_gnu_linker = FALSE; \ - \ - if (SIZE) \ - { \ - flag_strength_reduce = FALSE; \ - flag_inline_functions = FALSE; \ - } \ - } \ -while (0) - -/* STORAGE LAYOUT */ - -/* Define if you don't want extended real, but do want to use the - software floating point emulator for REAL_ARITHMETIC and - decimal <-> binary conversion. */ -#define REAL_ARITHMETIC - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. - */ -#define BITS_BIG_ENDIAN 1 - -/* Define this if most significant byte of a word is the lowest numbered. - We define big-endian, but since the 1600 series cannot address bytes - it does not matter. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this if most significant word of a multiword number is numbered. - For the 1600 we can decide arbitrarily since there are no machine instructions for them. */ -#define WORDS_BIG_ENDIAN 1 - -/* number of bits in an addressable storage unit */ -#define BITS_PER_UNIT 16 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; - if using 16-bit ints on a 68000, this would still be 32. - But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 16 - -/* Maximum number of bits in a word. */ -#define MAX_BITS_PER_WORD 16 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 1 - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 16 - -/* Allocation boundary (in *bits*) for storing pointers in memory. */ -#define POINTER_BOUNDARY 16 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 16 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 16 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 16 - -/* Biggest alignment that any data type can require on this machine, in bits. */ -#define BIGGEST_ALIGNMENT 16 - -/* Biggest alignment that any structure field can require on this machine, in bits */ -#define BIGGEST_FIELD_ALIGNMENT 16 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 16 - -/* Number of bits which any structure or union's size must be a multiple of. Each structure - or union's size is rounded up to a multiple of this */ -#define STRUCTURE_SIZE_BOUNDARY 16 - -/* Define this if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 1 - -/* An integer expression for the size in bits of the largest integer machine mode that - should actually be used. All integer machine modes of this size or smaller can be - used for structures and unions with the appropriate sizes. */ -#define MAX_FIXED_MODE_SIZE 32 - -/* LAYOUT OF SOURCE LANGUAGE DATA TYPES */ - -#define CHAR_TYPE_SIZE 16 -#define SHORT_TYPE_SIZE 16 -#define INT_TYPE_SIZE 16 -#define LONG_TYPE_SIZE 32 -#define LONG_LONG_TYPE_SIZE 32 -#define FLOAT_TYPE_SIZE 32 -#define DOUBLE_TYPE_SIZE 32 -#define LONG_DOUBLE_TYPE_SIZE 32 - -/* An expression whose value is 1 or 0, according to whether the type char should be - signed or unsigned by default. */ - -#define DEFAULT_SIGNED_CHAR 1 - -/* A C expression to determine whether to give an enum type only as many bytes - as it takes to represent the range of possible values of that type. A nonzero - value means to do that; a zero value means all enum types should be allocated - like int. */ - -#define DEFAULT_SHORT_ENUMS 0 - -/* A C expression for a string describing the name of the data type to use for - size values. */ - -#define SIZE_TYPE "long unsigned int" - -/* A C expression for a string describing the name of the datat type to use for the - result of subtracting two pointers */ - -#define PTRDIFF_TYPE "long int" - -#define TARGET_BELL '\a' -#define TARGET_BS '\b' -#define TARGET_TAB '\t' -#define TARGET_NEWLINE '\n' -#define TARGET_VT '\v' -#define TARGET_FF '\f' -#define TARGET_CR '\r' - - -/* REGISTER USAGE. */ - -#define ALL_16_BIT_REGISTERS 1 - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to FIRST_PSEUDO_REGISTER-1 */ - -#define FIRST_PSEUDO_REGISTER (REG_YBASE31 + 1) - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - - The registers are laid out as follows: - - {a0,a0l,a1,a1l,x,y,yl,p,pl} - Data Arithmetic Unit - {r0,r1,r2,r3,j,k,ybase} - Y Space Address Arithmetic Unit - {pt} - X Space Address Arithmetic Unit - {ar0,ar1,ar2,ar3} - Bit Manipulation UNit - {pr} - Return Address Register - - We reserve r2 for the Stack Pointer. - We specify r3 for the Frame Pointer but allow the compiler - to omit it when possible since we have so few pointer registers. */ - -#define REG_A0 0 -#define REG_A0L 1 -#define REG_A1 2 -#define REG_A1L 3 -#define REG_X 4 -#define REG_Y 5 -#define REG_YL 6 -#define REG_PROD 7 -#define REG_PRODL 8 -#define REG_R0 9 -#define REG_R1 10 -#define REG_R2 11 -#define REG_R3 12 -#define REG_J 13 -#define REG_K 14 -#define REG_YBASE 15 -#define REG_PT 16 -#define REG_AR0 17 -#define REG_AR1 18 -#define REG_AR2 19 -#define REG_AR3 20 -#define REG_C0 21 -#define REG_C1 22 -#define REG_C2 23 -#define REG_PR 24 -#define REG_RB 25 -#define REG_YBASE0 26 -#define REG_YBASE1 27 -#define REG_YBASE2 28 -#define REG_YBASE3 29 -#define REG_YBASE4 30 -#define REG_YBASE5 31 -#define REG_YBASE6 32 -#define REG_YBASE7 33 -#define REG_YBASE8 34 -#define REG_YBASE9 35 -#define REG_YBASE10 36 -#define REG_YBASE11 37 -#define REG_YBASE12 38 -#define REG_YBASE13 39 -#define REG_YBASE14 40 -#define REG_YBASE15 41 -#define REG_YBASE16 42 -#define REG_YBASE17 43 -#define REG_YBASE18 44 -#define REG_YBASE19 45 -#define REG_YBASE20 46 -#define REG_YBASE21 47 -#define REG_YBASE22 48 -#define REG_YBASE23 49 -#define REG_YBASE24 50 -#define REG_YBASE25 51 -#define REG_YBASE26 52 -#define REG_YBASE27 53 -#define REG_YBASE28 54 -#define REG_YBASE29 55 -#define REG_YBASE30 56 -#define REG_YBASE31 57 - -/* Do we have a accumulator register? */ -#define IS_ACCUM_REG(REGNO) ((REGNO) >= REG_A0 && (REGNO) <= REG_A1L) -#define IS_ACCUM_LOW_REG(REGNO) ((REGNO) == REG_A0L || (REGNO) == REG_A1L) - -/* Do we have a virtual ybase register */ -#define IS_YBASE_REGISTER_WINDOW(REGNO) ((REGNO) >= REG_YBASE0 && (REGNO) <= REG_YBASE31) - -#define IS_ADDRESS_REGISTER(REGNO) ((REGNO) >= REG_R0 && (REGNO) <= REG_R3) - -#define FIXED_REGISTERS \ -{0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 1, 0, 0, 1, \ - 1, \ - 0, 0, 0, 0, \ - 1, 1, 1, \ - 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 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - On the 1610 'a0' holds return values from functions. 'r0' holds - structure-value addresses. - - In addition we don't save either j, k, ybase or any of the - bit manipulation registers. */ - - -#define CALL_USED_REGISTERS \ -{1, 1, 1, 1, 0, 1, 1, 1, 1, \ - 1, 0, 0, 1, 1, 1, 1, \ - 1, \ - 0, 0, 1, 1, \ - 1, 1, 1, \ - 0, 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} - -/* List the order in which to allocate registers. Each register must be - listed once, even those in FIXED_REGISTERS. - - We allocate in the following order: - */ - -#define REG_ALLOC_ORDER \ -{ REG_R0, REG_R1, REG_R2, REG_PROD, REG_Y, REG_X, \ - REG_PRODL, REG_YL, REG_AR0, REG_AR1, \ - REG_RB, REG_A0, REG_A1, REG_A0L, \ - REG_A1L, REG_AR2, REG_AR3, \ - REG_YBASE, REG_J, REG_K, REG_PR, REG_PT, REG_C0, \ - REG_C1, REG_C2, REG_R3, \ - REG_YBASE0, REG_YBASE1, REG_YBASE2, REG_YBASE3, \ - REG_YBASE4, REG_YBASE5, REG_YBASE6, REG_YBASE7, \ - REG_YBASE8, REG_YBASE9, REG_YBASE10, REG_YBASE11, \ - REG_YBASE12, REG_YBASE13, REG_YBASE14, REG_YBASE15, \ - REG_YBASE16, REG_YBASE17, REG_YBASE18, REG_YBASE19, \ - REG_YBASE20, REG_YBASE21, REG_YBASE22, REG_YBASE23, \ - REG_YBASE24, REG_YBASE25, REG_YBASE26, REG_YBASE27, \ - REG_YBASE28, REG_YBASE29, REG_YBASE30, REG_YBASE31 } - -/* Zero or more C statements that may conditionally modify two - variables `fixed_regs' and `call_used_regs' (both of type `char - []') after they have been initialized from the two preceding - macros. - - This is necessary in case the fixed or call-clobbered registers - depend on target flags. - - You need not define this macro if it has no work to do. - - If the usage of an entire class of registers depends on the target - flags, you may indicate this to GCC by using this macro to modify - `fixed_regs' and `call_used_regs' to 1 for each of the registers in - the classes which should not be used by GCC. Also define the macro - `REG_CLASS_FROM_LETTER' to return `NO_REGS' if it is called with a - letter for a class that shouldn't be used. - - (However, if this class is not included in `GENERAL_REGS' and all - of the insn patterns whose constraints permit this class are - controlled by target switches, then GCC will automatically avoid - using these registers when the target switches are opposed to - them.) If the user tells us there is no BMU, we can't use - ar0-ar3 for register allocation */ - -#define CONDITIONAL_REGISTER_USAGE \ -do \ - { \ - if (!TARGET_BMU) \ - { \ - int regno; \ - \ - for (regno = REG_AR0; regno <= REG_AR3; regno++) \ - fixed_regs[regno] = call_used_regs[regno] = 1; \ - } \ - if (TARGET_RESERVE_YBASE) \ - { \ - int regno; \ - \ - for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++) \ - fixed_regs[regno] = call_used_regs[regno] = 1; \ - } \ - } \ -while (0) - -/* Determine which register classes are very likely used by spill registers. - local-alloc.c won't allocate pseudos that have these classes as their - preferred class unless they are "preferred or nothing". */ - -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - ((CLASS) != ALL_REGS && (CLASS) != YBASE_VIRT_REGS) - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - (GET_MODE_SIZE(MODE)) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ - -#define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok(REGNO, MODE) - -/* Value is 1 if it is a good idea to tie two pseudo registers - when one has mode MODE1 and one has mode MODE2. - If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, - for any hard reg, then this must be 0 for correct output. */ -#define MODES_TIEABLE_P(MODE1, MODE2) \ - (((MODE1) == (MODE2)) || \ - (GET_MODE_CLASS((MODE1)) == MODE_FLOAT) \ - == (GET_MODE_CLASS((MODE2)) == MODE_FLOAT)) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* DSP1600 pc isn't overloaded on a register. */ -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. - This is r3 in our case */ -#define STACK_POINTER_REGNUM REG_R3 - -/* Base register for access to local variables of the function. - This is r2 in our case */ -#define FRAME_POINTER_REGNUM REG_R2 - -/* We can debug without the frame pointer */ -#define CAN_DEBUG_WITHOUT_FP 1 - -/* The 1610 saves the return address in this register */ -#define RETURN_ADDRESS_REGNUM REG_PR - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM - -/* Register in which static-chain is passed to a function. */ - -#define STATIC_CHAIN_REGNUM 4 - -/* Register in which address to store a structure value - is passed to a function. This is 'r0' in our case */ -#define STRUCT_VALUE_REGNUM REG_R0 - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - - -enum reg_class -{ - NO_REGS, - A0H_REG, - A0L_REG, - A0_REG, - A1H_REG, - ACCUM_HIGH_REGS, - A1L_REG, - ACCUM_LOW_REGS, - A1_REG, - ACCUM_REGS, - X_REG, - X_OR_ACCUM_LOW_REGS, - X_OR_ACCUM_REGS, - YH_REG, - YH_OR_ACCUM_HIGH_REGS, - X_OR_YH_REGS, - YL_REG, - YL_OR_ACCUM_LOW_REGS, - X_OR_YL_REGS, - X_OR_Y_REGS, - Y_REG, - ACCUM_OR_Y_REGS, - PH_REG, - X_OR_PH_REGS, - PL_REG, - PL_OR_ACCUM_LOW_REGS, - X_OR_PL_REGS, - YL_OR_PL_OR_ACCUM_LOW_REGS, - P_REG, - ACCUM_OR_P_REGS, - YL_OR_P_REGS, - ACCUM_LOW_OR_YL_OR_P_REGS, - Y_OR_P_REGS, - ACCUM_Y_OR_P_REGS, - NO_FRAME_Y_ADDR_REGS, - Y_ADDR_REGS, - ACCUM_LOW_OR_Y_ADDR_REGS, - ACCUM_OR_Y_ADDR_REGS, - X_OR_Y_ADDR_REGS, - Y_OR_Y_ADDR_REGS, - P_OR_Y_ADDR_REGS, - NON_HIGH_YBASE_ELIGIBLE_REGS, - YBASE_ELIGIBLE_REGS, - J_REG, - J_OR_DAU_16_BIT_REGS, - BMU_REGS, - NOHIGH_NON_ADDR_REGS, - NON_ADDR_REGS, - SLOW_MEM_LOAD_REGS, - NOHIGH_NON_YBASE_REGS, - NO_ACCUM_NON_YBASE_REGS, - NON_YBASE_REGS, - YBASE_VIRT_REGS, - ACCUM_LOW_OR_YBASE_REGS, - ACCUM_OR_YBASE_REGS, - X_OR_YBASE_REGS, - Y_OR_YBASE_REGS, - ACCUM_LOW_YL_PL_OR_YBASE_REGS, - P_OR_YBASE_REGS, - ACCUM_Y_P_OR_YBASE_REGS, - Y_ADDR_OR_YBASE_REGS, - YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS, - YBASE_OR_YBASE_ELIGIBLE_REGS, - NO_HIGH_ALL_REGS, - ALL_REGS, - LIM_REG_CLASSES -}; - -/* GENERAL_REGS must be the name of a register class */ -#define GENERAL_REGS ALL_REGS - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ -{ \ - "NO_REGS", \ - "A0H_REG", \ - "A0L_REG", \ - "A0_REG", \ - "A1H_REG", \ - "ACCUM_HIGH_REGS", \ - "A1L_REG", \ - "ACCUM_LOW_REGS", \ - "A1_REG", \ - "ACCUM_REGS", \ - "X_REG", \ - "X_OR_ACCUM_LOW_REGS", \ - "X_OR_ACCUM_REGS", \ - "YH_REG", \ - "YH_OR_ACCUM_HIGH_REGS", \ - "X_OR_YH_REGS", \ - "YL_REG", \ - "YL_OR_ACCUM_LOW_REGS", \ - "X_OR_YL_REGS", \ - "X_OR_Y_REGS", \ - "Y_REG", \ - "ACCUM_OR_Y_REGS", \ - "PH_REG", \ - "X_OR_PH_REGS", \ - "PL_REG", \ - "PL_OR_ACCUM_LOW_REGS", \ - "X_OR_PL_REGS", \ - "PL_OR_YL_OR_ACCUM_LOW_REGS", \ - "P_REG", \ - "ACCUM_OR_P_REGS", \ - "YL_OR_P_REGS", \ - "ACCUM_LOW_OR_YL_OR_P_REGS", \ - "Y_OR_P_REGS", \ - "ACCUM_Y_OR_P_REGS", \ - "NO_FRAME_Y_ADDR_REGS", \ - "Y_ADDR_REGS", \ - "ACCUM_LOW_OR_Y_ADDR_REGS", \ - "ACCUM_OR_Y_ADDR_REGS", \ - "X_OR_Y_ADDR_REGS", \ - "Y_OR_Y_ADDR_REGS", \ - "P_OR_Y_ADDR_REGS", \ - "NON_HIGH_YBASE_ELIGIBLE_REGS", \ - "YBASE_ELIGIBLE_REGS", \ - "J_REG", \ - "J_OR_DAU_16_BIT_REGS", \ - "BMU_REGS", \ - "NOHIGH_NON_ADDR_REGS", \ - "NON_ADDR_REGS", \ - "SLOW_MEM_LOAD_REGS", \ - "NOHIGH_NON_YBASE_REGS", \ - "NO_ACCUM_NON_YBASE_REGS", \ - "NON_YBASE_REGS", \ - "YBASE_VIRT_REGS", \ - "ACCUM_LOW_OR_YBASE_REGS", \ - "ACCUM_OR_YBASE_REGS", \ - "X_OR_YBASE_REGS", \ - "Y_OR_YBASE_REGS", \ - "ACCUM_LOW_YL_PL_OR_YBASE_REGS", \ - "P_OR_YBASE_REGS", \ - "ACCUM_Y_P_OR_YBASE_REGS", \ - "Y_ADDR_OR_YBASE_REGS", \ - "YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS", \ - "YBASE_OR_YBASE_ELIGIBLE_REGS", \ - "NO_HIGH_ALL_REGS", \ - "ALL_REGS" \ -} - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS \ -{ \ - {0x00000000, 0x00000000}, /* no reg */ \ - {0x00000001, 0x00000000}, /* a0h */ \ - {0x00000002, 0x00000000}, /* a0l */ \ - {0x00000003, 0x00000000}, /* a0h:a0l */ \ - {0x00000004, 0x00000000}, /* a1h */ \ - {0x00000005, 0x00000000}, /* accum high */ \ - {0x00000008, 0x00000000}, /* a1l */ \ - {0x0000000A, 0x00000000}, /* accum low */ \ - {0x0000000c, 0x00000000}, /* a1h:a1l */ \ - {0x0000000f, 0x00000000}, /* accum regs */ \ - {0x00000010, 0x00000000}, /* x reg */ \ - {0x0000001A, 0x00000000}, /* x & accum_low_regs */ \ - {0x0000001f, 0x00000000}, /* x & accum regs */ \ - {0x00000020, 0x00000000}, /* y high */ \ - {0x00000025, 0x00000000}, /* yh, accum high */ \ - {0x00000030, 0x00000000}, /* x & yh */ \ - {0x00000040, 0x00000000}, /* y low */ \ - {0x0000004A, 0x00000000}, /* y low, accum_low */ \ - {0x00000050, 0x00000000}, /* x & yl */ \ - {0x00000060, 0x00000000}, /* yl:yh */ \ - {0x00000070, 0x00000000}, /* x, yh,a nd yl */ \ - {0x0000006F, 0x00000000}, /* accum, y */ \ - {0x00000080, 0x00000000}, /* p high */ \ - {0x00000090, 0x00000000}, /* x & ph */ \ - {0x00000100, 0x00000000}, /* p low */ \ - {0x0000010A, 0x00000000}, /* p_low and accum_low */ \ - {0x00000110, 0x00000000}, /* x & pl */ \ - {0x0000014A, 0x00000000}, /* pl,yl,a1l,a0l */ \ - {0x00000180, 0x00000000}, /* pl:ph */ \ - {0x0000018F, 0x00000000}, /* accum, p */ \ - {0x000001C0, 0x00000000}, /* pl:ph and yl */ \ - {0x000001CA, 0x00000000}, /* pl:ph, yl, a0l, a1l */ \ - {0x000001E0, 0x00000000}, /* y or p */ \ - {0x000001EF, 0x00000000}, /* accum, y or p */ \ - {0x00000E00, 0x00000000}, /* r0-r2 */ \ - {0x00001E00, 0x00000000}, /* r0-r3 */ \ - {0x00001E0A, 0x00000000}, /* r0-r3, accum_low */ \ - {0x00001E0F, 0x00000000}, /* accum,r0-r3 */ \ - {0x00001E10, 0x00000000}, /* x,r0-r3 */ \ - {0x00001E60, 0x00000000}, /* y,r0-r3 */ \ - {0x00001F80, 0x00000000}, /* p,r0-r3 */ \ - {0x00001FDA, 0x00000000}, /* ph:pl, r0-r3, x,a0l,a1l */ \ - {0x00001fff, 0x00000000}, /* accum,x,y,p,r0-r3 */ \ - {0x00002000, 0x00000000}, /* j */ \ - {0x00002025, 0x00000000}, /* j, yh, a1h, a0h */ \ - {0x001E0000, 0x00000000}, /* ar0-ar3 */ \ - {0x03FFE1DA, 0x00000000}, /* non_addr except yh,a0h,a1h */ \ - {0x03FFE1FF, 0x00000000}, /* non_addr regs */ \ - {0x03FFFF8F, 0x00000000}, /* non ybase except yh, yl, and x */ \ - {0x03FFFFDA, 0x00000000}, /* non ybase regs except yh,a0h,a1h */ \ - {0x03FFFFF0, 0x00000000}, /* non ybase except a0,a0l,a1,a1l */ \ - {0x03FFFFFF, 0x00000000}, /* non ybase regs */ \ - {0xFC000000, 0x03FFFFFF}, /* virt ybase regs */ \ - {0xFC00000A, 0x03FFFFFF}, /* accum_low, virt ybase regs */ \ - {0xFC00000F, 0x03FFFFFF}, /* accum, virt ybase regs */ \ - {0xFC000010, 0x03FFFFFF}, /* x,virt ybase regs */ \ - {0xFC000060, 0x03FFFFFF}, /* y,virt ybase regs */ \ - {0xFC00014A, 0x03FFFFFF}, /* accum_low, yl, pl, ybase */ \ - {0xFC000180, 0x03FFFFFF}, /* p,virt ybase regs */ \ - {0xFC0001EF, 0x03FFFFFF}, /* accum,y,p,ybase regs */ \ - {0xFC001E00, 0x03FFFFFF}, /* r0-r3, ybase regs */ \ - {0xFC001FDA, 0x03FFFFFF}, /* r0-r3, pl:ph,yl,x,a1l,a0l */ \ - {0xFC001FFF, 0x03FFFFFF}, /* virt ybase, ybase eligible regs */ \ - {0xFCFFFFDA, 0x03FFFFFF}, /* all regs except yh,a0h,a1h */ \ - {0xFFFFFFFF, 0x03FFFFFF} /* all regs */ \ -} - - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) regno_reg_class(REGNO) - -/* The class value for index registers, and the one for base regs. */ - -#define INDEX_REG_CLASS NO_REGS -#define BASE_REG_CLASS Y_ADDR_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) \ - dsp16xx_reg_class_from_letter(C) - -#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \ - secondary_reload_class(CLASS, MODE, X) - -/* When defined, the compiler allows registers explicitly used in the - rtl to be used as spill registers but prevents the compiler from - extending the lifetime of these registers. */ - -#define SMALL_REGISTER_CLASSES 1 - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -/* A C expression which is nonzero if register REGNO is suitable for use - as a base register in operand addresses. It may be either a suitable - hard register or a pseudo register that has been allocated such a - hard register. - - On the 1610 the Y address pointers can be used as a base registers */ -#define REGNO_OK_FOR_BASE_P(REGNO) \ -(((REGNO) >= REG_R0 && (REGNO) < REG_R3 + 1) || ((unsigned) reg_renumber[REGNO] >= REG_R0 \ - && (unsigned) reg_renumber[REGNO] < REG_R3 + 1)) - -#define REGNO_OK_FOR_YBASE_P(REGNO) \ - (((REGNO) == REG_YBASE) || ((unsigned) reg_renumber[REGNO] == REG_YBASE)) - -#define REGNO_OK_FOR_INDEX_P(REGNO) 0 - -#ifdef ALL_16_BIT_REGISTERS -#define IS_32_BIT_REG(REGNO) 0 -#else -#define IS_32_BIT_REG(REGNO) \ - ((REGNO) == REG_A0 || (REGNO) == REG_A1 || (REGNO) == REG_Y || (REGNO) == REG_PROD) -#endif - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. - Also, we must ensure that a PLUS is reloaded either - into an accumulator or an address register. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) preferred_reload_class (X, CLASS) - -/* A C expression that places additional restrictions on the register - class to use when it is necessary to be able to hold a value of - mode MODE in a reload register for which class CLASS would - ordinarily be used. - - Unlike `PREFERRED_RELOAD_CLASS', this macro should be used when - there are certain modes that simply can't go in certain reload - classes. - - The value is a register class; perhaps CLASS, or perhaps another, - smaller class. - - Don't define this macro unless the target machine has limitations - which require the macro to do something nontrivial. */ - -#if 0 -#define LIMIT_RELOAD_CLASS(MODE, CLASS) dsp16xx_limit_reload_class (MODE, CLASS) -#endif - -/* A C expression for the maximum number of consecutive registers of class CLASS - needed to hold a value of mode MODE */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - class_max_nregs(CLASS, MODE) - -/* The letters 'I' through 'P' in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. - - For the 16xx, the following constraints are used: - 'I' requires a non-negative 16-bit value. - 'J' requires a non-negative 9-bit value - 'K' requires a constant 0 operand. - 'L' requires 16-bit value - 'M' 32-bit value -- low 16-bits zero - */ - -#define SMALL_INT(X) (SMALL_INTVAL (INTVAL (X))) -#define SMALL_INTVAL(I) ((unsigned) (I) < 0x10000) -#define SHORT_IMMEDIATE(X) (SHORT_INTVAL (INTVAL(X))) -#define SHORT_INTVAL(I) ((unsigned) (I) < 0x100) - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (SMALL_INTVAL(VALUE)) \ - : (C) == 'J' ? (SHORT_INTVAL(VALUE)) \ - : (C) == 'K' ? ((VALUE) == 0) \ - : (C) == 'L' ? ! ((VALUE) & ~0x0000ffff) \ - : (C) == 'M' ? ! ((VALUE) & ~0xffff0000) \ - : (C) == 'N' ? ((VALUE) == -1 || (VALUE) == 1 || \ - (VALUE) == -2 || (VALUE) == 2) \ - : 0) - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1 - -/* Optional extra constraints for this machine */ -#define EXTRA_CONSTRAINT(OP,C) \ - ((C) == 'R' ? symbolic_address_p (OP) \ - : 0) - -/* DESCRIBING STACK LAYOUT AND CALLING CONVENTIONS */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -/* #define STACK_GROWS_DOWNWARD */ - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -/* #define FRAME_GROWS_DOWNWARD */ - -#define ARGS_GROW_DOWNWARD - -/* We use post decrement on the 1600 because there isn't - a pre-decrement addressing mode. This means that we - assume the stack pointer always points at the next - FREE location on the stack. */ -#define STACK_PUSH_CODE POST_INC - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ -#define STARTING_FRAME_OFFSET 0 - -/* Offset from the stack pointer register to the first - location at which outgoing arguments are placed. */ -#define STACK_POINTER_OFFSET (0) - -struct dsp16xx_frame_info -{ - unsigned long total_size; /* # bytes that the entire frame takes up */ - unsigned long var_size; /* # bytes that variables take up */ - unsigned long args_size; /* # bytes that outgoing arguments take up */ - unsigned long extra_size; /* # bytes of extra gunk */ - unsigned int reg_size; /* # bytes needed to store regs */ - long fp_save_offset; /* offset from vfp to store registers */ - unsigned long sp_save_offset; /* offset from new sp to store registers */ - int initialized; /* != 0 if frame size already calculated */ - int num_regs; /* number of registers saved */ - int function_makes_calls; /* Does the function make calls */ -}; - -extern struct dsp16xx_frame_info current_frame_info; - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. */ -/* #define PUSH_ROUNDING(BYTES) ((BYTES)) */ - -/* If defined, the maximum amount of space required for outgoing - arguments will be computed and placed into the variable - 'current_function_outgoing_args_size'. No space will be pushed - onto the stack for each call; instead, the function prologue should - increase the stack frame size by this amount. - - It is not proper to define both 'PUSH_ROUNDING' and - 'ACCUMULATE_OUTGOING_ARGS'. */ -#define ACCUMULATE_OUTGOING_ARGS - -/* Offset of first parameter from the argument pointer - register value. */ - -#define FIRST_PARM_OFFSET(FNDECL) (0) - -/* Value is 1 if returning from a function call automatically - pops the arguments described by the number-of-args field in the call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. On the 1610 all function return their values - in a0 (i.e. the upper 16 bits). If the return value is 32-bits the - entire register is significant. */ - -#define VALUE_REGNO(MODE) (REG_Y) - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx_REG (TYPE_MODE (VALTYPE), VALUE_REGNO(TYPE_MODE(VALTYPE))) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ -#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, VALUE_REGNO(MODE)) - -/* 1 if N is a possible register number for a function value. */ -#define FUNCTION_VALUE_REGNO_P(N) ((N) == REG_Y) - - -/* Define where to put the arguments to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ - -/* On the 1610 all args are pushed, except if -mregparm is specified - then the first two words of arguments are passed in a0, a1. */ -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - dsp16xx_function_arg (CUM, MODE, TYPE, NAMED) - -/* Define the first register to be used for argument passing */ -#define FIRST_REG_FOR_FUNCTION_ARG REG_Y - -/* Define the profitability of saving registers around calls. - NOTE: For now we turn this off because of a bug in the - caller-saves code and also because i'm not sure it is helpful - on the 1610. */ - -#define CALLER_SAVE_PROFITABLE(REFS,CALLS) 0 - -/* This indicates that an argument is to be passed with an invisible reference - (i.e., a pointer to the object is passed). - - On the dsp16xx, we do this if it must be passed on the stack. */ - -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - (MUST_PASS_IN_STACK (MODE, TYPE)) - -/* For an arg passed partly in registers and partly in memory, - this is the number of registers used. - For args passed entirely in registers or entirely in memory, zero. */ - -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) (0) - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. */ -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) ((CUM) = 0) - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - dsp16xx_function_arg_advance (&CUM, MODE,TYPE, NAMED) - -/* 1 if N is a possible register number for function argument passing. */ -#define FUNCTION_ARG_REGNO_P(N) \ - ((N) == REG_Y || (N) == REG_YL || (N) == REG_PROD || (N) == REG_PRODL) - -/* This macro generates the assembly code for function entry. - FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - 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. */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) function_prologue(FILE, SIZE) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) fatal("Profiling not implemented yet.") - -/* Output assembler code to FILE to initialize this source file's - basic block profiling info, if that has not already been done. */ -#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) fatal("Profiling not implemented yet.") - -/* Output assembler code to FILE to increment the entry-count for - the BLOCKNO'th basic block in this source file. */ -#define BLOCK_PROFILER(FILE, BLOCKNO) fatal("Profiling not implemented yet.") - - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. */ - -#define EXIT_IGNORE_STACK (0) - -#define TRAMPOLINE_TEMPLATE(FILE) fatal ("Trampolines not yet implemented"); - -/* Length in units of the trampoline for entering a nested function. - This is a dummy value */ - -#define TRAMPOLINE_SIZE 20 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ - fatal ("Trampolines not yet implemented"); - -/* This macro generates the assembly code for function exit, - on machines that need it. If FUNCTION_EPILOGUE is not defined - then individual return instructions are generated for each - return statement. Args are same as for FUNCTION_PROLOGUE. - - The function epilogue should not depend on the current stack pointer! - It should use the frame pointer only. This is mandatory because - of alloca; we also take advantage of it to omit stack adjustments - before returning. */ - -#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue(FILE, SIZE) - -/* A C expression which is nonzero if a function must have and use a - frame pointer. If its value is nonzero the functions will have a - frame pointer. */ -#define FRAME_POINTER_REQUIRED (current_function_calls_alloca) - -/* A C statement to store in the variable 'DEPTH' the difference - between the frame pointer and the stack pointer values immediately - after the function prologue. */ -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ -{ (DEPTH) = initial_frame_pointer_offset(); \ -} - -/* IMPLICIT CALLS TO LIBRARY ROUTINES */ - -#define ADDHF3_LIBCALL "__Emulate_addhf3" -#define SUBHF3_LIBCALL "__Emulate_subhf3" -#define MULHF3_LIBCALL "__Emulate_mulhf3" -#define DIVHF3_LIBCALL "__Emulate_divhf3" -#define CMPHF3_LIBCALL "__Emulate_cmphf3" -#define FIXHFHI2_LIBCALL "__Emulate_fixhfhi2" -#define FLOATHIHF2_LIBCALL "__Emulate_floathihf2" -#define NEGHF2_LIBCALL "__Emulate_neghf2" - -#define UMULHI3_LIBCALL "__Emulate_umulhi3" -#define MULHI3_LIBCALL "__Emulate_mulhi3" -#define UDIVQI3_LIBCALL "__Emulate_udivqi3" -#define UDIVHI3_LIBCALL "__Emulate_udivhi3" -#define DIVQI3_LIBCALL "__Emulate_divqi3" -#define DIVHI3_LIBCALL "__Emulate_divhi3" -#define MODQI3_LIBCALL "__Emulate_modqi3" -#define MODHI3_LIBCALL "__Emulate_modhi3" -#define UMODQI3_LIBCALL "__Emulate_umodqi3" -#define UMODHI3_LIBCALL "__Emulate_umodhi3" -#define ASHRHI3_LIBCALL "__Emulate_ashrhi3" -#define LSHRHI3_LIBCALL "__Emulate_lshrhi3" -#define ASHLHI3_LIBCALL "__Emulate_ashlhi3" -#define LSHLHI3_LIBCALL "__Emulate_lshlhi3" /* NOT USED */ - -/* Define this macro if calls to the ANSI C library functions memcpy and - memset should be generated instead of the BSD function bcopy & bzero. */ -#define TARGET_MEM_FUNCTIONS - - -/* ADDRESSING MODES */ - -/* The 1610 has post-increment and decrement, but no pre-modify */ -#define HAVE_POST_INCREMENT 1 -#define HAVE_POST_DECREMENT 1 - -/* #define HAVE_PRE_DECREMENT 0 */ -/* #define HAVE_PRE_INCREMENT 0 */ - -/* Recognize any constant value that is a valid address. */ -#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) - -/* Maximum number of registers that can appear in a valid memory address. */ -#define MAX_REGS_PER_ADDRESS 1 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) 0 - -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) \ - ((REGNO (X) >= REG_R0 && REGNO (X) < REG_R3 + 1 ) \ - || (REGNO (X) >= FIRST_PSEUDO_REGISTER)) - -/* Nonzero if X is the 'ybase' register */ -#define REG_OK_FOR_YBASE_P(X) \ - (REGNO(X) == REG_YBASE || (REGNO (X) >= FIRST_PSEUDO_REGISTER)) -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) - -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -/* Nonzero if X is the 'ybase' register */ -#define REG_OK_FOR_YBASE_P(X) REGNO_OK_FOR_YBASE_P (REGNO(X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - On the 1610, the actual legitimate addresses must be N (N must fit in - 5 bits), *rn (register indirect), *rn++, or *rn-- */ - -#define INT_FITS_5_BITS(I) ((unsigned long) (I) < 0x20) -#define INT_FITS_16_BITS(I) ((unsigned long) (I) < 0x10000) -#define YBASE_CONST_OFFSET(I) ((I) >= -31 && (I) <= 0) -#define YBASE_OFFSET(X) (GET_CODE (X) == CONST_INT && YBASE_CONST_OFFSET (INTVAL(X))) - -#define FITS_16_BITS(X) (GET_CODE (X) == CONST_INT && INT_FITS_16_BITS(INTVAL(X))) -#define FITS_5_BITS(X) (GET_CODE (X) == CONST_INT && INT_FITS_5_BITS(INTVAL(X))) -#define ILLEGAL_HIMODE_ADDR(MODE, CONST) ((MODE) == HImode && CONST == -31) - -#define INDIRECTABLE_ADDRESS_P(X) \ - ((GET_CODE(X) == REG && REG_OK_FOR_BASE_P(X)) \ - || ((GET_CODE(X) == POST_DEC || GET_CODE(X) == POST_INC) \ - && REG_P(XEXP(X,0)) && REG_OK_FOR_BASE_P(XEXP(X,0))) \ - || (GET_CODE(X) == CONST_INT && (unsigned long) (X) < 0x20)) - - -#define INDEXABLE_ADDRESS_P(X,MODE) \ - ((GET_CODE(X) == PLUS && GET_CODE (XEXP (X,0)) == REG && \ - XEXP(X,0) == stack_pointer_rtx && YBASE_OFFSET(XEXP(X,1)) && \ - !ILLEGAL_HIMODE_ADDR(MODE, INTVAL(XEXP(X,1)))) || \ - (GET_CODE(X) == PLUS && GET_CODE (XEXP (X,1)) == REG && \ - XEXP(X,1) == stack_pointer_rtx && YBASE_OFFSET(XEXP(X,0)) && \ - !ILLEGAL_HIMODE_ADDR(MODE, INTVAL(XEXP(X,0))))) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - if (INDIRECTABLE_ADDRESS_P(X)) \ - goto ADDR; \ -} - - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. - - For the 1610, we need not do anything. However, if we don't, - `memory_address' will try lots of things to get a valid address, most of - which will result in dead code and extra pseudos. So we make the address - valid here. - - This is easy: The only valid addresses are an offset from a register - and we know the address isn't valid. So just call either `force_operand' - or `force_reg' unless this is a (plus (reg ...) (const_int 0)). */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -{ if (GET_CODE (X) == PLUS && XEXP (X, 1) == const0_rtx) \ - X = XEXP (x, 0); \ - if (GET_CODE (X) == MULT || GET_CODE (X) == PLUS) \ - X = force_operand (X, 0); \ - else \ - X = force_reg (Pmode, X); \ - goto WIN; \ -} - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. - On the 1610, only postdecrement and postincrement address depend thus - (the amount of decrement or increment being the length of the operand). */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ - if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == POST_DEC) goto LABEL - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ -#define LEGITIMATE_CONSTANT_P(X) (1) - - -/* CONDITION CODE INFORMATION */ - -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. */ - -#define NOTICE_UPDATE_CC(EXP, INSN) \ - notice_update_cc( (EXP) ) - -/* DESCRIBING RELATIVE COSTS OF OPERATIONS */ - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. */ -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - return 0; \ - case LABEL_REF: \ - case SYMBOL_REF: \ - case CONST: \ - return COSTS_N_INSNS (1); \ - \ - case CONST_DOUBLE: \ - return COSTS_N_INSNS (2); - -/* Like CONST_COSTS but applies to nonconstant RTL expressions. - This can be used, for example to indicate how costly a multiply - instruction is. */ -#define RTX_COSTS(X,CODE,OUTER_CODE) \ - case MEM: \ - return GET_MODE (X) == QImode ? COSTS_N_INSNS (2) : \ - COSTS_N_INSNS (4); \ - case DIV: \ - case MOD: \ - return COSTS_N_INSNS (38); \ - case MULT: \ - if (GET_MODE (X) == QImode) \ - return COSTS_N_INSNS (2); \ - else \ - return COSTS_N_INSNS (38); \ - case PLUS: \ - if (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \ - { \ - if (GET_CODE (XEXP (X,1)) == CONST_INT) \ - { \ - int number = INTVAL(XEXP (X,1)); \ - if (number == 1) \ - return COSTS_N_INSNS (1); \ - if (INT_FITS_16_BITS(number)) \ - return COSTS_N_INSNS (2); \ - else \ - return COSTS_N_INSNS (4); \ - } \ - return COSTS_N_INSNS (1); \ - } \ - else \ - return COSTS_N_INSNS (38); \ - case MINUS: \ - if (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \ - { \ - if (GET_CODE (XEXP (X,1)) == CONST_INT) \ - { \ - if (INT_FITS_16_BITS(INTVAL(XEXP(X,1)))) \ - return COSTS_N_INSNS (2); \ - else \ - return COSTS_N_INSNS (4); \ - } \ - return COSTS_N_INSNS (1); \ - } \ - else \ - return COSTS_N_INSNS (38); \ - case AND: case IOR: case XOR: \ - if (GET_CODE (XEXP (X,1)) == CONST_INT) \ - { \ - if (INT_FITS_16_BITS(INTVAL(XEXP(X,1)))) \ - return COSTS_N_INSNS (2); \ - else \ - return COSTS_N_INSNS (4); \ - } \ - return COSTS_N_INSNS (1); \ - case NEG: case NOT: \ - return COSTS_N_INSNS (1); \ - case ASHIFT: \ - case ASHIFTRT: \ - case LSHIFTRT: \ - if (GET_CODE (XEXP (X,1)) == CONST_INT) \ - { \ - int number = INTVAL(XEXP (X,1)); \ - if (number == 1 || number == 4 || number == 8 || \ - number == 16) \ - return COSTS_N_INSNS (1); \ - else \ - return COSTS_N_INSNS (2); \ - } \ - return COSTS_N_INSNS (1); - -/* An expression giving the cost of an addressing mode that contains - address. */ -#define ADDRESS_COST(ADDR) dsp16xx_address_cost (ADDR) - -/* A c expression for the cost of moving data from a register in - class FROM to one in class TO. The classes are expressed using - the enumeration values such as GENERAL_REGS. A value of 2 is - the default. */ -#define REGISTER_MOVE_COST(FROM,TO) dsp16xx_register_move_cost (FROM, TO) - -/* A C expression for the cost of moving data of mode MODE between - a register and memory. A value of 2 is the default. */ -#define MEMORY_MOVE_COST(MODE,CLASS,IN) \ - (GET_MODE_CLASS(MODE) == MODE_INT && MODE == QImode ? 12 \ - : 16) - -/* A C expression for the cost of a branch instruction. A value of - 1 is the default; */ -#define BRANCH_COST 2 - - -/* Define this because otherwise gcc will try to put the function address - in any old pseudo register. We can only use pt. */ -#define NO_FUNCTION_CSE - -/* Define this macro as a C expression which is nonzero if accessing less - than a word of memory (i.e a char or short) is no faster than accessing - a word of memory, i.e if such access require more than one instruction - or if ther is no difference in cost between byte and (aligned) word - loads. */ -#define SLOW_BYTE_ACCESS 1 - -/* Define this macro if zero-extension (of a char or short to an int) can - be done faster if the destination is a register that is know to be zero. */ -/* #define SLOW_ZERO_EXTEND */ - -/* Define this macro if unaligned accesses have a cost many times greater than - aligned accesses, for example if they are emulated in a trap handler */ -/* define SLOW_UNALIGNED_ACCESS */ - -/* Define this macro to inhibit strength reduction of memory addresses */ -/* #define DONT_REDUCE_ADDR */ - - -/* DIVIDING THE OUTPUT IN SECTIONS */ -/* Output before read-only data. */ - -#define DEFAULT_TEXT_SEG_NAME ".text" -#define TEXT_SECTION_ASM_OP rsect_text - -/* Output before constants and strings */ -#define DEFAULT_CONST_SEG_NAME ".const" -#define READONLY_SECTION_ASM_OP rsect_const -#define READONLY_DATA_SECTION const_section - -/* Output before writable data. */ -#define DEFAULT_DATA_SEG_NAME ".data" -#define DATA_SECTION_ASM_OP rsect_data - -#define DEFAULT_BSS_SEG_NAME ".bss" -#define BSS_SECTION_ASM_OP rsect_bss - -/* We will default to using 1610 if the user doesn't - specify it. */ -#define DEFAULT_CHIP_NAME "1610" - -/* A list of names for sections other than the standard ones, which are - 'in_text' and 'in_data' (and .bss if BSS_SECTION_ASM_OP is defined). */ -#define EXTRA_SECTIONS in_const - -#define EXTRA_SECTION_FUNCTIONS \ -void \ -const_section () \ -{ \ - if (in_section != in_const) \ - { \ - fprintf (asm_out_file, "%s\n", READONLY_SECTION_ASM_OP); \ - in_section = in_const; \ - } \ -} - -/* THE OVERALL FRAMEWORK OF AN ASSEMBLER FILE */ - -/* Output at beginning of assembler file. */ -#define ASM_FILE_START(FILE) dsp16xx_file_start () - -/* Prevent output of .gcc_compiled */ -#define ASM_IDENTIFY_GCC(FILE) - -/* A C string constant describing how to begin a comment in the target - assembler language. */ -/* define ASM_COMMENT_START */ - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ -#define ASM_APP_OFF "" - -/* OUTPUT OF DATA */ - -/* This is how to output an assembler line defining a `double' constant. */ -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) asm_output_float (FILE,VALUE) - -/* This is how to output an assembler line defining a `float' constant. */ -#define ASM_OUTPUT_FLOAT(FILE,VALUE) asm_output_float (FILE, VALUE) - -/* This is how to output an assembler line defining a 'float' constant of - size HFmode. */ -#define ASM_OUTPUT_SHORT_FLOAT(FILE,VALUE) asm_output_float (FILE, VALUE) - -/* This is how to output an assembler line defining an `char' constant. */ -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ -( fprintf (FILE, "\tint "), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "\n")) - -/* This is how to output an assembler line defining an `short' constant. */ -#define ASM_OUTPUT_SHORT(FILE,EXP) asm_output_long(FILE,INTVAL(EXP)) - -/* This is how to output an assembler line defining a 'int' constant. */ -#define ASM_OUTPUT_INT(FILE, EXP) asm_output_long(FILE,INTVAL(EXP)) - -/* This is how to output an assembler line for a numeric constant byte. */ -#define ASM_OUTPUT_BYTE(FILE,VALUE) \ - fprintf ((FILE), "\tint %ld\n", (long)(VALUE)) - - -/* This is how we output a 'c' character string. For the 16xx - assembler we have to do it one letter at a time */ - -#define ASCII_LENGTH 10 - -#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \ - do { \ - FILE *_hide_asm_out_file = (MYFILE); \ - unsigned char *_hide_p = (unsigned char *) (MYSTRING); \ - int _hide_thissize = (MYLENGTH); \ - { \ - FILE *asm_out_file = _hide_asm_out_file; \ - unsigned char *p = _hide_p; \ - int thissize = _hide_thissize; \ - int i; \ - \ - for (i = 0; i < thissize; i++) \ - { \ - register int c = p[i]; \ - \ - if (i % ASCII_LENGTH == 0) \ - fprintf (asm_out_file, "\tint "); \ - \ - if (c >= ' ' && c < 0177 && c != '\'') \ - { \ - putc ('\'', asm_out_file); \ - putc (c, asm_out_file); \ - putc ('\'', asm_out_file); \ - } \ - else \ - { \ - fprintf (asm_out_file, "%d", c); \ - /* After an octal-escape, if a digit follows, \ - terminate one string constant and start another. \ - The Vax assembler fails to stop reading the escape \ - after three digits, so this is the only way we \ - can get it to parse the data properly. \ - if (i < thissize - 1 \ - && p[i + 1] >= '0' && p[i + 1] <= '9') \ - fprintf (asm_out_file, "\'\n\tint \'"); \ - */ \ - } \ - /* if: \ - we are not at the last char (i != thissize -1) \ - and (we are not at a line break multiple \ - but i == 0) (it will be the very first time) \ - then put out a comma to extend. \ - */ \ - if ((i != thissize - 1) && ((i + 1) % ASCII_LENGTH)) \ - fprintf(asm_out_file, ","); \ - if (!((i + 1) % ASCII_LENGTH)) \ - fprintf (asm_out_file, "\n"); \ - } \ - fprintf (asm_out_file, "\n"); \ - } \ - } \ - while (0) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable or function - named NAME. LABELNO is an integer which is different for - each call. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ - do { \ - int len = strlen (NAME); \ - char *temp = (char *) alloca (len + 3); \ - temp[0] = 'L'; \ - strcpy (&temp[1], (NAME)); \ - temp[len + 1] = '_'; \ - temp[len + 2] = 0; \ - (OUTPUT) = (char *) alloca (strlen (NAME) + 11); \ - ASM_GENERATE_INTERNAL_LABEL (OUTPUT, temp, LABELNO); \ - } while (0) - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - - -/* OUTPUT OF UNINITIALIZED VARIABLES */ - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ - asm_output_common (FILE, NAME, SIZE, ROUNDED); - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ - asm_output_local (FILE, NAME, SIZE, ROUNDED); - -/* OUTPUT AND GENERATION OF LABELS */ - -/* This is how to output the definition of a user-level label named NAME, - such as the label on a static function or variable NAME. */ -#define ASM_OUTPUT_LABEL(FILE,NAME) \ - do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) - -/* This is how to output a command to make the user-level label named NAME - defined for reference from other files. */ - -#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ - do { fputs (".global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) - -/* A C statement to output to the stdio stream any text necessary - for declaring the name of an external symbol named name which - is referenced in this compilation but not defined. */ - -#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ -{ \ - fprintf (FILE, ".extern "); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ -} -/* A C statement to output on stream an assembler pseudo-op to - declare a library function named external. */ - -#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ -{ \ - fprintf (FILE, ".extern "); \ - assemble_name (FILE, XSTR (FUN, 0)); \ - fprintf (FILE, "\n"); \ -} - -/* The prefix to add to user-visible assembler symbols. */ - -#define USER_LABEL_PREFIX "_" - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ -#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - fprintf (FILE, "%s%d:\n", 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. - This is suitable for output with `assemble_name'. */ -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*%s%d", PREFIX, NUM) - - -/* OUTPUT OF ASSEMBLER INSTRUCTIONS */ - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{"a0", "a0l", "a1", "a1l", "x", "y", "yl", "p", "pl", \ - "r0", "r1", "r2", "r3", "j", "k", "ybase", "pt", \ - "ar0", "ar1", "ar2", "ar3", \ - "c0", "c1", "c2", "pr", "rb", \ - "*(0)", "*(1)", "*(2)", "*(3)", "*(4)", "*(5)", \ - "*(6)", "*(7)", "*(8)", "*(9)", "*(10)", "*(11)", \ - "*(12)", "*(13)", "*(14)", "*(15)", "*(16)", "*(17)", \ - "*(18)", "*(19)", "*(20)", "*(21)", "*(22)", "*(23)", \ - "*(24)", "*(25)", "*(26)", "*(27)", "*(28)", "*(29)", \ - "*(30)", "*(31)" } - -#define HIMODE_REGISTER_NAMES \ -{"a0", "a0", "a1", "a1", "x", "y", "y", "p", "p", \ - "r0", "r1", "r2", "r3", "j", "k", "ybase", "pt", \ - "ar0", "ar1", "ar2", "ar3", \ - "c0", "c1", "c2", "pr", "rb", \ - "*(0)", "*(1)", "*(2)", "*(3)", "*(4)", "*(5)", \ - "*(6)", "*(7)", "*(8)", "*(9)", "*(10)", "*(11)", \ - "*(12)", "*(13)", "*(14)", "*(15)", "*(16)", "*(17)", \ - "*(18)", "*(19)", "*(20)", "*(21)", "*(22)", "*(23)", \ - "*(24)", "*(25)", "*(26)", "*(27)", "*(28)", "*(29)", \ - "*(30)", "*(31)" } - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) 0 - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. - - DSP1610 extensions for operand codes: - - %H - print lower 16 bits of constant - %U - print upper 16 bits of constant - %w - print low half of register (e.g 'a0l') - %u - print upper half of register (e.g 'a0') - %b - print high half of accumulator for F3 ALU instructions - %h - print constant in decimal */ - -#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE, X, CODE) - - -/* Print a memory address as an operand to reference that memory location. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code since it is used only for profiling */ -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) fatal("Profiling not implemented yet."); - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code since it is used only for profiling */ -#define ASM_OUTPUT_REG_POP(FILE,REGNO) fatal("Profiling not implemented yet."); - -/* OUTPUT OF DISPATCH TABLES */ - -/* This macro should be provided on machines where the addresses in a dispatch - table are relative to the table's own address. */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\tint L%d-L%d\n", VALUE, REL) - -/* This macro should be provided on machines where the addresses in a dispatch - table are absolute. */ -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\tint L%d\n", VALUE) - -/* ASSEMBLER COMMANDS FOR ALIGNMENT */ - -/* This is how to output an assembler line that says to advance - the location counter to a multiple of 2**LOG bytes. We should - not have to do any alignment since the 1610 is a word machine. */ -#define ASM_OUTPUT_ALIGN(FILE,LOG) - -/* Define this macro if ASM_OUTPUT_SKIP should not be used in the text section - because it fails to put zero1 in the bytes that are skipped. */ -#define ASM_NO_SKIP_IN_TEXT 1 - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t%d * int 0\n", (SIZE)) - -/* CONTROLLING DEBUGGING INFORMATION FORMAT */ - -/* Define this macro if GCC should produce COFF-style debugging output - for SDB in response to the '-g' option */ -#define SDB_DEBUGGING_INFO - -/* Support generating stabs for the listing file generator */ -#define DBX_DEBUGGING_INFO - -/* The default format when -g is given is still COFF debug info */ -#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* MISCELLANEOUS PARAMETERS */ - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE QImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE 1 */ - -/* Specify the tree operation to be used to convert reals to integers. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* This is the kind of divide that is easiest to do in the general case. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 1 - -/* Defining this macro causes the compiler to omit a sign-extend, zero-extend, - or bitwise 'and' instruction that truncates the count of a shift operation - to a width equal to the number of bits needed to represent the size of the - object being shifted. Do not define this macro unless the truncation applies - to both shift operations and bit-field operations (if any). */ -/* #define SHIFT_COUNT_TRUNCATED */ - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* When a prototype says `char' or `short', really pass an `int'. */ -#define PROMOTE_PROTOTYPES - -/* An alias for the machine mode used for pointers */ -#define Pmode QImode - -/* A function address in a call instruction - is a byte address (for indexing purposes) - so give the MEM rtx a byte's mode. */ -#define FUNCTION_MODE QImode - -#if !defined(__DATE__) -#define TARGET_VERSION fprintf (stderr, " (%s)", VERSION_INFO1) -#else -#define TARGET_VERSION fprintf (stderr, " (%s, %s)", VERSION_INFO1, __DATE__) -#endif - -#define VERSION_INFO1 "AT&T DSP16xx C Cross Compiler, version 1.2.0" - - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* If this macro is defined, GNU CC gathers statistics about the number and - kind of tree node it allocates during each run. The option '-fstats' will - tell the compiler to print these statistics about the sizes of it obstacks. */ -#define GATHER_STATISTICS - -/* Define this so gcc does not output a call to __main, since we - are not currently supporting c++. */ -#define INIT_SECTION_ASM_OP 1 diff --git a/gcc/config/dsp16xx/dsp16xx.md b/gcc/config/dsp16xx/dsp16xx.md deleted file mode 100755 index 9923178..0000000 --- a/gcc/config/dsp16xx/dsp16xx.md +++ /dev/null @@ -1,2171 +0,0 @@ -;;- Machine description for the AT&T DSP1600 for GNU C compiler -;; Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. -;; Contributed by Michael Collison (collison@world.std.com). - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; Attribute specifications - -; Type of each instruction. Default is arithmetic. -; I'd like to write the list as this, but genattrtab won't accept it. -; -; "jump,cond_jump,call, ; flow-control instructions -; load_i,load, store, move ; Y space address arithmetic instructions -; malu,special,f3_alu,f3_alu_i ; data arithmetic unit instructions -; shift_i,shift, bfield_i, bfield ; bit manipulation unit instructions -; arith, ; integer unit instructions -; nop - -; Classification of each insn. Some insns of TYPE_BRANCH are multi-word. -(define_attr "type" - "jump,cond_jump,call,load_i,load,move,store,malu,malu_mul,special,f3_alu,f3_alu_i,shift_i,shift,bfield_i,bfield,nop,ld_short_i" - (const_string "malu")) - -; Length in # of instructions of each insn. The values are not exact, but -; are safe. -(define_attr "length" "" - (cond [(eq_attr "type" "cond_jump,f3_alu_i,shift_i,bfield_i,load_i") - (const_int 2)] - (const_int 1))) - - -;; .................... -;; -;; Test against 0 instructions -;; -;; .................... - -(define_expand "tsthi" - [(set (cc0) - (match_operand:HI 0 "register_operand" ""))] - "" - " -{ - dsp16xx_compare_gen = gen_tst_reg; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = const0_rtx; - DONE; -}") - -(define_insn "tsthi_1" - [(set (cc0) - (match_operand:HI 0 "register_operand" "A"))] - "" - "%0=%0" - [(set_attr "type" "malu")]) - -(define_expand "tstqi" - [(set (cc0) - (match_operand:QI 0 "register_operand" ""))] - "" - " -{ - dsp16xx_compare_gen = gen_tst_reg; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = const0_rtx; - DONE; -}") - -(define_insn "tstqi_1" - [(set (cc0) - (match_operand:QI 0 "register_operand" "j,q")) - (clobber (match_scratch:QI 1 "=k,u"))] - "" - "@ - %1=0\;%b0-0 - %1=0\;%b0-0" - [(set_attr "type" "malu,malu")]) - - -;; -;; .................... -;; -;; Bit test instructions -;; -;; .................... - -(define_insn "" - [(set (cc0) - (and:HI (match_operand:HI 0 "register_operand" "A,!A,A") - (match_operand:HI 1 "nonmemory_operand" "Z,A,I")))] - "" - "* -{ - switch (which_alternative) - { - case 0: - case 1: - return \"%0&%1\"; - - case 2: - return \"%0&%H1\"; - } -}" - [(set_attr "type" "f3_alu,malu,f3_alu_i")]) - - -;;(define_insn "" -;; [(set (cc0) -;; (and:QI (match_operand:QI 0 "register_operand" "h") -;; (match_operand:QI 1 "const_int_operand" "I")))] -;; "" -;; "%b0&%H1" -;; [(set_attr "type" "f3_alu_i")]) - -;; -;; -;; Compare Instructions -;; - -(define_expand "cmphi" - [(parallel [(set (cc0) - (compare (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 "")) - (clobber (match_scratch:QI 4 "")) - (clobber (match_scratch:QI 5 ""))])] - "" - " -{ - if (GET_CODE (operands[1]) == CONST_INT) - operands[1] = force_reg (HImode, operands[1]); - - dsp16xx_compare_gen = gen_compare_reg; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = operands[1]; - DONE; -}") - -(define_insn "" - [(set (cc0) - (compare (match_operand:HI 0 "general_operand" "Z*r*m*i") - (match_operand:HI 1 "general_operand" "Z*r*m*i"))) - (clobber (match_scratch:QI 2 "=&A")) - (clobber (match_scratch:QI 3 "=&A")) - (clobber (match_scratch:QI 4 "=&A")) - (clobber (match_scratch:QI 5 "=&A"))] - "next_cc_user_unsigned (insn)" - "* -{ - if (GET_CODE(operands[0]) == REG) - { - if (REGNO (operands[0]) == REG_Y || - REGNO (operands[0]) == REG_PROD) - { - output_asm_insn (\"a0=%0\", operands); - } - else if (IS_YBASE_REGISTER_WINDOW (REGNO(operands[0]))) - { - output_asm_insn (\"a0=%u0\;a0l=%w0\", operands); - } - else - fatal (\"Invalid register for compare\"); - } - else if (GET_CODE(operands[0]) == CONST_INT) - { - output_asm_insn (\"a0=%U0\;a0l=%H0\", operands); - } - else if (GET_CODE (operands[0]) == MEM) - { - rtx xoperands[2]; - - xoperands[0] = gen_rtx_REG (HImode, REG_A0); - xoperands[1] = operands[0]; - double_reg_from_memory (xoperands); - } - - if (GET_CODE(operands[1]) == REG) - { - if (REGNO (operands[1]) == REG_Y || - REGNO (operands[1]) == REG_PROD) - { - output_asm_insn (\"a1=%1\", operands); - } - else if (IS_YBASE_REGISTER_WINDOW (REGNO(operands[1]))) - { - output_asm_insn (\"a1=%u1\;a1l=%w1\", operands); - } - else - fatal (\"Invalid register for compare\"); - } - else if (GET_CODE (operands[1]) == MEM) - { - rtx xoperands[2]; - - xoperands[0] = gen_rtx_REG (HImode, REG_A1); - xoperands[1] = operands[1]; - double_reg_from_memory (xoperands); - } - else if (GET_CODE(operands[1]) == CONST_INT) - { - output_asm_insn (\"a1=%U1\;a1l=%H1\", operands); - } - - return \"psw = 0\;a0 - a1\"; -}") - -(define_insn "" - [(set (cc0) (compare (match_operand:HI 0 "register_operand" "A,!A") - (match_operand:HI 1 "register_operand" "Z,*A")))] - "" - "@ - %0-%1 - %0-%1" - [(set_attr "type" "malu,f3_alu")]) - -(define_expand "cmpqi" - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "") - (match_operand:QI 1 "nonmemory_operand" ""))) - (clobber (match_operand:QI 2 "register_operand" "")) - (clobber (match_operand:QI 3 "register_operand" ""))])] - "" - " - { - if (operands[0]) /* Avoid unused code warning */ - { - dsp16xx_compare_gen = gen_compare_reg; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = operands[1]; - DONE; - } - }") - -(define_insn "" - [(set (cc0) (compare (match_operand:QI 0 "register_operand" "k,k,!k,k,u,u,!u,u") - (match_operand:QI 1 "nonmemory_operand" "w,z,u,i,w,z,k,i"))) - (clobber (match_scratch:QI 2 "=j,j,j,j,q,q,q,q")) - (clobber (match_scratch:QI 3 "=v,y,q,X,v,y,j,X"))] - "next_cc_user_unsigned (insn)" - "@ - %2=0\;%3=0\;%2-%3 - %2=0\;%3=0\;%2-%3 - %2=0\;%3=0\;%2-%3 - %2=0\;%0-%H1 - %2=0\;%3=0\;%2-%3 - %2=0\;%3=0\;%2-%3 - %2=0\;%3=0\;%2-%3 - %2=0\;%0-%H1") - - -(define_insn "" - [(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,j,!j,j,q,q,!q,q") - (match_operand:QI 1 "nonmemory_operand" "v,y,q,i,v,y,j,i"))) - (clobber (match_scratch:QI 2 "=k,k,k,k,u,u,u,u")) - (clobber (match_scratch:QI 3 "=w,z,u,X,w,z,k,X"))] - "" - "@ - %2=0\;%3=0\;%0-%1 - %2=0\;%3=0\;%0-%1 - %2=0\;%3=0\;%0-%1 - %2=0\;%b0-%H1 - %2=0\;%3=0\;%0-%1 - %2=0\;%3=0\;%0-%1 - %2=0\;%3=0\;%0-%1 - %2=0\;%b0-%H1") - - -(define_expand "cmphf" - [(set (cc0) - (compare (match_operand:HF 0 "register_operand" "") - (match_operand:HF 1 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_cmphf3_libcall) - dsp16xx_cmphf3_libcall = gen_rtx_SYMBOL_REF (Pmode, CMPHF3_LIBCALL); - - dsp16xx_compare_gen = gen_compare_reg; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = operands[1]; - emit_library_call (dsp16xx_cmphf3_libcall, 1, HImode, 2, - operands[0], HFmode, - operands[1], HFmode); - emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode)))); - DONE; -}") - - -;; .................... -;; -;; Add instructions -;; -;; .................... - - -(define_insn "addhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A") - (plus:HI (match_operand:HI 1 "register_operand" "%A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,d,i")))] - "" - "@ - %0=%1+%2 - %0=%1+%2 - %0=%w1+%H2\;%0=%b0+%U2" - [(set_attr "type" "malu,malu,f3_alu_i")]) - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u") - (plus:QI (plus:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk") - (match_operand:QI 2 "register_operand" "wz,wz,uk,uk")) - (match_operand:QI 3 "immediate_operand" "i,i,i,i"))) - (clobber (match_scratch:QI 4 "=j,q,j,q"))] - "" - "@ - %m0=%m1+%m2\;%m0=%0+%H3 - %m0=%m1+%m2\;%m0=%0+%H3 - %m0=%m1+%m2\;%m0=%0+%H3 - %m0=%m1+%m2\;%m0=%0+%H3") - -(define_expand "addqi3" - [(parallel [(set (match_operand:QI 0 "register_operand" "") - (plus:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (match_scratch:QI 3 ""))])] - "" - " -{ - if (reload_in_progress) - { - if (REG_P (operands[1]) && - (REGNO(operands[1]) == STACK_POINTER_REGNUM || - REGNO(operands[1]) == FRAME_POINTER_REGNUM) && - GET_CODE (operands[2]) == CONST_INT) - { - if (REG_P (operands[0]) && IS_ACCUM_REG(REGNO(operands[0]))) - emit_move_insn (operands[0], operands[1]); - - operands[1] = operands[0]; - } - } -}") - - -(define_insn "match_addqi3" - [(set (match_operand:QI 0 "register_operand" "=!a,!a,k,u,!k,!u,h,!a") - (plus:QI (match_operand:QI 1 "register_operand" "0,0,uk,uk,uk,uk,h,0") - (match_operand:QI 2 "nonmemory_operand" "W,N,wzi,wzi,uk,uk,i,n"))) - (clobber (match_scratch:QI 3 "=X,X,j,q,j,q,X,W"))] - "" - "* -{ - switch (which_alternative) - { - case 0: - return \"*%0++%2\"; - - case 1: - switch (INTVAL (operands[2])) - { - case -1: - return \"*%0--\"; - - case 1: - return \"*%0++\"; - - case -2: - return \"*%0--\;*%0--\"; - - case 2: - return \"*%0++\;*%0++\"; - } - - case 2: - case 3: - if (!CONSTANT_P(operands[2])) - return \"%m0=%m1+%m2\"; - else - return \"%m0=%1+%H2\"; - - case 4: - case 5: - return \"%m0=%m1+%m2\"; - - case 6: - return \"%0=%b1+%H2\"; - - case 7: - return \"%3=%2\;*%0++%3\"; - } -}") - -(define_expand "addhf3" - [(set (match_operand:HF 0 "register_operand" "") - (plus:HF (match_operand:HF 1 "register_operand" "") - (match_operand:HF 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_addhf3_libcall) - dsp16xx_addhf3_libcall = gen_rtx_SYMBOL_REF (Pmode, ADDHF3_LIBCALL); - - emit_library_call (dsp16xx_addhf3_libcall, 1, HFmode, 2, - operands[1], HFmode, - operands[2], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - - -;; -;; .................... -;; -;; Subtract instructions -;; -;; .................... - -(define_insn "subhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A") - (minus:HI (match_operand:HI 1 "register_operand" "A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,d,i")))] - "" - "@ - %0=%1-%2 - %0=%1-%2 - %0=%w1-%H2\;%0=%b0-%U2" - [(set_attr "type" "malu,malu,f3_alu_i")]) - -(define_insn "subqi3" - [(set (match_operand:QI 0 "register_operand" "=?*a,k,u,!k,!u") - (minus:QI (match_operand:QI 1 "register_operand" "0,uk,uk,uk,uk") - (match_operand:QI 2 "nonmemory_operand" "n,wzi,wzi,uk,uk"))) - (clobber (match_scratch:QI 3 "=W,j,q,j,q"))] - "" - "* -{ - switch (which_alternative) - { - case 0: - switch (INTVAL (operands[2])) - { - case 0: - return \"\"; - - case 1: - return \"*%0--\"; - - case -1: - return \"*%0++\"; - - default: - operands[2] = GEN_INT (-INTVAL (operands[2])); - - if (SHORT_IMMEDIATE(operands[2])) - return \"set %3=%H2\;*%0++%3\"; - else - return \"%3=%H2\;*%0++%3\"; - } - - case 1: - case 2: - if (!CONSTANT_P(operands[2])) - return \"%m0=%m1-%m2\"; - else - return \"%m0=%1-%H2\"; - - case 3: - case 4: - return \"%m0=%m1-%m2\"; - } -}") - -(define_expand "subhf3" - [(set (match_operand:HF 0 "register_operand" "") - (minus:HF (match_operand:HF 1 "register_operand" "") - (match_operand:HF 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_subhf3_libcall) - dsp16xx_subhf3_libcall = gen_rtx_SYMBOL_REF (Pmode, SUBHF3_LIBCALL); - - emit_library_call (dsp16xx_subhf3_libcall, 1, HFmode, 2, - operands[1], HFmode, - operands[2], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - -(define_insn "neghi2" - [(set (match_operand:HI 0 "register_operand" "=A") - (neg:HI (match_operand:HI 1 "register_operand" "A")))] - "" - "%0=-%1" - [(set_attr "type" "special")]) - -(define_expand "neghf2" - [(set (match_operand:HF 0 "general_operand" "") - (neg:HF (match_operand:HF 1 "general_operand" "")))] - "" -" -{ - if (!dsp16xx_neghf2_libcall) - dsp16xx_neghf2_libcall = gen_rtx_SYMBOL_REF (Pmode, NEGHF2_LIBCALL); - - emit_library_call (dsp16xx_neghf2_libcall, 1, HFmode, 1, - operands[1], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - - - -;; -;; .................... -;; -;; Multiply instructions -;; - -(define_expand "mulhi3" - [(set (match_operand:HI 0 "register_operand" "") - (mult:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_mulhi3_libcall) - dsp16xx_mulhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, MULHI3_LIBCALL); - - emit_library_call (dsp16xx_mulhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_insn "mulqi3" - [(set (match_operand:QI 0 "register_operand" "=w") - (mult:QI (match_operand:QI 1 "register_operand" "%x") - (match_operand:QI 2 "register_operand" "y"))) - (clobber (match_scratch:QI 3 "=v"))] - "" - "%m0=%1*%2" - [(set_attr "type" "malu_mul")]) - -(define_insn "mulqihi3" - [(set (match_operand:HI 0 "register_operand" "=t") - (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%x")) - (sign_extend:HI (match_operand:QI 2 "register_operand" "y"))))] - "" - "%0=%1*%2" - [(set_attr "type" "malu_mul")]) - -(define_insn "umulqihi3" - [(set (match_operand:HI 0 "register_operand" "=t") - (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%x")) - (zero_extend:HI (match_operand:QI 2 "register_operand" "y"))))] - "" - "%0=%1*%2" - [(set_attr "type" "malu_mul")]) - -(define_expand "mulhf3" - [(set (match_operand:HF 0 "register_operand" "") - (mult:HF (match_operand:HF 1 "register_operand" "") - (match_operand:HF 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_mulhf3_libcall) - dsp16xx_mulhf3_libcall = gen_rtx_SYMBOL_REF (Pmode, MULHF3_LIBCALL); - - emit_library_call (dsp16xx_mulhf3_libcall, 1, HFmode, 2, - operands[1], HFmode, - operands[2], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - - - -;; -;; ******************* -;; -;; Divide Instructions -;; - -(define_expand "divhi3" - [(set (match_operand:HI 0 "register_operand" "") - (div:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_divhi3_libcall) - dsp16xx_divhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, DIVHI3_LIBCALL); - - emit_library_call (dsp16xx_divhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "udivhi3" - [(set (match_operand:HI 0 "register_operand" "") - (udiv:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_udivhi3_libcall) - dsp16xx_udivhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, UDIVHI3_LIBCALL); - - emit_library_call (dsp16xx_udivhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "divqi3" - [(set (match_operand:QI 0 "register_operand" "") - (div:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_divqi3_libcall) - dsp16xx_divqi3_libcall = gen_rtx_SYMBOL_REF (Pmode, DIVQI3_LIBCALL); - - emit_library_call (dsp16xx_divqi3_libcall, 1, QImode, 2, - operands[1], QImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(QImode)); - DONE; -}") - -(define_expand "udivqi3" - [(set (match_operand:QI 0 "register_operand" "") - (udiv:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_udivqi3_libcall) - dsp16xx_udivqi3_libcall = gen_rtx_SYMBOL_REF (Pmode, UDIVQI3_LIBCALL); - - emit_library_call (dsp16xx_udivqi3_libcall, 1, QImode, 2, - operands[1], QImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(QImode)); - DONE; -}") - -;; -;; .................... -;; -;; Modulo instructions -;; -;; .................... - -(define_expand "modhi3" - [(set (match_operand:HI 0 "register_operand" "") - (mod:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_modhi3_libcall) - dsp16xx_modhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, MODHI3_LIBCALL); - - emit_library_call (dsp16xx_modhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "umodhi3" - [(set (match_operand:HI 0 "register_operand" "") - (umod:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_umodhi3_libcall) - dsp16xx_umodhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, UMODHI3_LIBCALL); - - emit_library_call (dsp16xx_umodhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "modqi3" - [(set (match_operand:QI 0 "register_operand" "") - (mod:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_modqi3_libcall) - dsp16xx_modqi3_libcall = gen_rtx_SYMBOL_REF (Pmode, MODQI3_LIBCALL); - - emit_library_call (dsp16xx_modqi3_libcall, 1, QImode, 2, - operands[1], QImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(QImode)); - DONE; -}") - -(define_expand "umodqi3" - [(set (match_operand:QI 0 "register_operand" "") - (umod:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_umodqi3_libcall) - dsp16xx_umodqi3_libcall = gen_rtx_SYMBOL_REF (Pmode, UMODQI3_LIBCALL); - - emit_library_call (dsp16xx_umodqi3_libcall, 1, QImode, 2, - operands[1], QImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(QImode)); - DONE; -}") - -(define_expand "divhf3" - [(set (match_operand:HF 0 "register_operand" "") - (div:HF (match_operand:HF 1 "register_operand" "") - (match_operand:HF 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_divhf3_libcall) - dsp16xx_divhf3_libcall = gen_rtx_SYMBOL_REF (Pmode, DIVHF3_LIBCALL); - - emit_library_call (dsp16xx_divhf3_libcall, 1, HFmode, 2, - operands[1], HFmode, - operands[2], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - - - -;; -;; ******************** -;; -;; Logical Instructions -;; - -(define_insn "andhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,?A") - (and:HI (match_operand:HI 1 "register_operand" "%A,!A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,A,i")))] - "" - "@ - %0=%1&%2 - %0=%1&%2 - %0=%w1&%H2\;%0=%b0&%U2" - [(set_attr "type" "f3_alu,f3_alu,f3_alu_i")]) - -(define_insn "andqi3" - [(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q") - (and:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk,uk,jq,jq,jq,jq,jq") - (match_operand:QI 2 "nonmemory_operand" "wz,wz,i,uk,uk,yv,yv,i,jq,jq"))) - (clobber (match_scratch:QI 3 "=j,q,X,j,q,k,u,X,k,u"))] - "" - "@ - %m0=%m1&%m2 - %m0=%m1&%m2 - %m0=%1&%H2 - %m0=%m1&%m2 - %m0=%m1&%m2 - %m0=%m1&%m2 - %m0=%m1&%m2 - %m0=%b1&%H2 - %m0=%m1&%m2 - %m0=%m1&%m2") - -(define_insn "iorhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A,?A") - (ior:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,A,I,i")))] - "" - "@ - %0=%u1|%u2 - %0=%u1|%u2 - %0=%w1|%H2 - %0=%w1|%H2\;%0=%b0|%U2" - [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i")]) - -(define_insn "iorqi3" - [(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q") - (ior:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk,uk,jq,jq,jq,jq,jq") - (match_operand:QI 2 "nonmemory_operand" "wz,wz,i,uk,uk,yv,yv,i,jq,jq"))) - (clobber (match_scratch:QI 3 "=j,q,X,j,q,k,u,X,k,u"))] - "" - "@ - %m0=%m1|%m2 - %m0=%m1|%m2 - %m0=%1|%H2 - %m0=%m1|%m2 - %m0=%m1|%m2 - %m0=%m1|%m2 - %m0=%m1|%m2 - %m0=%b1|%H2 - %m0=%m1|%m2 - %m0=%m1|%m2") - -(define_insn "xorhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A,?A") - (xor:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,A,I,i")))] - "" - "@ - %0=%1^%2 - %0=%1^%2 - %0=%w1^%H2 - %0=%w1^%H2\;%0=%b0^%U2" - [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i")]) - -(define_insn "xorqi3" - [(set (match_operand:QI 0 "register_operand" "=k,u,uk,!k,!u,j,q,jq,!j,!q") - (xor:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk,uk,jq,jq,jq,jq,jq") - (match_operand:QI 2 "nonmemory_operand" "wz,wz,i,uk,uk,yv,yv,i,jq,jq"))) - (clobber (match_scratch:QI 3 "=j,q,X,j,q,k,u,X,k,u"))] - "" - "@ - %m0=%m1^%m2 - %m0=%m1^%m2 - %m0=%1^%H2 - %m0=%m1^%m2 - %m0=%m1^%m2 - %m0=%m1^%m2 - %m0=%m1^%m2 - %m0=%b1^%H2 - %m0=%m1^%m2 - %m0=%m1^%m2") - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "register_operand" "=A") - (not:HI (match_operand:HI 1 "register_operand" "A")))] - "" - "%0= ~%1" - [(set_attr "type" "special")]) - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "register_operand" "=ku,jq") - (not:QI (match_operand:QI 1 "register_operand" "ku,jq")))] - "" - "@ - %m0= %1 ^ 0xffff - %m0= %b1 ^ 0xffff" - [(set_attr "type" "special")]) - - -;; -;; MOVE INSTRUCTIONS -;; - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, HImode)) - DONE; -}") - - -(define_insn "match_movhi1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=A,Z,A,d,d,m,?d,*Y,t,f") - (match_operand:HI 1 "general_operand" "d,A,K,i,m,d,*Y,?d,t,f"))] - "register_operand(operands[0], HImode) - || register_operand(operands[1], HImode)" - "* -{ - switch (which_alternative) - { - /* register to accumulator */ - case 0: - return \"%0=%1\"; - case 1: - return \"%u0=%u1\;%w0=%w1\"; - case 2: - return \"%0=%0^%0\"; - case 3: - return \"%u0=%U1\;%w0=%H1\"; - case 4: - double_reg_from_memory(operands); - return \"\"; - case 5: - double_reg_to_memory(operands); - return \"\"; - case 6: - case 7: - return \"%u0=%u1\;%w0=%w1\"; - case 8: - case 9: - return \"\"; - } -}" -[(set_attr "type" "move,move,load_i,load_i,load,store,load,store,move,move")]) - - -;; NOTE: It is cheaper to do 'y = *r0', than 'r0 = *r0'. - -(define_expand "movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, QImode)) - DONE; -}") - -;; The movqi pattern with the parallel is used for addqi insns (which have a parallel) -;; that are turned into moveqi insns by the flow phase. This happens when a auto-increment -;; is detected. - -(define_insn "match_movqi1" - [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "=A,r,aW,c,?D,m<>,e,Y,r,xyz,m<>") - (match_operand:QI 1 "general_operand" "r,A,J,i,m<>,D,Y,e,0,m<>,xyz")) - (clobber (match_scratch:QI 2 "=X,X,X,X,X,X,X,X,X,X,X"))])] - "register_operand(operands[0], QImode) - || register_operand(operands[1], QImode)" - "* -{ - switch (which_alternative) - { - case 0: - /* We have to use the move mnemonic otherwise the 1610 will - attempt to transfer all 32-bits of 'y', 'p' or an accumulator - , which we don't want */ - if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD - || IS_ACCUM_REG(REGNO(operands[1]))) - return \"move %0=%1\"; - else - return \"%0=%1\"; - - case 1: - return \"%0=%1\"; - - case 2: - return \"set %0=%H1\"; - - case 3: - return \"%0=%H1\"; - - case 4: - return \"%0=%1\"; - - case 5: - case 6: - return \"%0=%1\"; - - case 7: - return \"%0=%1\"; - - case 8: - return \"\"; - - case 9: case 10: - return \"%0=%1\"; - } -}") - -(define_insn "match_movqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=A,r,aW,c,?D,m<>,e,Y,r,xyz,m<>") - (match_operand:QI 1 "general_operand" "r,A,J,i,m<>,D,Y,e,0,m<>,xyz"))] - "register_operand(operands[0], QImode) - || register_operand(operands[1], QImode)" - "* -{ - switch (which_alternative) - { - case 0: - /* We have to use the move mnemonic otherwise the 1610 will - attempt to transfer all 32-bits of 'y', 'p' or an accumulator - , which we don't want */ - if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD - || IS_ACCUM_REG(REGNO(operands[1]))) - return \"move %0=%1\"; - else - return \"%0=%1\"; - - case 1: - return \"%0=%1\"; - - case 2: - return \"set %0=%H1\"; - - case 3: - return \"%0=%H1\"; - - case 4: - return \"%0=%1\"; - - case 5: - case 6: - return \"%0=%1\"; - - case 7: - return \"%0=%1\"; - - case 8: - return \"\"; - - case 9: case 10: - return \"%0=%1\"; - } -}") - -(define_expand "reload_inqi" - [(set (match_operand:QI 0 "register_operand" "=u") - (match_operand:QI 1 "sp_operand" "")) - (clobber (match_operand:QI 2 "register_operand" "=&q"))] - "" - " -{ - rtx addr_reg = XEXP (operands[1], 0); - rtx offset = XEXP (operands[1], 1); - - /* First, move the frame or stack pointer to the accumulator */ - emit_move_insn (operands[0], addr_reg); - - /* Then generate the add insn */ - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, - gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (PLUS, QImode, operands[0], offset)), - gen_rtx (CLOBBER, VOIDmode, operands[2])))); - DONE; -}") - -(define_expand "reload_inhi" - [(set (match_operand:HI 0 "register_operand" "=r") - (match_operand:HI 1 "register_operand" "r")) - (clobber (match_operand:QI 2 "register_operand" "=&h"))] - "" - " -{ - /* Check for an overlap of operand 2 (an accumulator) with - the msw of operand 0. If we have an overlap we must reverse - the order of the moves. */ - - if (REGNO(operands[2]) == REGNO(operands[0])) - { - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HImode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HImode), operands[2]); - } - else - { - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HImode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HImode), operands[2]); - } - - DONE; -}") - - -(define_expand "reload_outhi" - [(set (match_operand:HI 0 "register_operand" "=r") - (match_operand:HI 1 "register_operand" "r")) - (clobber (match_operand:QI 2 "register_operand" "=&h"))] - "" - " -{ - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HImode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HImode), operands[2]); - DONE; -}") - -(define_expand "movstrqi" - [(parallel [(set (match_operand:BLK 0 "memory_operand" "") - (match_operand:BLK 1 "memory_operand" "")) - (use (match_operand:QI 2 "const_int_operand" "")) - (use (match_operand:QI 3 "const_int_operand" "")) - (clobber (match_scratch:QI 4 "")) - (clobber (match_dup 5)) - (clobber (match_dup 6))])] - "" - " -{ - rtx addr0, addr1; - - if (GET_CODE (operands[2]) != CONST_INT) - FAIL; - - if (INTVAL(operands[2]) > 127) - FAIL; - - addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - - operands[5] = addr0; - operands[6] = addr1; - - operands[0] = change_address (operands[0], VOIDmode, addr0); - operands[1] = change_address (operands[1], VOIDmode, addr1); -}") - -(define_insn "" - [(set (mem:BLK (match_operand:QI 0 "register_operand" "a")) - (mem:BLK (match_operand:QI 1 "register_operand" "a"))) - (use (match_operand:QI 2 "const_int_operand" "n")) - (use (match_operand:QI 3 "immediate_operand" "i")) - (clobber (match_scratch:QI 4 "=x")) - (clobber (match_dup 0)) - (clobber (match_dup 1))] - "" - "* -{ return output_block_move (operands); }") - - -;; Floating point move insns - - -(define_expand "movhf" - [(set (match_operand:HF 0 "general_operand" "") - (match_operand:HF 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, HFmode)) - DONE; -}") - -(define_insn "match_movhf" - [(set (match_operand:HF 0 "nonimmediate_operand" "=A,Z,d,d,m,d,Y") - (match_operand:HF 1 "general_operand" "d,A,F,m,d,Y,d"))] - "" - "* -{ - /* NOTE: When loading the register 16 bits at a time we - MUST load the high half FIRST (because the 1610 zeros - the low half) and then load the low half */ - - switch (which_alternative) - { - /* register to accumulator */ - case 0: - return \"%0=%1\"; - case 1: - return \"%u0=%u1\;%w0=%w1\"; - case 2: - output_dsp16xx_float_const(operands); - return \"\"; - case 3: - double_reg_from_memory(operands); - return \"\"; - case 4: - double_reg_to_memory(operands); - return \"\"; - case 5: - case 6: - return \"%u0=%u1\;%w0=%w1\"; - } -}" -[(set_attr "type" "move,move,load_i,load,store,load,store")]) - - - -(define_expand "reload_inhf" - [(set (match_operand:HF 0 "register_operand" "=r") - (match_operand:HF 1 "register_operand" "r")) - (clobber (match_operand:QI 2 "register_operand" "=&h"))] - "" - " -{ - /* Check for an overlap of operand 2 (an accumulator) with - the msw of operand 0. If we have an overlap we must reverse - the order of the moves. */ - - if (REGNO(operands[2]) == REGNO(operands[0])) - { - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HFmode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HFmode), operands[2]); - } - else - { - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HFmode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HFmode), operands[2]); - } - - DONE; -}") - -(define_expand "reload_outhf" - [(set (match_operand:HF 0 "register_operand" "=r") - (match_operand:HF 1 "register_operand" "r")) - (clobber (match_operand:QI 2 "register_operand" "=&h"))] - "" - " -{ - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HFmode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HFmode), operands[2]); - DONE; -}") - - -;; -;; CONVERSION INSTRUCTIONS -;; - -(define_expand "extendqihi2" - [(clobber (match_dup 2)) - (set (match_dup 3) (match_operand:QI 1 "register_operand" "")) - (set (match_operand:HI 0 "register_operand" "") - (ashift:HI (match_dup 2) - (const_int 16))) - (set (match_dup 0) - (ashiftrt:HI (match_dup 0) (const_int 16)))] - "" - " -{ - operands[2] = gen_reg_rtx (HImode); - operands[3] = gen_rtx (SUBREG, QImode, operands[2], 1); -}") - -;;(define_insn "extendqihi2" -;; [(set (match_operand:HI 0 "register_operand" "=A") -;; (sign_extend:HI (match_operand:QI 1 "register_operand" "h")))] -;; "" -;; "%0 = %1 >> 16") - -;;(define_insn "zero_extendqihi2" -;; [(set (match_operand:HI 0 "register_operand" "=t,f,A,?d,?A") -;; (zero_extend:HI (match_operand:QI 1 "register_operand" "w,z,ku,A,r")))] -;; "" -;; "* -;; { -;; switch (which_alternative) -;; { -;; case 0: -;; case 1: -;; return \"%0=0\"; -;; -;; case 2: -;; if (REGNO(operands[1]) == (REGNO(operands[0]) + 1)) -;; return \"%0=0\"; -;; else -;; return \"%w0=%1\;%0=0\"; -;; case 3: -;; return \"%w0=%1\;%0=0\"; -;; -;; case 4: -;; if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD -;; || IS_ACCUM_REG(REGNO(operands[1]))) -;; return \"move %w0=%1\;%0=0\"; -;; else -;; return \"%w0=%1\;%0=0\"; -;; } -;; }") - -(define_expand "zero_extendqihi2" - [(clobber (match_dup 2)) - (set (match_dup 3) (match_operand:QI 1 "register_operand" "")) - (set (match_operand:HI 0 "register_operand" "") - (ashift:HI (match_dup 2) - (const_int 16))) - (set (match_dup 0) - (lshiftrt:HI (match_dup 0) (const_int 16)))] - "" - " -{ - operands[2] = gen_reg_rtx (HImode); - operands[3] = gen_rtx (SUBREG, QImode, operands[2], 1); -}") - - -(define_expand "floathihf2" - [(set (match_operand:HF 0 "register_operand" "") - (float:HF (match_operand:HI 1 "register_operand" "")))] - "" - " -{ - if (!dsp16xx_floathihf2_libcall) - dsp16xx_floathihf2_libcall = gen_rtx_SYMBOL_REF (Pmode, FLOATHIHF2_LIBCALL); - - emit_library_call (dsp16xx_floathihf2_libcall, 1, HFmode, 1, - operands[1], HImode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - -(define_expand "fix_trunchfhi2" - [(set (match_operand:HI 0 "register_operand" "") - (fix:HI (match_operand:HF 1 "register_operand" "")))] - "" - " -{ - if (!dsp16xx_fixhfhi2_libcall) - dsp16xx_fixhfhi2_libcall = gen_rtx_SYMBOL_REF (Pmode, FIXHFHI2_LIBCALL); - - emit_library_call (dsp16xx_fixhfhi2_libcall, 1, HImode, 1, - operands[1], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "fixuns_trunchfhi2" - [(set (match_operand:HI 0 "register_operand" "") - (unsigned_fix:HI (match_operand:HF 1 "register_operand" "")))] - "" - " -{ - rtx reg1 = gen_reg_rtx (HFmode); - rtx reg2 = gen_reg_rtx (HFmode); - rtx reg3 = gen_reg_rtx (HImode); - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31); - - if (reg1) /* turn off complaints about unreached code */ - { - emit_move_insn (reg1, immed_real_const_1 (offset, HFmode)); - do_pending_stack_adjust (); - - emit_insn (gen_cmphf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); - - emit_insn (gen_fix_trunchfhi2 (operands[0], operands[1])); - emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, - gen_rtx (LABEL_REF, VOIDmode, label2))); - emit_barrier (); - - emit_label (label1); - emit_insn (gen_subhf3 (reg2, operands[1], reg1)); - emit_move_insn (reg3, GEN_INT (0x80000000));; - - emit_insn (gen_fix_trunchfhi2 (operands[0], reg2)); - emit_insn (gen_iorhi3 (operands[0], operands[0], reg3)); - - emit_label (label2); - - /* allow REG_NOTES to be set on last insn (labels don't have enough - fields, and can't be used for REG_NOTES anyway). */ - emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); - DONE; - } -}") - -;; -;; SHIFT INSTRUCTIONS -;; - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 1)))] - "" - "%0=%1>>1" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 4)))] - "" - "%0=%1>>4" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 8)))] - "" - "%0=%1>>8" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 16)))] - "" - "%0=%1>>16" - [(set_attr "type" "special")]) - -;; -;; Arithmetic Right shift - -(define_expand "ashrhi3" - [(set (match_operand:HI 0 "register_operand" "") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!TARGET_BMU) - { - /* If we are shifting by a constant we can do it in 1 or more - 1600 core shift instructions. The core instructions can - shift by 1, 4, 8, or 16. */ - - if (GET_CODE(operands[2]) == CONST_INT) - ; - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - -#if 0 - if (!dsp16xx_ashrhi3_libcall) - dsp16xx_ashrhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, ASHRHI3_LIBCALL); - - emit_library_call (dsp16xx_ashrhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -#else - do_pending_stack_adjust (); - emit_insn (gen_tstqi (operands[2])); - emit_jump_insn (gen_bne (label1)); - emit_move_insn (operands[0], operands[1]); - emit_jump_insn (gen_jump (label2)); - emit_barrier (); - emit_label (label1); - - if (GET_CODE(operands[2]) != MEM) - { - rtx stack_slot; - - stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0); - stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0)); - emit_move_insn (stack_slot, operands[2]); - operands[2] = stack_slot; - } - - emit_insn (gen_match_ashrhi3_nobmu (operands[0], operands[1], operands[2])); - emit_label (label2); - DONE; -#endif - } - } -}") - -(define_insn "match_ashrhi3_bmu" - [(set (match_operand:HI 0 "register_operand" "=A,A,A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A,A,!A") - (match_operand:QI 2 "nonmemory_operand" "B,I,h")))] - "TARGET_BMU" - "@ - %0=%1>>%2 - %0=%1>>%H2 - %0=%1>>%2" - [(set_attr "type" "shift,shift_i,shift")]) - -(define_insn "match_ashrhi3_nobmu" - [(set (match_operand:HI 0 "register_operand" "=A,A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A,0") - (match_operand:QI 2 "general_operand" "n,m")))] - "!TARGET_BMU" - "* -{ - if (which_alternative == 0) - { - emit_1600_core_shift (ASHIFTRT, operands, INTVAL(operands[2])); - return \"\"; - } - else - { - output_asm_insn (\"cloop=%2\", operands); - output_asm_insn (\"do 0 \{\", operands); - output_asm_insn (\"%0=%0>>1\", operands); - return \"\}\"; - } -}") - - - -;; -;; Logical Right Shift - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 1)))] - "" - "%0=%1>>1\;%0=%b0&0x7fff" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 4)))] - "" - "%0=%1>>4\;%0=%b0&0x0fff" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 8)))] - "" - "%0=%1>>8\;%0=%b0&0x00ff" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 16)))] - "" - "%0=%1>>16\;%0=%b0&0x0000" - [(set_attr "type" "special")]) - -(define_expand "lshrhi3" - [(set (match_operand:HI 0 "register_operand" "") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!TARGET_BMU) - { - /* If we are shifting by a constant we can do it in 1 or more - 1600 core shift instructions. The core instructions can - shift by 1, 4, 8, or 16. */ - - if (GET_CODE(operands[2]) == CONST_INT) - emit_insn (gen_match_lshrhi3_nobmu (operands[0], operands[1], operands[2])); - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); -#if 0 - if (!dsp16xx_lshrhi3_libcall) - dsp16xx_lshrhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, LSHRHI3_LIBCALL); - - emit_library_call (dsp16xx_lshrhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -#else - do_pending_stack_adjust (); - emit_insn (gen_tstqi (operands[2])); - emit_jump_insn (gen_bne (label1)); - emit_move_insn (operands[0], operands[1]); - emit_jump_insn (gen_jump (label2)); - emit_barrier (); - emit_label (label1); - - if (GET_CODE(operands[2]) != MEM) - { - rtx stack_slot; - - stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0); - stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0)); - emit_move_insn (stack_slot, operands[2]); - operands[2] = stack_slot; - } - - emit_insn (gen_match_lshrhi3_nobmu (operands[0], operands[1], operands[2])); - emit_label (label2); - DONE; -#endif - } - } -}") - -(define_insn "match_lshrhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A,A,!A") - (match_operand:QI 2 "nonmemory_operand" "B,I,h")))] - "TARGET_BMU" - "@ - %0=%1>>>%2 - %0=%1>>>%H2 - %0=%1>>>%2" - [(set_attr "type" "shift,shift_i,shift")]) - -(define_insn "match_lshrhi3_nobmu" - [(set (match_operand:HI 0 "register_operand" "=A,A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A,0") - (match_operand:QI 2 "general_operand" "n,m"))) - (clobber (match_scratch:QI 3 "=X,Y"))] - "!TARGET_BMU" - "* -{ - if (which_alternative == 0) - { - emit_1600_core_shift (LSHIFTRT, operands, INTVAL(operands[2])); - return \"\"; - } - else - { - output_asm_insn (\"%3=psw\;psw=0\",operands); - output_asm_insn (\"cloop=%2\", operands); - output_asm_insn (\"do 0 \{\", operands); - output_asm_insn (\"%0=%0>>1\", operands); - output_asm_insn (\"\}\", operands); - return \"psw=%3\"; - } -}") - - -;; -;; Arithmetic Left shift - -;; Start off with special case arithmetic left shift by 1,4,8 or 16. - - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "register_operand" "A") - (const_int 1)))] - "" - "%0=%1<<1" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "register_operand" "A") - (const_int 4)))] - "" - "%0=%1<<4" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "register_operand" "A") - (const_int 8)))] - "" - "%0=%1<<8" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "A")) - (const_int 16)))] - "" - "%0=%1<<16" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "general_operand" "A") - (const_int 16)))] - "" - "%0=%1<<16" - [(set_attr "type" "special")]) - - - -;; Normal Arithmetic Shift Left - - -(define_expand "ashlhi3" - [(set (match_operand:HI 0 "register_operand" "") - (ashift:HI (match_operand:HI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!TARGET_BMU) - { - /* If we are shifting by a constant we can do it in 1 or more - 1600 core shift instructions. The core instructions can - shift by 1, 4, 8, or 16. */ - - if (GET_CODE(operands[2]) == CONST_INT) - ; - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); -#if 0 - if (!dsp16xx_ashlhi3_libcall) - dsp16xx_ashlhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, ASHLHI3_LIBCALL); - - emit_library_call (dsp16xx_ashlhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -#else - do_pending_stack_adjust (); - emit_insn (gen_tstqi (operands[2])); - emit_jump_insn (gen_bne (label1)); - emit_move_insn (operands[0], operands[1]); - emit_jump_insn (gen_jump (label2)); - emit_barrier (); - emit_label (label1); - - if (GET_CODE(operands[2]) != MEM) - { - rtx stack_slot; - - stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0); - stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0)); - emit_move_insn (stack_slot, operands[2]); - operands[2] = stack_slot; - } - emit_insn (gen_match_ashlhi3_nobmu (operands[0], operands[1], operands[2])); - emit_label (label2); - DONE; -#endif - } - } -}") - -(define_insn "match_ashlhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A") - (ashift:HI (match_operand:HI 1 "register_operand" "A,A,A") - (match_operand:QI 2 "nonmemory_operand" "B,I,!h")))] - "TARGET_BMU" - "@ - %0=%1<<%2\;move %u0=%u0 - %0=%1<<%H2\;move %u0=%u0 - %0=%1<<%2\;move %u0=%u0" - [(set_attr "type" "shift,shift_i,shift")]) - -(define_insn "match_ashlhi3_nobmu" - [(set (match_operand:HI 0 "register_operand" "=A,A") - (ashift:HI (match_operand:HI 1 "register_operand" "A,0") - (match_operand:QI 2 "general_operand" "n,m")))] - "!TARGET_BMU" - "* -{ - if (which_alternative == 0) - { - emit_1600_core_shift (ASHIFT, operands, INTVAL(operands[2])); - return \"\"; - } - else - { - output_asm_insn (\"cloop=%2\", operands); - output_asm_insn (\"do 0 \{\", operands); - output_asm_insn (\"%0=%0<<1\", operands); - return \"\}\"; - } -}") - - - -;; -;; Jump Instructions -;; - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(EQ, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(NE, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(GT, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(GE, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(LT, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(LE, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(GTU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(GEU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(LTU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen == gen_compare_reg) - operands[1] = (*dsp16xx_compare_gen)(LEU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = (*dsp16xx_compare_gen)(dsp16xx_compare_op0); -}") - - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "!TARGET_NEAR_JUMP" - "pt=%l0\;if %C1 goto pt" - [(set_attr "type" "cond_jump")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_NEAR_JUMP" - "if %C1 goto %l0" - [(set_attr "type" "cond_jump")]) - -;; -;; Negated conditional jump instructions. -;; These are necessary because jump optimization can turn -;; direct-conditional branches into reverse-conditional -;; branches. - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "!TARGET_NEAR_JUMP" - "pt=%l0\;if %I1 goto pt" - [(set_attr "type" "cond_jump")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "TARGET_NEAR_JUMP" - "if %I1 goto %l0" - [(set_attr "type" "cond_jump")]) - - -;; -;; JUMPS -;; - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "* - { - if (TARGET_NEAR_JUMP) - return \"goto %l0\"; - else - return \"pt=%l0\;goto pt\"; - }" - [(set_attr "type" "jump")]) - - -(define_insn "indirect_jump" - [(set (pc) (match_operand:QI 0 "register_operand" "A"))] - "" - "pt=%0\;goto pt" - [(set_attr "type" "jump")]) - -(define_insn "tablejump" - [(set (pc) (match_operand:QI 0 "register_operand" "A")) - (use (label_ref (match_operand 1 "" "")))] - "" - "pt=%0\;goto pt" - [(set_attr "type" "jump")]) - -;; -;; FUNCTION CALLS -;; - -;; Call subroutine with no return value. - - -(define_expand "call" - [(parallel [(call (match_operand:QI 0 "" "") - (match_operand 1 "" "")) - (clobber (reg:QI 24))])] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! call_address_operand (XEXP (operands[0], 0), QImode)) - operands[0] = gen_rtx (MEM, GET_MODE (operands[0]), - force_reg (Pmode, XEXP (operands[0], 0))); -}") - -(define_insn "" - [(parallel [(call (mem:QI (match_operand:QI 0 "call_address_operand" "hR")) - (match_operand 1 "" "")) - (clobber (reg:QI 24))])] - "" - "* -{ - if (GET_CODE (operands[0]) == REG || - (GET_CODE(operands[0]) == SYMBOL_REF && !TARGET_NEAR_CALL)) - return \"pt=%0\;call pt\"; - else - return \"call %0\"; -}" -[(set_attr "type" "call")]) - -;; Call subroutine with return value. - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "register_operand" "=f") - (call (match_operand:QI 1 "call_address_operand" "hR") - (match_operand:QI 2 "" ""))) - (clobber (reg:QI 24))])] - "" - " -{ - if (GET_CODE (operands[1]) == MEM - && ! call_address_operand (XEXP (operands[1], 0), QImode)) - operands[1] = gen_rtx (MEM, GET_MODE (operands[1]), - force_reg (Pmode, XEXP (operands[1], 0))); -}") - -(define_insn "" - [(parallel [(set (match_operand 0 "register_operand" "=f") - (call (mem:QI (match_operand:QI 1 "call_address_operand" "hR")) - (match_operand:QI 2 "" ""))) - (clobber (reg:QI 24))])] - "" - "* -{ - if (GET_CODE (operands[1]) == REG || - (GET_CODE(operands[1]) == SYMBOL_REF && !TARGET_NEAR_CALL)) - return \"pt=%1\;call pt\"; - else - return \"call %1\"; -}" -[(set_attr "type" "call")]) - - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "") - -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "type" "nop")]) - -;; -;; PEEPHOLE PATTERNS -;; - - -(define_peephole - [(set (match_operand:QI 0 "register_operand" "=A") - (reg:QI 16)) - (call (mem:QI (match_dup 0)) - (match_operand 1 "" "i"))] - "" - "call pt") - - -(define_peephole - [(set (match_operand:QI 0 "register_operand" "=A") - (reg:QI 16)) - (set (match_operand 1 "" "") - (call (mem:QI (match_dup 0)) - (match_operand 2 "" "i")))] - "" - "call pt") - -(define_peephole - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "register_operand" "A") - (const_int 16))) - (set (match_operand:HI 2 "register_operand" "") - (match_dup 0)) - (set (match_dup 0) - (ashiftrt:HI (match_dup 0) (const_int 16))) - (set (match_dup 2) - (match_dup 0))] - "" - "%0=%1<<16\;%0=%0>>16\;%u2=%u0\;%w2=%w0") - -(define_peephole - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "register_operand" "A") - (const_int 16))) - (set (match_operand:HI 2 "register_operand" "") - (match_dup 0)) - (set (match_dup 0) - (lshiftrt:HI (match_dup 0) (const_int 16))) - (set (match_dup 2) - (match_dup 0))] - "" - "%0=%1<<16\;%0=%0>>16\;%0=%b0&0x0000\;%u2=%u0\;%w2=%w0") diff --git a/gcc/config/dsp16xx/xm-dsp16xx.h b/gcc/config/dsp16xx/xm-dsp16xx.h deleted file mode 100755 index 00f86b4..0000000 --- a/gcc/config/dsp16xx/xm-dsp16xx.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Configuration file for GNU CC for AT&T DSP1600. - Copyright (C) 1993 Free Software Foundation, Inc. - Contributed by Michael Collison (collison@world.std.com). - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 8 -#define HOST_BITS_PER_SHORT 16 -#define HOST_BITS_PER_INT 16 -#define HOST_BITS_PER_LONG 32 -#define HOST_BITS_PER_LONGLONG 64 - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - -/* If compiled with GNU C, use the built-in alloca */ -#ifdef __GNUC__ -#define alloca __builtin_alloca -#else -#define USE_C_ALLOCA -#endif - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h deleted file mode 100755 index a149ab1..0000000 --- a/gcc/config/elfos.h +++ /dev/null @@ -1,754 +0,0 @@ -/* elfos.h -- operating system specific defines to be used when - targeting GCC for some generic ELF system - Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc. - Based on svr4.h contributed by Ron Guilmette (rfg@netcom.com). - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* For the sake of libgcc2.c, indicate target supports atexit. */ -#define HAVE_ATEXIT - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend.o%s" - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "%{!shared: \ - %{!symbolic: \ - %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\ - crtbegin.o%s" - -/* Attach a special .ident directive to the end of the file to identify - the version of GCC which compiled this code. The format of the - .ident string is patterned after the ones produced by native svr4 - C compilers. */ - -#define IDENT_ASM_OP ".ident" - -#define ASM_FILE_END(FILE) \ -do { \ - fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \ - IDENT_ASM_OP, version_string); \ - } while (0) - -/* Output #ident as a .ident. */ - -#define ASM_OUTPUT_IDENT(FILE, NAME) \ - fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME); - -/* Use periods rather than dollar signs in special g++ assembler names. */ - -#define NO_DOLLAR_IN_LABEL - -/* Writing `int' for a bitfield forces int alignment for the structure. */ - -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* Implicit library calls should use memcpy, not bcopy, etc. */ - -#define TARGET_MEM_FUNCTIONS - -/* Handle #pragma weak and #pragma pack. */ - -#define HANDLE_SYSV_PRAGMA - -/* System V Release 4 uses DWARF debugging info. */ - -#define DWARF_DEBUGGING_INFO - -/* All ELF targets can support DWARF-2. */ - -#define DWARF2_DEBUGGING_INFO - -/* gas on SVR4 supports the use of .stabs. Permit -gstabs to be used - in general, although it will only work when using gas. */ - -#define DBX_DEBUGGING_INFO - -/* The GNU tools operate better with stabs. Since we don't have - any native tools to be compatible with, default to stabs. */ - -#ifndef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG -#endif - -/* Make LBRAC and RBRAC addresses relative to the start of the - function. The native Solaris stabs debugging format works this - way, gdb expects it, and it reduces the number of relocation - entries. */ - -#define DBX_BLOCKS_FUNCTION_RELATIVE 1 - -/* When using stabs, gcc2_compiled must be a stabs entry, not an - ordinary symbol, or gdb won't see it. Furthermore, since gdb reads - the input piecemeal, starting with each N_SO, it's a lot easier if - the gcc2 flag symbol is *after* the N_SO rather than before it. So - we emit an N_OPT stab there. */ - -#define ASM_IDENTIFY_GCC(FILE) \ -do \ - { \ - if (write_symbols != DBX_DEBUG) \ - fputs ("gcc2_compiled.:\n", FILE); \ - } \ -while (0) - -#define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) \ -do \ - { \ - if (write_symbols == DBX_DEBUG) \ - fputs ("\t.stabs\t\"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \ - } \ -while (0) - -/* Like block addresses, stabs line numbers are relative to the - current function. */ - -#undef ASM_OUTPUT_SOURCE_LINE -#define ASM_OUTPUT_SOURCE_LINE(file, line) \ -do \ - { \ - static int sym_lineno = 1; \ - fprintf (file, "\t.stabn 68,0,%d,.LM%d-", \ - line, sym_lineno); \ - assemble_name (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \ - fprintf (file, "\n.LM%d:\n", sym_lineno); \ - sym_lineno += 1; \ - } \ -while (0) - -/* In order for relative line numbers to work, we must output the - stabs entry for the function name first. */ - -#define DBX_FUNCTION_FIRST - -#undef ASM_BYTE_OP -#define ASM_BYTE_OP ".byte" - -#undef SET_ASM_OP -#define SET_ASM_OP ".set" - -/* This is how to begin an assembly language file. Most svr4 assemblers want - at least a .file directive to come first, and some want to see a .version - directive come right after that. Here we just establish a default - which generates only the .file directive. If you need a .version - directive for any specific target, you should override this definition - in the target-specific file which includes this one. */ - -#undef ASM_FILE_START -#define ASM_FILE_START(FILE) \ - output_file_directive ((FILE), main_input_filename) - -/* This is how to allocate empty space in some section. The .zero - pseudo-op is used for this on most svr4 assemblers. */ - -#define SKIP_ASM_OP ".zero" - -#undef ASM_OUTPUT_SKIP -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t%s\t%u\n", SKIP_ASM_OP, (SIZE)) - -/* This is how to output a reference to a user-level label named NAME. - `assemble_name' uses this. - - For System V Release 4 the convention is *not* to prepend a leading - underscore onto user-level symbol names. */ - -#undef ASM_OUTPUT_LABELREF -#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "%s", NAME) - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - - For most svr4 systems, the convention is that any symbol which begins - with a period is not put into the linker symbol table by the assembler. */ - -#undef ASM_OUTPUT_INTERNAL_LABEL -#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \ -do { \ - fprintf (FILE, ".%s%d:\n", PREFIX, NUM); \ -} while (0) - -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. - - For most svr4 systems, the convention is that any symbol which begins - with a period is not put into the linker symbol table by the assembler. */ - -#undef ASM_GENERATE_INTERNAL_LABEL -#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ -do { \ - sprintf (LABEL, "*.%s%d", PREFIX, NUM); \ -} while (0) - -/* Output the label which precedes a jumptable. Note that for all svr4 - systems where we actually generate jumptables (which is to say every - svr4 target except i386, where we use casesi instead) we put the jump- - tables into the .rodata section and since other stuff could have been - put into the .rodata section prior to any given jumptable, we have to - make sure that the location counter for the .rodata section gets pro- - perly re-aligned prior to the actual beginning of the jump table. */ - -#define ALIGN_ASM_OP ".align" - -#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL -#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ - ASM_OUTPUT_ALIGN ((FILE), 2); -#endif - -#undef ASM_OUTPUT_CASE_LABEL -#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \ - do { \ - ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE) \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \ - } while (0) - -/* The standard SVR4 assembler seems to require that certain builtin - library routines (e.g. .udiv) be explicitly declared as .globl - in each assembly file where they are referenced. */ - -#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ - ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0)) - -/* This says how to output assembler code to declare an - uninitialized external linkage data object. Under SVR4, - the linker seems to want the alignment of data objects - to depend on their types. We do exactly that here. */ - -#define COMMON_ASM_OP ".comm" - -#undef ASM_OUTPUT_ALIGNED_COMMON -#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ -do { \ - fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \ - assemble_name ((FILE), (NAME)); \ - fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ -} while (0) - -/* This says how to output assembler code to declare an - uninitialized internal linkage data object. Under SVR4, - the linker seems to want the alignment of data objects - to depend on their types. We do exactly that here. */ - -#define LOCAL_ASM_OP ".local" - -#undef ASM_OUTPUT_ALIGNED_LOCAL -#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ -do { \ - fprintf ((FILE), "\t%s\t", LOCAL_ASM_OP); \ - assemble_name ((FILE), (NAME)); \ - fprintf ((FILE), "\n"); \ - ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ -} while (0) - -/* This is the pseudo-op used to generate a 32-bit word of data with a - specific value in some section. This is the same for all known svr4 - assemblers. */ - -#define INT_ASM_OP ".long" - -/* This is the pseudo-op used to generate a contiguous sequence of byte - values from a double-quoted string WITHOUT HAVING A TERMINATING NUL - AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */ - -#undef ASCII_DATA_ASM_OP -#define ASCII_DATA_ASM_OP ".ascii" - -/* Support const sections and the ctors and dtors sections for g++. - Note that there appears to be two different ways to support const - sections at the moment. You can either #define the symbol - READONLY_DATA_SECTION (giving it some code which switches to the - readonly data section) or else you can #define the symbols - EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and - SELECT_RTX_SECTION. We do both here just to be on the safe side. */ - -#define USE_CONST_SECTION 1 - -#define CONST_SECTION_ASM_OP ".section\t.rodata" - -/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. - - Note that we want to give these sections the SHF_WRITE attribute - because these sections will actually contain data (i.e. tables of - addresses of functions in the current root executable or shared library - file) and, in the case of a shared library, the relocatable addresses - will have to be properly resolved/relocated (and then written into) by - the dynamic linker when it actually attaches the given shared library - to the executing process. (Note that on SVR4, you may wish to use the - `-z text' option to the ELF linker, when building a shared library, as - an additional check that you are doing everything right. But if you do - use the `-z text' option when building a shared library, you will get - errors unless the .ctors and .dtors sections are marked as writable - via the SHF_WRITE attribute.) */ - -#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\"" -#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\"" - -/* On svr4, we *do* have support for the .init and .fini sections, and we - can put stuff in there to be executed before and after `main'. We let - crtstuff.c and other files know this by defining the following symbols. - The definitions say how to change sections to the .init and .fini - sections. This is the same for all known svr4 assemblers. */ - -#define INIT_SECTION_ASM_OP ".section\t.init" -#define FINI_SECTION_ASM_OP ".section\t.fini" - -/* A default list of other sections which we might be "in" at any given - time. For targets that use additional sections (e.g. .tdesc) you - should override this definition in the target-specific file which - includes this file. */ - -#undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_const, in_ctors, in_dtors - -/* A default list of extra section function definitions. For targets - that use additional sections (e.g. .tdesc) you should override this - definition in the target-specific file which includes this file. */ - -#undef EXTRA_SECTION_FUNCTIONS -#define EXTRA_SECTION_FUNCTIONS \ - CONST_SECTION_FUNCTION \ - CTORS_SECTION_FUNCTION \ - DTORS_SECTION_FUNCTION - -#define READONLY_DATA_SECTION() const_section () - -extern void text_section (); - -#define CONST_SECTION_FUNCTION \ -void \ -const_section () \ -{ \ - if (!USE_CONST_SECTION) \ - text_section(); \ - else if (in_section != in_const) \ - { \ - fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \ - in_section = in_const; \ - } \ -} - -#define CTORS_SECTION_FUNCTION \ -void \ -ctors_section () \ -{ \ - if (in_section != in_ctors) \ - { \ - fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ - in_section = in_ctors; \ - } \ -} - -#define DTORS_SECTION_FUNCTION \ -void \ -dtors_section () \ -{ \ - if (in_section != in_dtors) \ - { \ - fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ - in_section = in_dtors; \ - } \ -} - -/* Switch into a generic section. - This is currently only used to support section attributes. */ - -#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ -do { \ - static struct section_info \ - { \ - struct section_info *next; \ - char *name; \ - enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \ - } *sections; \ - struct section_info *s; \ - char *mode; \ - enum sect_enum type; \ - \ - for (s = sections; s; s = s->next) \ - if (!strcmp (NAME, s->name)) \ - break; \ - \ - if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \ - type = SECT_EXEC, mode = "ax"; \ - else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \ - type = SECT_RO, mode = "a"; \ - else \ - type = SECT_RW, mode = "aw"; \ - \ - if (s == 0) \ - { \ - s = (struct section_info *) xmalloc (sizeof (struct section_info)); \ - s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \ - strcpy (s->name, NAME); \ - s->type = type; \ - s->next = sections; \ - sections = s; \ - fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, mode); \ - } \ - else \ - { \ - if (DECL && s->type != type) \ - error_with_decl (DECL, "%s causes a section type conflict"); \ - \ - fprintf (FILE, ".section\t%s\n", NAME); \ - } \ -} while (0) - -#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1) -#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL)) -#define UNIQUE_SECTION(DECL,RELOC) \ -do { \ - int len; \ - char *name, *string, *prefix; \ - \ - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \ - \ - if (! DECL_ONE_ONLY (DECL)) \ - { \ - if (TREE_CODE (DECL) == FUNCTION_DECL) \ - prefix = ".text."; \ - else if (DECL_READONLY_SECTION (DECL, RELOC)) \ - prefix = ".rodata."; \ - else \ - prefix = ".data."; \ - } \ - else if (TREE_CODE (DECL) == FUNCTION_DECL) \ - prefix = ".gnu.linkonce.t."; \ - else if (DECL_READONLY_SECTION (DECL, RELOC)) \ - prefix = ".gnu.linkonce.r."; \ - else \ - prefix = ".gnu.linkonce.d."; \ - \ - len = strlen (name) + strlen (prefix); \ - string = alloca (len + 1); \ - sprintf (string, "%s%s", prefix, name); \ - \ - DECL_SECTION_NAME (DECL) = build_string (len, string); \ -} while (0) -/* A C statement (sans semicolon) to output an element in the table of - global constructors. */ -#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ - do { \ - ctors_section (); \ - fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* A C statement (sans semicolon) to output an element in the table of - global destructors. */ -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ - do { \ - dtors_section (); \ - fprintf (FILE, "\t%s\t ", INT_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ - } while (0) - -/* 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. */ - -#define SELECT_SECTION(DECL,RELOC) \ -{ \ - if (TREE_CODE (DECL) == STRING_CST) \ - { \ - if (! flag_writable_strings) \ - const_section (); \ - else \ - data_section (); \ - } \ - else if (TREE_CODE (DECL) == VAR_DECL) \ - { \ - if ((flag_pic && RELOC) \ - || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ - || !DECL_INITIAL (DECL) \ - || (DECL_INITIAL (DECL) != error_mark_node \ - && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \ - data_section (); \ - else \ - const_section (); \ - } \ - else \ - const_section (); \ -} - -/* A C statement or statements to switch to the appropriate - section for output of RTX in mode MODE. RTX is some kind - of constant in RTL. The argument MODE is redundant except - in the case of a `const_int' rtx. Currently, these always - go into the const section. */ - -#undef SELECT_RTX_SECTION -#define SELECT_RTX_SECTION(MODE,RTX) const_section() - -/* Define the strings used for the special svr4 .type and .size directives. - These strings generally do not vary from one system running svr4 to - another, but if a given system (e.g. m88k running svr) needs to use - different pseudo-op names for these, they may be overridden in the - file which includes this one. */ - -#define TYPE_ASM_OP ".type" -#define SIZE_ASM_OP ".size" - -/* This is how we tell the assembler that a symbol is weak. */ - -#define ASM_WEAKEN_LABEL(FILE,NAME) \ - do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \ - fputc ('\n', FILE); } while (0) - -/* The following macro defines the format used to output the second - operand of the .type assembler directive. Different svr4 assemblers - expect various different forms for this operand. The one given here - is just a default. You may need to override it in your machine- - specific tm.h file (depending upon the particulars of your assembler). */ - -#define TYPE_OPERAND_FMT "@%s" - -/* Write the extra assembler code needed to declare a function's result. - Most svr4 assemblers don't require any special declaration of the - result value, but there are exceptions. */ - -#ifndef ASM_DECLARE_RESULT -#define ASM_DECLARE_RESULT(FILE, RESULT) -#endif - -/* These macros generate the special .type and .size directives which - are used to set the corresponding fields of the linker symbol table - entries in an ELF object file under SVR4. These macros also output - the starting labels for the relevant functions/objects. */ - -/* Write the extra assembler code needed to declare a function properly. - Some svr4 assemblers need to also have something extra said about the - function's return value. We allow for that here. */ - -#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ - do { \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "function"); \ - putc ('\n', FILE); \ - ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -/* Write the extra assembler code needed to declare an object properly. */ - -#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ - do { \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ - putc ('\n', FILE); \ - size_directive_output = 0; \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ - { \ - size_directive_output = 1; \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ - } \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -/* Output the size directive for a decl in rest_of_decl_compilation - in the case where we did not do so before the initializer. - Once we find the error_mark_node, we know that the value of - size_directive_output was set - by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ - -#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ -do { \ - char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ - && ! AT_END && TOP_LEVEL \ - && DECL_INITIAL (DECL) == error_mark_node \ - && !size_directive_output) \ - { \ - size_directive_output = 1; \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, name); \ - fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ - } \ - } while (0) - -/* This is how to declare the size of a function. */ - -#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ - do { \ - if (!flag_inhibit_size_directive) \ - { \ - char label[256]; \ - static int labelno; \ - labelno++; \ - ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, (FNAME)); \ - fprintf (FILE, ","); \ - assemble_name (FILE, label); \ - fprintf (FILE, "-"); \ - assemble_name (FILE, (FNAME)); \ - putc ('\n', FILE); \ - } \ - } while (0) - -/* A table of bytes codes used by the ASM_OUTPUT_ASCII and - ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table - corresponds to a particular byte value [0..255]. For any - given byte value, if the value in the corresponding table - position is zero, the given character can be output directly. - If the table value is 1, the byte must be output as a \ooo - octal escape. If the tables value is anything else, then the - byte value should be output as a \ followed by the value - in the table. Note that we can use standard UN*X escape - sequences for many control characters, but we don't use - \a to represent BEL because some svr4 assemblers (e.g. on - the i386) don't know about that. Also, we don't use \v - since some versions of gas, such as 2.2 did not accept it. */ - -#define ESCAPES \ -"\1\1\1\1\1\1\1\1btn\1fr\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\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\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\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" - -/* Some svr4 assemblers have a limit on the number of characters which - can appear in the operand of a .string directive. If your assembler - has such a limitation, you should define STRING_LIMIT to reflect that - limit. Note that at least some svr4 assemblers have a limit on the - actual number of bytes in the double-quoted string, and that they - count each character in an escape sequence as one byte. Thus, an - escape sequence like \377 would count as four bytes. - - If your target assembler doesn't support the .string directive, you - should define this to zero. -*/ - -#define STRING_LIMIT ((unsigned) 256) - -#define STRING_ASM_OP ".string" - -/* The routine used to output NUL terminated strings. We use a special - version of this for most svr4 targets because doing so makes the - generated assembly code more compact (and thus faster to assemble) - as well as more readable, especially for targets like the i386 - (where the only alternative is to output character sequences as - comma separated lists of numbers). */ - -#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \ - do \ - { \ - register unsigned char *_limited_str = (unsigned char *) (STR); \ - register unsigned ch; \ - fprintf ((FILE), "\t%s\t\"", STRING_ASM_OP); \ - for (; ch = *_limited_str; _limited_str++) \ - { \ - register int escape; \ - switch (escape = ESCAPES[ch]) \ - { \ - case 0: \ - putc (ch, (FILE)); \ - break; \ - case 1: \ - fprintf ((FILE), "\\%03o", ch); \ - break; \ - default: \ - putc ('\\', (FILE)); \ - putc (escape, (FILE)); \ - break; \ - } \ - } \ - fprintf ((FILE), "\"\n"); \ - } \ - while (0) - -/* The routine used to output sequences of byte values. We use a special - version of this for most svr4 targets because doing so makes the - generated assembly code more compact (and thus faster to assemble) - as well as more readable. Note that if we find subparts of the - character sequence which end with NUL (and which are shorter than - STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */ - -#undef ASM_OUTPUT_ASCII -#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \ - do \ - { \ - register unsigned char *_ascii_bytes = (unsigned char *) (STR); \ - register unsigned char *limit = _ascii_bytes + (LENGTH); \ - register unsigned bytes_in_chunk = 0; \ - for (; _ascii_bytes < limit; _ascii_bytes++) \ - { \ - register unsigned char *p; \ - if (bytes_in_chunk >= 60) \ - { \ - fprintf ((FILE), "\"\n"); \ - bytes_in_chunk = 0; \ - } \ - for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \ - continue; \ - if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \ - { \ - if (bytes_in_chunk > 0) \ - { \ - fprintf ((FILE), "\"\n"); \ - bytes_in_chunk = 0; \ - } \ - ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \ - _ascii_bytes = p; \ - } \ - else \ - { \ - register int escape; \ - register unsigned ch; \ - if (bytes_in_chunk == 0) \ - fprintf ((FILE), "\t%s\t\"", ASCII_DATA_ASM_OP); \ - switch (escape = ESCAPES[ch = *_ascii_bytes]) \ - { \ - case 0: \ - putc (ch, (FILE)); \ - bytes_in_chunk++; \ - break; \ - case 1: \ - fprintf ((FILE), "\\%03o", ch); \ - bytes_in_chunk += 4; \ - break; \ - default: \ - putc ('\\', (FILE)); \ - putc (escape, (FILE)); \ - bytes_in_chunk += 2; \ - break; \ - } \ - } \ - } \ - if (bytes_in_chunk > 0) \ - fprintf ((FILE), "\"\n"); \ - } \ - while (0) - -/* All SVR4 targets use the ELF object file format. */ -#define OBJECT_FORMAT_ELF diff --git a/gcc/config/elxsi/elxsi.c b/gcc/config/elxsi/elxsi.c deleted file mode 100755 index b881853..0000000 --- a/gcc/config/elxsi/elxsi.c +++ /dev/null @@ -1,127 +0,0 @@ -/* Subroutines for insn-output.c for GNU compiler. Elxsi version. - Copyright (C) 1987, 1992, 1997 Free Software Foundation, Inc - This port, done by Mike Stump in 1988, and is the first - 64 bit port of GNU CC. - Based upon the VAX port. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include -#include "rtl.h" - -extern char *reg_names[]; -rtx cmp_op0=0, cmp_op1=0; - -/* table of relations for compares and branches */ -char *cmp_tab[] = { - "gt", "gt", "eq", "eq", "ge", "ge", "lt", "lt", "ne", "ne", - "le", "le" }; - -/* type is the index into the above table */ -/* s is "" for signed, or "u" for unsigned */ -char *cmp_jmp(s, type, where) char *s; rtx where; { - rtx br_ops[3]; - char template[50]; - char *f = ""; - char *bits = "64"; - if (GET_MODE (cmp_op0) == SFmode) f = "f", bits = "32"; - if (GET_MODE (cmp_op0) == DFmode) f = "f"; - br_ops[0] = where; - br_ops[1] = cmp_op0; - br_ops[2] = cmp_op1; - if (cmp_op1) - sprintf(template, "%scmp%s.br.%s\t%%1,%%2:j%s\t%%l0", - f, s, bits, cmp_tab[type]); - else if (*f) - sprintf(template, "fcmp.br.%s\t%%1,=0:j%s\t%%l0", - bits, cmp_tab[type]); - else if (*s) /* can turn the below in to a jmp ... */ - sprintf(template, "cmpu.br.64\t%%1,=0:j%s\t%%l0", s, cmp_tab[type]); - else - sprintf(template, "jmp.%s\t%%1,%%l0", cmp_tab[type+1]); - output_asm_insn(template, br_ops); - return ""; -} - -char *cmp_set(s, type, reg) char *s, *type; rtx reg; { - rtx br_ops[3]; - char template[50]; - char *f = ""; - char *bits = "64"; - if (GET_MODE (cmp_op0) == SFmode) f = "f", bits = "32"; - else if (GET_MODE (cmp_op0) == DFmode) f = "f"; - else if (GET_MODE (cmp_op0) == SImode) bits = "32"; - else if (GET_MODE (cmp_op0) == HImode) bits = "16"; - else if (GET_MODE (cmp_op0) == QImode) bits = "8"; - br_ops[0] = reg; - br_ops[1] = cmp_op0; - br_ops[2] = cmp_op1; - if (cmp_op1) - sprintf(template, "%scmp%s.%s\t%%0,%%1,%%2:%s", - f, s, bits, type); - else - sprintf(template, "%scmp%s.%s\t%%0,%%1,=0:%s", - f, s, bits, type); - output_asm_insn(template, br_ops); - return ""; -} - -print_operand_address (file, addr) - FILE *file; - register rtx addr; -{ - register rtx reg1, reg2, breg, ireg; - rtx offset; - - retry: - switch (GET_CODE (addr)) - { - - case MEM: - if (GET_CODE (XEXP (addr, 0)) == REG) - fprintf (file, "%s", reg_names[REGNO (addr)]); - else abort(); - break; - - case REG: - fprintf (file, "[%s]", reg_names[REGNO (addr)]); - break; - - case PLUS: - reg1 = 0; reg2 = 0; - ireg = 0; breg = 0; - offset = 0; - if (GET_CODE (XEXP (addr, 0)) == REG) - { - offset = XEXP (addr, 1); - addr = XEXP (addr, 0); - } - else if (GET_CODE (XEXP (addr, 1)) == REG) - { - offset = XEXP (addr, 0); - addr = XEXP (addr, 1); - } - fprintf (file, "[%s]", reg_names[REGNO (addr)]); - output_address (offset); - break; - - default: - output_addr_const (file, addr); - } -} diff --git a/gcc/config/elxsi/elxsi.h b/gcc/config/elxsi/elxsi.h deleted file mode 100755 index 6e8da32..0000000 --- a/gcc/config/elxsi/elxsi.h +++ /dev/null @@ -1,967 +0,0 @@ -/* Definitions of target machine for GNU compiler. Elxsi version. - Copyright (C) 1987, 1988, 1992, 1995, 1996 Free Software Foundation, Inc. - This port, contributed by Mike Stump in 1988, is the first - 64 bit port of GNU CC. - Based upon the VAX port. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -/* Names to predefine in the preprocessor for this target machine. */ - -#define CPP_PREDEFINES "-Delxsi -Dunix -Asystem(unix) -Acpu(elxsi) -Amachine(elxsi)" - -/* Print subsidiary information on the compiler version in use. */ - -#define TARGET_VERSION fprintf (stderr, " (elxsi)"); - -/* Run-time compilation parameters selecting different hardware subsets. */ - -extern int target_flags; - -/* Macros used in the machine description to test the flags. */ - -/* Nonzero if compiling code that Unix assembler can assemble. */ -#define TARGET_UNIX_ASM (target_flags & 1) - - -/* Macro to define tables used to set the flags. - This is a list in braces of pairs in braces, - each pair being { "NAME", VALUE } - where VALUE is the bits to set or minus the bits to clear. - An empty string NAME is used to identify the default VALUE. */ - -#define TARGET_SWITCHES \ - { {"unix", 1}, \ - {"embos", -1}, \ - { "", TARGET_DEFAULT}} - -/* Default target_flags if no switches specified. */ - -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT 1 -#endif - -/* Target machine storage layout */ - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. - This is not true on the vax. */ -#define BITS_BIG_ENDIAN 0 - -/* Define this if most significant byte of a word is the lowest numbered. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this if most significant word of a multiword number is numbered. */ -#define WORDS_BIG_ENDIAN 1 - -/* Number of bits in an addressable storage unit */ -#define BITS_PER_UNIT 8 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; - if using 16-bit ints on a 68000, this would still be 32. - But on a machine with 16-bit registers, this would be 16. */ -#define BITS_PER_WORD 64 -#define Rmode DImode - -#define INT_TYPE_SIZE 32 - -#define LONG_TYPE_SIZE 32 - -#define LONG_LONG_TYPE_SIZE 64 - -#define FLOAT_TYPE_SIZE 32 - -#define DOUBLE_TYPE_SIZE 64 - -#define LONG_DOUBLE_TYPE_SIZE 64 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 8 - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 32 - -/* Allocation boundary (in *bits*) for storing pointers in memory. */ -#define POINTER_BOUNDARY 32 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 8 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 8 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 32 - -/* A bitfield declared as `int' forces `int' alignment for the struct. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* No data type wants to be aligned rounder than this. */ -#define BIGGEST_ALIGNMENT 32 - -/* Define this if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 0 - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. */ -#define FIRST_PSEUDO_REGISTER 16 - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - On the elxsi, these is the .r15 (aka .sp). */ -#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. */ -#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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. - On the vax, all registers are one word long. */ -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) 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, - for any hard reg, then this must be 0 for correct output. */ -#define MODES_TIEABLE_P(MODE1, MODE2) 1 - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM 15 - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 14 - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms - may be accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED 0 - -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ -{ int regno; \ - int offset = 0; \ - for( regno=0; regno < FIRST_PSEUDO_REGISTER; regno++ ) \ - if( regs_ever_live[regno] && !call_used_regs[regno] ) \ - offset += 8; \ - (DEPTH) = (offset + ((get_frame_size() + 3) & ~3) ); \ - (DEPTH) = 0; \ -} - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM 14 - -/* Register in which static-chain is passed to a function. */ -#define STATIC_CHAIN_REGNUM 0 - -/* Register in which address to store a structure value - is passed to a function. */ -#define STRUCT_VALUE_REGNUM 1 - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -/* The vax has only one kind of registers, so NO_REGS and ALL_REGS - are the only classes. */ - -enum reg_class { NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES }; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ - {"NO_REGS", "GENERAL_REGS", "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS {0, 0x07fff, 0xffff} - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) (REGNO == 15 ? ALL_REGS : GENERAL_REGS) - -/* The class value for index registers, and the one for base regs. */ - -#define INDEX_REG_CLASS GENERAL_REGS -#define BASE_REG_CLASS GENERAL_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) NO_REGS - -/* The letters I, J, K, L and M in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (VALUE) >=-16 && (VALUE) <=15 : 0) - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1 - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ -/* On the vax, this is always the size of MODE in words, - since all registers are the same size. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -#define STACK_GROWS_DOWNWARD - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ -#define STARTING_FRAME_OFFSET -4 - -/* Offset of first parameter from the argument pointer register value. */ -#define FIRST_PARM_OFFSET(FNDECL) 4 - -/* Value is 1 if returning from a function call automatically - pops the arguments described by the number-of-args field in the call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. - - On the Vax, the RET insn always pops all the args for any function. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) (SIZE) - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. */ - -/* On the Vax the return value is in R0 regardless. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), 0) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ - -/* On the Vax the return value is in R0 regardless. */ - -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) - -/* Define this if PCC uses the nonreentrant convention for returning - structure and union values. */ - -#define PCC_STATIC_STRUCT_RETURN - -/* 1 if N is a possible register number for a function value. - On the Vax, R0 is the only register thus used. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) - -/* 1 if N is a possible register number for function argument passing. - On the Vax, no registers are used in this way. */ - -#define FUNCTION_ARG_REGNO_P(N) 0 - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. - - On the vax, this is a single integer, which is a number of bytes - of arguments scanned so far. */ - -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. - - On the vax, the offset starts at 0. */ - -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,x,INDIRECT) \ - ((CUM) = 0) - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - ((CUM) += ((MODE) != BLKmode \ - ? (GET_MODE_SIZE (MODE) + 3) & ~3 \ - : (int_size_in_bytes (TYPE) + 3) & ~3)) - -/* Define where to put the arguments to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ - -/* On the vax all args are pushed. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0 - -/* This macro generates the assembly code for function entry. - FILE is a stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. - 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. */ - -#define FUNCTION_PROLOGUE(FILE, SIZE) \ -{ register int regno; \ - register int cnt = 0; \ - extern char call_used_regs[]; \ - /* the below two lines are a HACK, and should be deleted, but \ - for now are very much needed (1.35) */ \ - if (frame_pointer_needed) \ - regs_ever_live[14]=1, call_used_regs[14]=0; \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ - if (regs_ever_live[regno] && !call_used_regs[regno]) \ - cnt+=8; \ - if ((SIZE)+cnt) \ - fprintf (FILE, "\tadd.64\t.sp,=%d\n", -(SIZE)-cnt); \ - cnt = 0; \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ - if (regs_ever_live[regno] && !call_used_regs[regno]) \ - fprintf (FILE, "\tst.64\t.r%d,[.sp]%d\n", regno, (cnt+=8)-12); \ - if (frame_pointer_needed) \ - fprintf (FILE, "\tadd.64\t.r14,.sp,=%d\n", (SIZE)+cnt); \ -} - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - fprintf (FILE, "\tld.64\t.r0,.LP%d\n\tcall\tmcount\n", (LABELNO)); - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. */ - -#define EXIT_IGNORE_STACK 0 - -/* This macro generates the assembly code for function exit, - on machines that need it. If FUNCTION_EPILOGUE is not defined - then individual return instructions are generated for each - return statement. Args are same as for FUNCTION_PROLOGUE. */ - -#define FUNCTION_EPILOGUE(FILE, SIZE) \ -{ register int regno; \ - register int cnt = 0; \ - extern char call_used_regs[]; \ - extern int current_function_calls_alloca; \ - /* this conditional is ONLY here because there is a BUG; \ - EXIT_IGNORE_STACK is ignored itself when the first part of \ - the condition is true! (at least in version 1.35) */ \ - /* the 8*10 is for 64 bits of .r5 - .r14 */ \ - if (current_function_calls_alloca || (SIZE)>=(256-8*10)) { \ - /* use .r4 as a temporary! Ok for now.... */ \ - fprintf (FILE, "\tld.64\t.r4,.r14\n"); \ - for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno) \ - if (regs_ever_live[regno] && !call_used_regs[regno]) \ - cnt+=8; \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) \ - if (regs_ever_live[regno] && !call_used_regs[regno]) \ - fprintf (FILE, "\tld.64\t.r%d,[.r14]%d\n", regno, \ - -((cnt-=8) + 8)-4-(SIZE)); \ - fprintf (FILE, "\tld.64\t.sp,.r4\n\texit\t0\n"); \ - } else { \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) \ - if (regs_ever_live[regno] && !call_used_regs[regno]) \ - fprintf (FILE, "\tld.64\t.r%d,[.sp]%d\n", regno, (cnt+=8)-12); \ - fprintf (FILE, "\texit\t%d\n", (SIZE)+cnt); \ - } } - -/* If the memory address ADDR is relative to the frame pointer, - correct it to be relative to the stack pointer instead. - This is for when we don't use a frame pointer. - ADDR should be a variable name. */ - -#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \ -{ int offset = -1; \ - rtx regs = stack_pointer_rtx; \ - if (ADDR == frame_pointer_rtx) \ - offset = 0; \ - else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx \ - && GET_CODE (XEXP (ADDR, 0)) == CONST_INT) \ - offset = INTVAL (XEXP (ADDR, 0)); \ - else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \ - && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \ - offset = INTVAL (XEXP (ADDR, 1)); \ - else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \ - { rtx other_reg = XEXP (ADDR, 1); \ - offset = 0; \ - regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \ - else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \ - { rtx other_reg = XEXP (ADDR, 0); \ - offset = 0; \ - regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \ - if (offset >= 0) \ - { int regno; \ - extern char call_used_regs[]; \ - offset += 4; /* I don't know why??? */ \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ - if (regs_ever_live[regno] && ! call_used_regs[regno]) \ - offset += 8; \ - ADDR = plus_constant (regs, offset + (DEPTH)); } } - - -/* Addressing modes, and classification of registers for them. */ - -/* #define HAVE_POST_INCREMENT 0 */ -/* #define HAVE_POST_DECREMENT 0 */ - -/* #define HAVE_PRE_DECREMENT 0 */ -/* #define HAVE_PRE_INCREMENT 0 */ - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_INDEX_P(regno) \ -((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0) -#define REGNO_OK_FOR_BASE_P(regno) \ -((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0) - -/* Maximum number of registers that can appear in a valid memory address. */ - -#define MAX_REGS_PER_ADDRESS 2 - -/* 1 if X is an rtx for a constant that is a valid address. */ - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ - || GET_CODE (X) == HIGH) - -/* 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) \ - (GET_CODE (X) != CONST_DOUBLE) - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) 1 -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) 1 - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - CONSTANT_ADDRESS_P is actually machine-independent. */ - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - if (GET_CODE (X) == REG) goto ADDR; \ - if (CONSTANT_ADDRESS_P (X)) goto ADDR; \ - if (GET_CODE (X) == PLUS) \ - { \ - /* Handle [index]
represented with index-sum outermost */\ - if (GET_CODE (XEXP (X, 0)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT) \ - goto ADDR; \ - if (GET_CODE (XEXP (X, 1)) == REG \ - && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 0)) == CONST_INT) \ - goto ADDR; \ - } \ - } - - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. - - For the vax, nothing needs to be done. */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {} - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. */ -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) - - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE 1 */ - -/* Specify the tree operation to be used to convert reals to integers. */ -#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR - -/* This is the kind of divide that is easiest to do in the general case. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* This flag, if defined, says the same insns that convert to a signed fixnum - also convert validly to an unsigned one. */ -#define FIXUNS_TRUNC_LIKE_FIX_TRUNC - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 8 - -/* Define this if zero-extension is slow (more than one real instruction). */ -/* #define SLOW_ZERO_EXTEND */ - -/* Nonzero if access to memory by bytes is slow and undesirable. */ -#define SLOW_BYTE_ACCESS 0 - -/* Define if shifts truncate the shift count - which implies one can omit a sign-extension or zero-extension - of a shift count. */ -/* #define SHIFT_COUNT_TRUNCATED */ - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -#define Pmode SImode - -/* A function address in a call instruction - is a byte address (for indexing purposes) - so give the MEM rtx a byte's mode. */ -#define FUNCTION_MODE QImode - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. */ - -#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - /* Constant zero is super cheap due to clr instruction. */ \ - if (RTX == const0_rtx) return 0; \ - if ((unsigned) INTVAL (RTX) < 077) return 1; \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - return 3; \ - case CONST_DOUBLE: \ - return 5; - -/* - * We can use the BSD C library routines for the gnulib calls that are - * still generated, since that's what they boil down to anyways. - */ - -/* #define UDIVSI3_LIBCALL "*udiv" */ -/* #define UMODSI3_LIBCALL "*urem" */ - -/* Tell final.c how to eliminate redundant test instructions. */ - -/* Here we define machine-dependent flags and fields in cc_status - (see `conditions.h'). No extra ones are needed for the vax. */ - -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. */ - -#define NOTICE_UPDATE_CC(EXP, INSN) \ - CC_STATUS_INIT; - - -/* Control the assembler format that we output. */ - -/* Output the name of the file we are compiling. */ -#define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) \ - do { fprintf (STREAM, "\t.file\t"); \ - output_quoted_string (STREAM, NAME); \ - fprintf (STREAM, "\n"); \ - } while (0) - -/* Output at beginning of assembler file. */ -#define ASM_FILE_START(FILE) fprintf (FILE, ""); - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF "" - -/* Output before read-only data. */ - -#define TEXT_SECTION_ASM_OP "\t.inst" - -/* Output before writable data. */ - -#define DATA_SECTION_ASM_OP "\t.var" - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{".r0", ".r1", ".r2", ".r3", ".r4", ".r5", ".r6", ".r7", ".r8", \ - ".r9", ".r10", ".r11", ".r12", ".r13", ".r14", ".sp"} - -/* This is BSD, so it wants DBX format. */ - -/* #define DBX_DEBUGGING_INFO */ - -/* How to renumber registers for dbx and gdb. - Vax needs no change in the numeration. */ - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* Do not break .stabs pseudos into continuations. */ - -#define DBX_CONTIN_LENGTH 0 - -/* This is the char to use for continuation (in case we need to turn - continuation back on). */ - -#define DBX_CONTIN_CHAR '?' - -/* Don't use the `xsfoo;' construct in DBX output; this system - doesn't support it. */ - -#define DBX_NO_XREFS - -/* This is how to output the definition of a user-level label named NAME, - such as the label on a static function or variable NAME. */ - -#define ASM_OUTPUT_LABEL(FILE,NAME) \ - do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) - -/* This is how to output a command to make the user-level label named NAME - defined for reference from other files. */ - -#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ - do { fputs ("\t.extdef\t", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) - -/* The prefix to add to user-visible assembler symbols. */ - -#define USER_LABEL_PREFIX "" - -/* This is how to output an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. */ - -#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ - fprintf (FILE, ".%s%d:\n", 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. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, ".%s%d", PREFIX, NUM) - -/* This is how to output an assembler line defining a `double' constant. - It is .dfloat or .gfloat, depending. */ - -#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ -{ union {double d; int i[2]; } tem; \ - tem.d = (VALUE); \ - fprintf (FILE, "\t.data\t%d{32}, %d{32}\n", tem.i[0], tem.i[1]); } - -/* This is how to output an assembler line defining a `float' constant. */ - -#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ -{ union {float f; int i; } tem; \ - tem.f = (VALUE); \ - fprintf (FILE, "\t.data %d{32}\n", tem.i); } - -/* This is how to output an assembler line defining an `int' constant. */ - -#define ASM_OUTPUT_INT(FILE,VALUE) \ -( \ - fprintf (FILE, "\t.data\t"), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "{32}\n")) - -#define ASM_OUTPUT_DOUBLE_INT(FILE,VALUE) \ -{ \ - fprintf (FILE, "\t.data\t"); \ - if (GET_CODE (VALUE) == CONST_DOUBLE) \ - { \ - fprintf (FILE, "%d", CONST_DOUBLE_HIGH (VALUE)); \ - fprintf (FILE, "{32}, "); \ - fprintf (FILE, "%d", CONST_DOUBLE_LOW (VALUE)); \ - fprintf (FILE, "{32}\n"); \ - } else if (GET_CODE (VALUE) == CONST_INT) \ - { \ - int val = INTVAL (VALUE); \ - fprintf (FILE, "%d", val < 0 ? -1 : 0); \ - fprintf (FILE, "{32}, "); \ - fprintf (FILE, "%d", val); \ - fprintf (FILE, "{32}\n"); \ - } else abort (); \ -} - -/* Likewise for `char' and `short' constants. */ - -#define ASM_OUTPUT_SHORT(FILE,VALUE) \ -( fprintf (FILE, "\t.data\t"), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "{16}\n")) - -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ -( fprintf (FILE, "\t.data\t"), \ - output_addr_const (FILE, (VALUE)), \ - fprintf (FILE, "{8}\n")) - -/* This is how to output an assembler line for a numeric constant byte. */ - -#define ASM_OUTPUT_BYTE(FILE,VALUE) \ - fprintf (FILE, "\t.data\t%d{8}\n", (VALUE)) - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tsubi.64\t4,.sp\n\tst.32\t%s,[.sp]\n", reg_names[REGNO]) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tld.32\t%s,[.sp]\n\taddi.64\t4,.sp\n", reg_names[REGNO]) - -/* This is how to output an element of a case-vector that is absolute. - (The Vax does not use such vectors, - but we must define this macro anyway.) */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.data .L%d{32}\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\t.data .L%d-.L%d{32}\n", VALUE, REL) - -/* This is how to output an assembler line - that says to advance the location counter - to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - if (LOG!=0) fprintf (FILE, "\t.align\t%d\n", (LOG)); else 0 - -/* This is how to output an assembler line - that says to advance the location counter by SIZE bytes. */ - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t.space %d\n", (SIZE)) - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs (".comm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d\n", (ROUNDED))) - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -( fputs (".bss ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d,%d\n", (SIZE),(ROUNDED))) - -/* Store in OUTPUT a string (made with alloca) containing - an assembler-name for a local static variable named NAME. - LABELNO is an integer which is different for each call. */ - -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) - -/* Define the parentheses used to group arithmetic operations - in assembler code. */ - -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* Define results of standard character escape sequences. */ -#define TARGET_BELL 007 -#define TARGET_BS 010 -#define TARGET_TAB 011 -#define TARGET_NEWLINE 012 -#define TARGET_VT 013 -#define TARGET_FF 014 -#define TARGET_CR 015 - -/* Print an instruction operand X on file FILE. - CODE is the code from the %-spec that requested printing this operand; - if `%z3' was used to print operand 3, then CODE is 'z'. */ - -#define PRINT_OPERAND(FILE, X, CODE) \ -{ \ - if (CODE == 'r' && GET_CODE (X) == MEM && GET_CODE (XEXP (X, 0)) == REG) \ - fprintf (FILE, "%s", reg_names[REGNO (XEXP (X, 0))]); \ - else if (GET_CODE (X) == REG) \ - fprintf (FILE, "%s", reg_names[REGNO (X)]); \ - else if (GET_CODE (X) == MEM) \ - output_address (XEXP (X, 0)); \ - else \ - { \ - /*debug_rtx(X);*/ \ - putc ('=', FILE); \ - output_addr_const (FILE, X); } \ - } - -/* Print a memory operand whose address is X, on file FILE. - This uses a function in output-vax.c. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ - print_operand_address (FILE, ADDR) - -/* Functions used in the md file. */ - -extern char *cmp_set(); -extern char *cmp_jmp(); - -/* These are stubs, and have yet to bee written. */ - -#define TRAMPOLINE_SIZE 26 -#define TRAMPOLINE_TEMPLATE(FILE) -#define INITIALIZE_TRAMPOLINE(TRAMP,FNADDR,CXT) diff --git a/gcc/config/elxsi/elxsi.md b/gcc/config/elxsi/elxsi.md deleted file mode 100755 index b6969e9..0000000 --- a/gcc/config/elxsi/elxsi.md +++ /dev/null @@ -1,1420 +0,0 @@ -;;- Machine description for GNU compiler, Elxsi Version -;; Copyright (C) 1987, 1988, 1992, 1994 Free Software Foundation, Inc. -;; Contributed by Mike Stump in 1988, and is the first -;; 64 bit port of GNU CC. -;; Based upon the VAX port. - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 1, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - -;;- Instruction patterns. When multiple patterns apply, -;;- the first one in the file is chosen. -;;- -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. -;;- -;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code -;;- updates for most instructions. - - -(define_insn "" - [(set (reg:SI 15) - (plus:SI (reg:SI 15) - (match_operand:SI 0 "general_operand" "g")))] - "" - "add.64\\t.sp,%0") - -(define_insn "" - [(set (reg:SI 15) - (plus:SI (match_operand:SI 0 "general_operand" "g") - (reg:SI 15)))] - "" - "add.64\\t.sp,%0") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "r") - (plus:SI (reg:SI 15) - (match_operand:SI 1 "general_operand" "g")))] - "" - "ld.32\\t%0,.sp\;add.64\\t%0,%1") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "r") - (plus:SI (match_operand:SI 1 "general_operand" "g") - (reg:SI 15)))] - "" - "ld.32\\t%0,.sp\;add.64\\t%0,%1") - -(define_insn "" - [(set (reg:SI 15) - (minus:SI (reg:SI 15) - (match_operand:SI 0 "general_operand" "g")))] - "" - "sub.64\\t.sp,%0") - -(define_insn "" - [(set (reg:SI 15) - (match_operand:SI 0 "general_operand" "rm"))] - "" - "ld.32\\t.sp,%0") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "m,r") - (reg:SI 15))] - "" - "* - if (which_alternative == 0) - return \"st.32\\t.sp,%0\"; - return \"ld.32\\t%0,.sp\"; -") - -; tstdi is first test insn so that it is the one to match -; a constant argument. - -(define_insn "tstdi" - [(set (cc0) - (match_operand:DI 0 "register_operand" "r"))] - "" - "* - extern rtx cmp_op0, cmp_op1; - cmp_op0=operands[0]; cmp_op1=0; - return \";\\ttstdi\\t%0\"; -") - -(define_insn "tstdf" - [(set (cc0) - (match_operand:DF 0 "register_operand" "r"))] - "" - "* - extern rtx cmp_op0, cmp_op1; - cmp_op0=operands[0]; cmp_op1=0; - return \";\\ttstdf\\t%0\"; -") - -(define_insn "tstsf" - [(set (cc0) - (match_operand:SF 0 "register_operand" "r"))] - "" - "* - extern rtx cmp_op0, cmp_op1; - cmp_op0=operands[0]; cmp_op1=0; - return \";\\ttstsf\\t%0\"; -") - -(define_insn "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "register_operand" "r") - (match_operand:DI 1 "general_operand" "rm")))] - "" - "* - extern rtx cmp_op0, cmp_op1; - cmp_op0=operands[0]; cmp_op1=operands[1]; - return \";\\tcmpdi\\t%0,%1\"; -") - -(define_insn "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "register_operand" "r") - (match_operand:DF 1 "general_operand" "rm")))] - "" - "* - extern rtx cmp_op0, cmp_op1; - cmp_op0=operands[0]; cmp_op1=operands[1]; - return \";\\tcmpdf\\t%0,%1\"; -") - -(define_insn "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "register_operand" "r") - (match_operand:SF 1 "general_operand" "rm")))] - "" - "* - extern rtx cmp_op0, cmp_op1; - cmp_op0=operands[0]; cmp_op1=operands[1]; - return \";\\tcmpsf\\t%0,%1\"; -") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (eq (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmp.64\\t%0,%1,%2:eq") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ne (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmp.64\\t%0,%1,%2:ne") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (le (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmp.64\\t%0,%1,%2:le") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (leu (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmpu.64\\t%0,%1,%2:le") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (lt (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmp.64\\t%0,%1,%2:lt") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ltu (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmpu.64\\t%0,%1,%2:lt") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ge (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmp.64\\t%0,%1,%2:ge") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (geu (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmpu.64\\t%0,%1,%2:ge") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (gt (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmp.64\\t%0,%1,%2:gt") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (gtu (match_operand:DI 1 "register_operand" "r") - (match_operand:DI 2 "general_operand" "g")))] - "" - "cmpu.64\\t%0,%1,%2:gt") - -(define_insn "seq" - [(set (match_operand:DI 0 "register_operand" "=r") - (eq (cc0) (const_int 0)))] - "" - "* return cmp_set(\"\", \"eq\", operands[0]); ") - -(define_insn "sne" - [(set (match_operand:DI 0 "register_operand" "=r") - (ne (cc0) (const_int 0)))] - "" - "* return cmp_set(\"\", \"ne\", operands[0]); ") - -(define_insn "sle" - [(set (match_operand:DI 0 "register_operand" "=r") - (le (cc0) (const_int 0)))] - "" - "* return cmp_set(\"\", \"le\", operands[0]); ") - -(define_insn "sleu" - [(set (match_operand:DI 0 "register_operand" "=r") - (leu (cc0) (const_int 0)))] - "" - "* return cmp_set(\"u\", \"le\", operands[0]); ") - -(define_insn "slt" - [(set (match_operand:DI 0 "register_operand" "=r") - (lt (cc0) (const_int 0)))] - "" - "* return cmp_set(\"\", \"lt\", operands[0]); ") - -(define_insn "sltu" - [(set (match_operand:DI 0 "register_operand" "=r") - (ltu (cc0) (const_int 0)))] - "" - "* return cmp_set(\"u\", \"lt\", operands[0]); ") - -(define_insn "sge" - [(set (match_operand:DI 0 "register_operand" "=r") - (ge (cc0) (const_int 0)))] - "" - "* return cmp_set(\"\", \"ge\", operands[0]); ") - -(define_insn "sgeu" - [(set (match_operand:DI 0 "register_operand" "=r") - (geu (cc0) (const_int 0)))] - "" - "* return cmp_set(\"u\", \"ge\", operands[0]); ") - -(define_insn "sgt" - [(set (match_operand:DI 0 "register_operand" "=r") - (gt (cc0) (const_int 0)))] - "" - "* return cmp_set(\"\", \"gt\", operands[0]); ") - -(define_insn "sgtu" - [(set (match_operand:DI 0 "register_operand" "=r") - (gtu (cc0) (const_int 0)))] - "" - "* return cmp_set(\"u\", \"gt\", operands[0]); ") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (eq (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmp.32\\t%0,%1,%2:eq") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ne (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmp.32\\t%0,%1,%2:ne") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (le (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmp.32\\t%0,%1,%2:le") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (leu (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmpu.32\\t%0,%1,%2:le") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (lt (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmp.32\\t%0,%1,%2:lt") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ltu (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmpu.32\\t%0,%1,%2:lt") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ge (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmp.32\\t%0,%1,%2:ge") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (geu (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmpu.32\\t%0,%1,%2:ge") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (gt (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmp.32\\t%0,%1,%2:gt") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (gtu (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "m")))] - "" - "cmpu.32\\t%0,%1,%2:gt") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (eq (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmp.16\\t%0,%1,%2:eq") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (ne (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmp.16\\t%0,%1,%2:ne") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (le (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmp.16\\t%0,%1,%2:le") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (leu (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmpu.16\\t%0,%1,%2:le") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (lt (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmp.16\\t%0,%1,%2:lt") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (ltu (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmpu.16\\t%0,%1,%2:lt") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (ge (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmp.16\\t%0,%1,%2:ge") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (geu (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmpu.16\\t%0,%1,%2:ge") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (gt (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmp.16\\t%0,%1,%2:gt") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (gtu (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "general_operand" "m")))] - "" - "cmpu.16\\t%0,%1,%2:gt") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (eq (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmp.8\\t%0,%1,%2:eq") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (ne (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmp.8\\t%0,%1,%2:ne") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (le (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmp.8\\t%0,%1,%2:le") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (leu (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmpu.8\\t%0,%1,%2:le") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (lt (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmp.8\\t%0,%1,%2:lt") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (ltu (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmpu.8\\t%0,%1,%2:lt") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (ge (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmp.8\\t%0,%1,%2:ge") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (geu (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmpu.8\\t%0,%1,%2:ge") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (gt (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmp.8\\t%0,%1,%2:gt") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=r") - (gtu (match_operand:QI 1 "register_operand" "r") - (match_operand:QI 2 "general_operand" "m")))] - "" - "cmpu.8\\t%0,%1,%2:gt") - - - -(define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=r,m") - (match_operand:DF 1 "general_operand" "rm,r"))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.64\\t%0,%1\"; - return \"st.64\\t%1,%0\"; -}") - -(define_insn "movsf" - [(set (match_operand:SF 0 "general_operand" "=r,m") - (match_operand:SF 1 "general_operand" "rm,r"))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.32\\t%0,%1\"; - return \"st.32\\t%1,%0\"; -}") - -(define_insn "movdi" - [(set (match_operand:DI 0 "general_operand" "=r,m,rm") - (match_operand:DI 1 "general_operand" "g,r,I"))] - "" - "* - if (which_alternative == 0) - return \"ld.64\\t%0,%1\"; - else if (which_alternative == 1) - return \"st.64\\t%1,%0\"; - else - if (GET_CODE(operands[1])==CONST_INT) { - if (INTVAL(operands[1]) >= 0) - return \"sti.64\\t%c1,%0\"; - else - return \"stin.64\\t%n1,%0\"; - } -") - -(define_insn "movsi" - [(set (match_operand:SI 0 "general_operand" "=r,m,r") - (match_operand:SI 1 "general_operand" "rm,rI,i"))] - "" - "* - if (which_alternative == 0) - return \"ld.32\\t%0,%1\"; - else if (which_alternative == 1) { - if (GET_CODE(operands[1])==CONST_INT) { - if (INTVAL(operands[1]) >= 0) - return \"sti.32\\t%c1,%0\"; - else - return \"stin.32\\t%n1,%0\"; - } - return \"st.32\\t%1,%0\"; - } else - return \"ld.64\\t%0,%1 ; I only want 32\"; -") - -(define_insn "movhi" - [(set (match_operand:HI 0 "general_operand" "=r,m,r") - (match_operand:HI 1 "general_operand" "m,rI,ri"))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.16\\t%0,%1\"; - if (which_alternative == 2) - return \"ld.64\\t%0,%1\\t; I only want 16\"; - if (GET_CODE(operands[1])==CONST_INT) { - if (INTVAL(operands[1]) >= 0) - return \"sti.16\\t%c1,%0\"; - else - return \"stin.16\\t%n1,%0\"; - } - return \"st.16\\t%1,%0\"; -}") - -(define_insn "movqi" - [(set (match_operand:QI 0 "general_operand" "=r,m,r") - (match_operand:QI 1 "general_operand" "m,rI,ri"))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.8\\t%0,%1\"; - if (which_alternative == 2) - return \"ld.64\\t%0,%1\\t; I only want 8\"; - if (GET_CODE(operands[1])==CONST_INT) { - if (INTVAL(operands[1]) >= 0) - return \"sti.8\\t%c1,%0\"; - else - return \"stin.8\\t%n1,%0\"; - } - return \"st.8\\t%1,%0\"; -}") - -;; Extension and truncation insns. -;; Those for integer source operand -;; are ordered widest source type first. - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=r") - (truncate:SF (match_operand:DF 1 "general_operand" "rm")))] - "" - "cvt.ds\\t%0,%1") - -(define_insn "truncdiqi2" - [(set (match_operand:QI 0 "general_operand" "=r,m,r") - (truncate:QI (match_operand:DI 1 "general_operand" "m,r,0")))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.8\\t%0,%1\"; - else if (which_alternative == 1) - return \"st.8\\t%1,%0\"; - return \"\"; -}") - -(define_insn "truncdihi2" - [(set (match_operand:HI 0 "general_operand" "=r,m,r") - (truncate:HI (match_operand:DI 1 "general_operand" "m,r,0")))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.16\\t%0,%1\"; - if (which_alternative == 1) - return \"st.16\\t%1,%0\"; - return \"\"; -}") - -(define_insn "truncdisi2" - [(set (match_operand:SI 0 "general_operand" "=r,m") - (truncate:SI (match_operand:DI 1 "general_operand" "rm,r")))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.32\\t%0,%1\"; - return \"st.32\\t%1,%0\"; -}") - -(define_insn "truncsiqi2" - [(set (match_operand:QI 0 "general_operand" "=r,m,r") - (truncate:QI (match_operand:SI 1 "general_operand" "m,r,0")))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.8\\t%0,%1\"; - if (which_alternative == 1) - return \"st.8\\t%1,%0\"; - return \"\"; -}") - -(define_insn "truncsihi2" - [(set (match_operand:HI 0 "general_operand" "=r,m,r") - (truncate:HI (match_operand:SI 1 "general_operand" "m,r,0")))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.16\\t%0,%1\"; - if (which_alternative == 1) - return \"st.16\\t%1,%0\"; - return \"\"; -}") - -(define_insn "trunchiqi2" - [(set (match_operand:QI 0 "general_operand" "=r,m,r") - (truncate:QI (match_operand:HI 1 "general_operand" "m,r,0")))] - "" - "* -{ - if (which_alternative == 0) - return \"ld.8\\t%0,%1\"; - if (which_alternative == 1) - return \"st.8\\t%1,%0\"; - return \"\"; -}") - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=r") - (sign_extend:DF (match_operand:SF 1 "general_operand" "rm")))] - "" - "cvt.sd\\t%0,%1") - -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI (match_operand:SI 1 "general_operand" "rm")))] - "" - "ld.32\\t%0,%1") - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (sign_extend:SI (match_operand:HI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ld.16\\t%0,%1\"; - return \"extract\\t%0,%1:bit 48,16\"; -") - -(define_insn "extendhidi2" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (sign_extend:DI (match_operand:HI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ld.16\\t%0,%1\"; - return \"extract\\t%0,%1:bit 48,16\"; -") - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (sign_extend:HI (match_operand:QI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ld.8\\t%0,%1\"; - return \"extract\\t%0,%1:bit 56,8\"; -") - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (sign_extend:SI (match_operand:QI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ld.8\\t%0,%1\"; - return \"extract\\t%0,%1:bit 56,8\"; -") - -(define_insn "extendqidi2" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (sign_extend:DI (match_operand:QI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ld.8\\t%0,%1\"; - return \"extract\\t%0,%1:bit 56,8\"; -") - -(define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))] - "" - "ldz.32\\t%0,%1") - - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI (match_operand:HI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ldz.16\\t%0,%1\"; - return \"extractz\\t%0,%1:bit 48,16\"; -") - -(define_insn "zero_extendhidi2" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (match_operand:HI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ldz.16\\t%0,%1\"; - return \"extractz\\t%0,%1:bit 48,16\"; -") - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (zero_extend:HI (match_operand:QI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ldz.8\\t%0,%1\"; - return \"extractz\\t%0,%1:bit 56,8\"; -") - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI (match_operand:QI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ldz.8\\t%0,%1\"; - return \"extractz\\t%0,%1:bit 56,8\"; -") - -(define_insn "zero_extendqidi2" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (zero_extend:DI (match_operand:QI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative==0) - return \"ldz.8\\t%0,%1\"; - return \"extractz\\t%0,%1:bit 56,8\"; -") - - -(define_insn "ashrdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "rn")))] - "" - "sra\\t%0,%1,%2") - -(define_insn "lshrdi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "rn")))] - "" - "srl\\t%0,%1,%2") - -(define_insn "ashldi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashift:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:SI 2 "general_operand" "rn")))] - "" - "sla\\t%0,%1,%2") - -(define_insn "anddi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (and:DI (match_operand:DI 1 "general_operand" "%0,r") - (match_operand:DI 2 "general_operand" "g,g")))] - "1 /*which_alternative == 0 || check356(operands[2])*/" - "* - if (which_alternative == 0) - return \"and\\t%0,%2\"; - return \"and\\t%0,%1,%2\"; -") - -(define_insn "iordi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (ior:DI (match_operand:DI 1 "general_operand" "%0,r") - (match_operand:DI 2 "general_operand" "g,g")))] - "1 /*which_alternative == 0 || check356(operands[2])*/" - "* - if (which_alternative == 0) - return \"or\\t%0,%2\"; - return \"or\\t%0,%1,%2\"; -") - -(define_insn "xordi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (xor:DI (match_operand:DI 1 "general_operand" "%0,r") - (match_operand:DI 2 "general_operand" "g,g")))] - "1 /*which_alternative == 0 || check356(operands[2])*/" - "* - if (which_alternative == 0) - return \"xor\\t%0,%2\"; - return \"xor\\t%0,%1,%2\"; -") - -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (not:DI (match_operand:DI 1 "general_operand" "rm")))] - "" - "not\\t%0,%1") - -;; gcc 2.1 does not widen ~si into ~di. -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (not:SI (match_operand:SI 1 "register_operand" "r")))] - "" - "not\\t%0,%1") - -(define_insn "negdi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (neg:DI (match_operand:DI 1 "general_operand" "rm")))] - "" - "neg.64\\t%0,%1") - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (neg:SI (match_operand:SI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative == 0) - return \"neg.32\\t%0,%1\"; - return \"neg.64\\t%0,%1 ; I only want 32\"; -") - -(define_insn "neghi2" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (neg:HI (match_operand:HI 1 "general_operand" "m,r")))] - "" - "* - if (which_alternative == 0) - return \"neg.16\\t%0,%1\"; - return \"neg.64\\t%0,%1 ; I only want 16\"; -") - -(define_insn "adddf3" - [(set (match_operand:DF 0 "register_operand" "=r") - (plus:DF (match_operand:DF 1 "general_operand" "%0") - (match_operand:DF 2 "general_operand" "rm")))] - "" - "fadd.64\\t%0,%2") - -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=r") - (plus:SF (match_operand:SF 1 "general_operand" "%0") - (match_operand:SF 2 "general_operand" "rm")))] - "" - "fadd.32\\t%0,%2") - -;; There is also an addi.64 4,.r0'' optimization -(define_insn "adddi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (plus:DI (match_operand:DI 1 "general_operand" "%0,r") - (match_operand:DI 2 "general_operand" "g,g")))] - "1 /*which_alternative == 0 || check356(operands[2])*/" - "* - if (which_alternative == 0) - return \"add.64\\t%0,%2\"; - return \"add.64\\t%0,%1,%2\"; -") - -(define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (plus:SI (match_operand:SI 1 "general_operand" "%0,r,0") - (match_operand:SI 2 "general_operand" "m,m,g")))] - "1 /*which_alternative != 1 || check356(operands[2])*/" - "* - if (which_alternative == 0) - return \"add.32\\t%0,%2\"; - if (which_alternative == 1) - return \"add.32\\t%0,%1,%2\"; - return \"add.64\\t%0,%2 ; I only want 32\"; -") - -(define_insn "addhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r,r") - (plus:HI (match_operand:HI 1 "general_operand" "%0,r,0") - (match_operand:HI 2 "general_operand" "m,m,g")))] - "1 /*which_alternative != 1 || check356(operands[2])*/" - "* - if (which_alternative == 0) - return \"add.16\\t%0,%2\"; - if (which_alternative == 1) - return \"add.16\\t%0,%1,%2\"; - return \"add.64\\t%0,%2 ; I only want 16\"; -") - -(define_insn "subdf3" - [(set (match_operand:DF 0 "register_operand" "=r") - (minus:DF (match_operand:DF 1 "general_operand" "0") - (match_operand:DF 2 "general_operand" "rm")))] - "" - "fsub.64\\t%0,%2") - -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=r") - (minus:SF (match_operand:SF 1 "general_operand" "0") - (match_operand:SF 2 "general_operand" "rm")))] - "" - "fsub.32\\t%0,%2") - -(define_insn "subdi3" - [(set (match_operand:DI 0 "register_operand" "=r,r,r") - (minus:DI (match_operand:DI 1 "general_operand" "0,g,r") - (match_operand:DI 2 "general_operand" "g,r,g")))] - "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" - "* - if (which_alternative == 0) - return \"sub.64\\t%0,%2\"; - else if (which_alternative == 1) - return \"subr.64\\t%0,%2,%1\"; - else - return \"sub.64\\t%0,%1,%2\"; -") - -(define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (minus:SI (match_operand:SI 1 "general_operand" "0,m,r,0") - (match_operand:SI 2 "general_operand" "m,r,m,g")))] - "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" - "* - if (which_alternative == 0) - return \"sub.32\\t%0,%2\"; - else if (which_alternative == 1) - return \"subr.32\\t%0,%2,%1\"; - else if (which_alternative == 2) - return \"sub.32\\t%0,%1,%2\"; - else - return \"sub.64\\t%0,%2 ; I only want 32\"; -") - -(define_insn "subhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") - (minus:HI (match_operand:HI 1 "general_operand" "0,m,r,0") - (match_operand:HI 2 "general_operand" "m,r,m,g")))] - "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" - "* - if (which_alternative == 0) - return \"sub.16\\t%0,%2\"; - else if (which_alternative == 1) - return \"subr.16\\t%0,%2,%1\"; - else if (which_alternative == 2) - return \"sub.16\\t%0,%1,%2\"; - else - return \"sub.64\\t%0,%2 ; I only want 16\"; -") - -(define_insn "muldf3" - [(set (match_operand:DF 0 "register_operand" "=r") - (mult:DF (match_operand:DF 1 "general_operand" "%0") - (match_operand:DF 2 "general_operand" "rm")))] - "" - "fmul.64\\t%0,%2") - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=r") - (mult:SF (match_operand:SF 1 "general_operand" "%0") - (match_operand:SF 2 "general_operand" "rm")))] - "" - "fmul.32\\t%0,%2") - -(define_insn "muldi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (mult:DI (match_operand:DI 1 "general_operand" "%0,r") - (match_operand:DI 2 "general_operand" "g,g")))] - "1 /*which_alternative == 0 || check356(operands[2])*/" - "* - if (which_alternative == 0) - return \"mul.64\\t%0,%2\"; - return \"mul.64\\t%0,%1,%2\"; -") - -(define_insn "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (mult:SI (match_operand:SI 1 "general_operand" "%0,r,0") - (match_operand:SI 2 "general_operand" "m,m,g")))] - "1 /*which_alternative == 0 || check356(operands[2])*/" - "* - if (which_alternative == 0) - return \"mul.32\\t%0,%2\"; - else if (which_alternative == 1) - return \"mul.32\\t%0,%1,%2\"; - else - return \"mul.64\\t%0,%2 ; I only want 32\"; -") - -(define_insn "mulhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r,r") - (mult:HI (match_operand:HI 1 "general_operand" "%0,r,0") - (match_operand:HI 2 "general_operand" "m,m,g")))] - "1 /*which_alternative == 0 || check356(operands[2])*/" - "* - if (which_alternative == 0) - return \"mul.16\\t%0,%2\"; - else if (which_alternative == 1) - return \"mul.16\\t%0,%1,%2\"; - else - return \"mul.64\\t%0,%2 ; I only want 16\"; -") - -(define_insn "divdf3" - [(set (match_operand:DF 0 "register_operand" "=r") - (div:DF (match_operand:DF 1 "general_operand" "0") - (match_operand:DF 2 "general_operand" "rm")))] - "" - "fdiv.64\\t%0,%2") - -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=r") - (div:SF (match_operand:SF 1 "general_operand" "0") - (match_operand:SF 2 "general_operand" "rm")))] - "" - "fdiv.32\\t%0,%2") - -(define_insn "divdi3" - [(set (match_operand:DI 0 "register_operand" "=r,r,r") - (div:DI (match_operand:DI 1 "general_operand" "0,g,r") - (match_operand:DI 2 "general_operand" "g,r,g")))] - "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" - "* - if (which_alternative == 0) - return \"div.64\\t%0,%2\"; - else if (which_alternative == 1) - return \"divr.64\\t%0,%2,%1\"; - else - return \"div.64\\t%0,%1,%2\"; -") - -(define_insn "divsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (div:SI (match_operand:SI 1 "general_operand" "0,m,r,0") - (match_operand:SI 2 "general_operand" "m,r,m,g")))] - "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" - "* -/* We don't ignore high bits. */ -if (0) { - if (which_alternative == 0) - return \"div.32\\t%0,%2\"; - else if (which_alternative == 1) - return \"divr.32\\t%0,%2,%1\"; - else if (which_alternative == 2) - return \"div.32\\t%0,%1,%2\"; - else - return \"ld.32\\t%0,%0\;div.64\\t%0,%2 ; I only want 32\"; -} else { - if (which_alternative == 0) - return \"ld.32\\t%0,%0\;div.32\\t%0,%2\"; - else if (which_alternative == 1) - return \"ld.32\\t%2,%2\;divr.32\\t%0,%2,%1\"; - else if (which_alternative == 2) - return \"ld.32\\t%1,%1\;div.32\\t%0,%1,%2\"; - else - return \"ld.32\\t%0,%0\;div.64\\t%0,%2 ; I only want 32\"; -} -") - -(define_insn "divhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") - (div:HI (match_operand:HI 1 "general_operand" "0,m,r,0,0") - (match_operand:HI 2 "general_operand" "m,r,m,r,i")))] - "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" - "* - if (which_alternative == 0) - return \"extract\\t%0,%0:bit 48,16\;div.16\\t%0,%2\"; - else if (which_alternative == 1) - return \"extract\\t%2,%2:bit 48,16\;divr.16\\t%0,%2,%1\"; - else if (which_alternative == 2) - return \"extract\\t%1,%1:bit 48,16\;div.16\\t%0,%1,%2\"; - else if (which_alternative == 3) - return \"extract\\t%0,%0:bit 48,16\;extract\\t%2,%2:bit 48,16\;div.64\\t%0,%2 ; I only want 16\"; - else - return \"extract\\t%0,%0:bit 48,16\;div.64\\t%0,%2 ; I only want 16\"; -") - -(define_insn "modhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") - (mod:HI (match_operand:HI 1 "general_operand" "0,m,r,0,0") - (match_operand:HI 2 "general_operand" "m,r,m,r,i")))] - "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" - "* - if (which_alternative == 0) - return \"extract\\t%0,%0:bit 48,16\;rem.16\\t%0,%2\"; - else if (which_alternative == 1) - return \"extract\\t%2,%2:bit 48,16\;remr.16\\t%0,%2,%1\"; - else if (which_alternative == 2) - return \"extract\\t%1,%1:bit 48,16\;rem.16\\t%0,%1,%2\"; - else if (which_alternative == 3) - return \"extract\\t%0,%0:bit 48,16\;extract\\t%2,%2:bit 48,16\;rem.64\\t%0,%2 ; I only want 16\"; - else - return \"extract\\t%0,%0:bit 48,16\;rem.64\\t%0,%2 ; I only want 16\"; -") - -(define_insn "moddi3" - [(set (match_operand:DI 0 "register_operand" "=r,r,r") - (mod:DI (match_operand:DI 1 "general_operand" "0,g,r") - (match_operand:DI 2 "general_operand" "g,r,g")))] - "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" - "* - if (which_alternative == 0) - return \"rem.64\\t%0,%2\"; - else if (which_alternative == 1) - return \"remr.64\\t%0,%2,%1\"; - else - return \"rem.64\\t%0,%1,%2\"; -") - -(define_insn "modsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (mod:SI (match_operand:SI 1 "general_operand" "0,m,r,0") - (match_operand:SI 2 "general_operand" "m,r,m,g")))] - "1 /*which_alternative == 0 || check356(operands[which_alternative])*/" - "* -/* There is a micro code bug with the below... */ -if (0) { - if (which_alternative == 0) - return \"rem.32\\t%0,%2\"; - else if (which_alternative == 1) - return \"remr.32\\t%0,%2,%1\"; - else if (which_alternative == 2) - return \"rem.32\\t%0,%1,%2\"; - else - return \"ld.32\\t%0,%0\;rem.64\\t%0,%2 ; I only want 32\"; -} else { - if (which_alternative == 0) - return \"ld.32\\t%0,%0\;rem.32\\t%0,%2\"; - else if (which_alternative == 1) - return \"ld.32\\t%2,%2\;remr.32\\t%0,%2,%1\"; - else if (which_alternative == 2) - return \"ld.32\\t%1,%1\;rem.32\\t%0,%1,%2\"; - else - return \"ld.32\\t%0,%0\;rem.64\\t%0,%2 ; I only want 32\"; -} -") - - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "jmp\\t%l0") - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "r"))] - "" -;; Maybe %l0 is better, maybe we can relax register only. - "verify this before use ld.32\\t.r0,%0\;br.reg\\t.r0") - -(define_insn "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"\", 2, operands[0]); ") - -(define_insn "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"\", 8, operands[0]); ") - -(define_insn "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"\", 0, operands[0]); ") - -(define_insn "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"u\", 0, operands[0]); ") - -(define_insn "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"\", 6, operands[0]); ") - -(define_insn "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"u\", 6, operands[0]); ") - -(define_insn "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"\", 4, operands[0]); ") - -(define_insn "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"u\", 4, operands[0]); ") - -(define_insn "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"\", 10, operands[0]); ") - -(define_insn "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return cmp_jmp(\"u\", 10, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"\", 8, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"\", 2, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"\", 10, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"u\", 10, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"\", 4, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"u\", 4, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"\", 6, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"u\", 6, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"\", 0, operands[0]); ") - -(define_insn "" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* return cmp_jmp(\"u\", 0, operands[0]); ") - -;; Note that operand 1 is total size of args, in bytes, -;; and what the call insn wants is the number of words. -(define_insn "call" - [(call (match_operand:QI 0 "general_operand" "m") - (match_operand:QI 1 "general_operand" "g"))] - "" - "* - if (GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) == REG) - if (REGNO (XEXP (operands[0], 0)) != 0) - return \"add.64\\t.sp,=-4\;ld.64\\t.r0,=.+11\;st.32\\t.r0,[.sp]\;br.reg\\t%r0\;add.64\\t.sp,=4\;add.64\\t.sp,%1\"; - else - return \"add.64\\t.sp,=-4\;ld.64\\t.r1,=.+11\;st.32\\t.r1,[.sp]\;br.reg\\t%r0\;add.64\\t.sp,=4\;add.64\\t.sp,%1\"; - else - return \"add.64\\t.sp,=-4\;call\\t%0\;add.64\\t.sp,=4\;add.64\\t.sp,%1\"; - ") - -(define_insn "call_value" - [(set (match_operand 0 "" "g") - (call (match_operand:QI 1 "general_operand" "m") - (match_operand:QI 2 "general_operand" "g")))] - "" - "* - if (GET_CODE (operands[1]) == MEM && GET_CODE (XEXP (operands[1], 0)) == REG) - if (REGNO (XEXP (operands[1], 0)) != 0) - return \"add.64\\t.sp,=-4\;ld.64\\t.r0,=.+11\;st.32\\t.r0,[.sp]\;br.reg\\t%r1\;add.64\\t.sp,=4\;add.64\\t.sp,%2\"; - else - return \"add.64\\t.sp,=-4\;ld.64\\t.r1,=.+11\;st.32\\t.r1,[.sp]\;br.reg\\t%r1\;add.64\\t.sp,=4\;add.64\\t.sp,%2\"; - else - return \"add.64\\t.sp,=-4\;call\\t%1\;add.64\\t.sp,=4\;add.64\\t.sp,%2\"; - ") - -(define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "register_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "" - "br.reg\\t%0") - -(define_insn "nop" - [(const_int 0)] - "" - "nop") diff --git a/gcc/config/elxsi/x-elxsi b/gcc/config/elxsi/x-elxsi deleted file mode 100755 index 30a458d..0000000 --- a/gcc/config/elxsi/x-elxsi +++ /dev/null @@ -1,9 +0,0 @@ -# Our make needs a little help... -MAKE=make - -# We don't support -g yet, so don't try and use it. -CFLAGS = -LIBGCC2_CFLAGS = -O2 $(GCC_CFLAGS) - -# Hide xmalloc so that it does not conflict with the one in libc.a, Ick! -X_CFLAGS = -Dxmalloc=my_xmalloc diff --git a/gcc/config/elxsi/xm-elxsi.h b/gcc/config/elxsi/xm-elxsi.h deleted file mode 100755 index ab35a68..0000000 --- a/gcc/config/elxsi/xm-elxsi.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Configuration for GNU C-compiler for Elxsi. - Copyright (C) 1987, 1993 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* #defines that need visibility everywhere. */ -#define FALSE 0 -#define TRUE 1 - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* This describes the machine the compiler is hosted on. */ -#define HOST_BITS_PER_CHAR 8 -#define HOST_BITS_PER_SHORT 16 -#define HOST_BITS_PER_INT 32 -#define HOST_BITS_PER_LONG 32 - -/* Arguments to use with `exit'. */ -#define SUCCESS_EXIT_CODE 0 -#define FATAL_EXIT_CODE 33 - diff --git a/gcc/config/float-d10v.h b/gcc/config/float-d10v.h deleted file mode 100755 index 92403a5..0000000 --- a/gcc/config/float-d10v.h +++ /dev/null @@ -1,131 +0,0 @@ -/* CYGNUS LOCAL */ -/* float.h for target d10v which defaults to float==double */ -#ifndef _FLOAT_H_ -#define _FLOAT_H_ -/* Produced by enquire version 4.3, CWI, Amsterdam */ - - /* Radix of exponent representation */ -#undef FLT_RADIX -#define FLT_RADIX 2 - /* Number of base-FLT_RADIX digits in the significand of a float */ -#undef FLT_MANT_DIG -#define FLT_MANT_DIG 24 - /* Number of decimal digits of precision in a float */ -#undef FLT_DIG -#define FLT_DIG 6 - /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ -#undef FLT_ROUNDS -#define FLT_ROUNDS 1 - /* Difference between 1.0 and the minimum float greater than 1.0 */ -#undef FLT_EPSILON -#define FLT_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ -#undef FLT_MIN_EXP -#define FLT_MIN_EXP (-125) - /* Minimum normalised float */ -#undef FLT_MIN -#define FLT_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised float */ -#undef FLT_MIN_10_EXP -#define FLT_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ -#undef FLT_MAX_EXP -#define FLT_MAX_EXP 128 - /* Maximum float */ -#undef FLT_MAX -#define FLT_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable float */ -#undef FLT_MAX_10_EXP -#define FLT_MAX_10_EXP 38 - -#if __DOUBLE__!=64 - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#undef DBL_MANT_DIG -#define DBL_MANT_DIG 24 - /* Number of decimal digits of precision in a double */ -#undef DBL_DIG -#define DBL_DIG 6 - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#undef DBL_EPSILON -#define DBL_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#undef DBL_MIN_EXP -#define DBL_MIN_EXP (-125) - /* Minimum normalised double */ -#undef DBL_MIN -#define DBL_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised double */ -#undef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#undef DBL_MAX_EXP -#define DBL_MAX_EXP 128 - /* Maximum double */ -#undef DBL_MAX -#define DBL_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable double */ -#undef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 38 - -#else - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#undef DBL_MANT_DIG -#define DBL_MANT_DIG 53 - /* Number of decimal digits of precision in a double */ -#undef DBL_DIG -#define DBL_DIG 15 - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#undef DBL_EPSILON -#define DBL_EPSILON 2.2204460492503131e-16 - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#undef DBL_MIN_EXP -#define DBL_MIN_EXP (-1021) - /* Minimum normalised double */ -#undef DBL_MIN -#define DBL_MIN 2.2250738585072014e-308 - /* Minimum int x such that 10**x is a normalised double */ -#undef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-307) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#undef DBL_MAX_EXP -#define DBL_MAX_EXP 1024 - /* Maximum double */ -#undef DBL_MAX -#define DBL_MAX 1.7976931348623157e+308 - /* Maximum int x such that 10**x is a representable double */ -#undef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 308 - -#endif - - /* Number of base-FLT_RADIX digits in the significand of a long double */ -#undef LDBL_MANT_DIG -#define LDBL_MANT_DIG 53 - /* Number of decimal digits of precision in a long double */ -#undef LDBL_DIG -#define LDBL_DIG 15 - /* Difference between 1.0 and the minimum long double greater than 1.0 */ -#undef LDBL_EPSILON -#define LDBL_EPSILON 2.2204460492503131e-16 - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ -#undef LDBL_MIN_EXP -#define LDBL_MIN_EXP (-1021) - /* Minimum normalised long double */ -#undef LDBL_MIN -#define LDBL_MIN 2.2250738585072014e-308 - /* Minimum int x such that 10**x is a normalised long double */ -#undef LDBL_MIN_10_EXP -#define LDBL_MIN_10_EXP (-307) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ -#undef LDBL_MAX_EXP -#define LDBL_MAX_EXP 1024 - /* Maximum long double */ -#undef LDBL_MAX -#define LDBL_MAX 1.7976931348623157e+308 - /* Maximum int x such that 10**x is a representable long double */ -#undef LDBL_MAX_10_EXP -#define LDBL_MAX_10_EXP 308 - -#endif /* _FLOAT_H_ */ diff --git a/gcc/config/float-i128.h b/gcc/config/float-i128.h deleted file mode 100755 index 6a9dd48..0000000 --- a/gcc/config/float-i128.h +++ /dev/null @@ -1,96 +0,0 @@ -/* float.h for target with IEEE 32, 64 and 128 bit floating point formats */ -#ifndef _FLOAT_H_ -#define _FLOAT_H_ -/* Produced by enquire version 4.3, CWI, Amsterdam */ - - /* Radix of exponent representation */ -#undef FLT_RADIX -#define FLT_RADIX 2 - /* Number of base-FLT_RADIX digits in the significand of a float */ -#undef FLT_MANT_DIG -#define FLT_MANT_DIG 24 - /* Number of decimal digits of precision in a float */ -#undef FLT_DIG -#define FLT_DIG 6 - /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ -#undef FLT_ROUNDS -#define FLT_ROUNDS 1 - /* Difference between 1.0 and the minimum float greater than 1.0 */ -#undef FLT_EPSILON -#define FLT_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ -#undef FLT_MIN_EXP -#define FLT_MIN_EXP (-125) - /* Minimum normalised float */ -#undef FLT_MIN -#define FLT_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised float */ -#undef FLT_MIN_10_EXP -#define FLT_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ -#undef FLT_MAX_EXP -#define FLT_MAX_EXP 128 - /* Maximum float */ -#undef FLT_MAX -#define FLT_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable float */ -#undef FLT_MAX_10_EXP -#define FLT_MAX_10_EXP 38 - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#undef DBL_MANT_DIG -#define DBL_MANT_DIG 53 - /* Number of decimal digits of precision in a double */ -#undef DBL_DIG -#define DBL_DIG 15 - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#undef DBL_EPSILON -#define DBL_EPSILON 2.2204460492503131e-16 - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#undef DBL_MIN_EXP -#define DBL_MIN_EXP (-1021) - /* Minimum normalised double */ -#undef DBL_MIN -#define DBL_MIN 2.2250738585072014e-308 - /* Minimum int x such that 10**x is a normalised double */ -#undef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-307) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#undef DBL_MAX_EXP -#define DBL_MAX_EXP 1024 - /* Maximum double */ -#undef DBL_MAX -#define DBL_MAX 1.7976931348623157e+308 - /* Maximum int x such that 10**x is a representable double */ -#undef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 308 - - /* Number of base-FLT_RADIX digits in the significand of a long double */ -#undef LDBL_MANT_DIG -#define LDBL_MANT_DIG 113 - /* Number of decimal digits of precision in a long double */ -#undef LDBL_DIG -#define LDBL_DIG 33 - /* Difference between 1.0 and the minimum long double greater than 1.0 */ -#undef LDBL_EPSILON -#define LDBL_EPSILON 1.925929944387235853055977942584927319E-34L - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ -#undef LDBL_MIN_EXP -#define LDBL_MIN_EXP (-16381) - /* Minimum normalised long double */ -#undef LDBL_MIN -#define LDBL_MIN 3.362103143112093506262677817321752603E-4932L - /* Minimum int x such that 10**x is a normalised long double */ -#undef LDBL_MIN_10_EXP -#define LDBL_MIN_10_EXP (-4931) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ -#undef LDBL_MAX_EXP -#define LDBL_MAX_EXP 16384 - /* Maximum long double */ -#undef LDBL_MAX -#define LDBL_MAX 1.189731495357231765085759326628007016E+4932L - /* Maximum int x such that 10**x is a representable long double */ -#undef LDBL_MAX_10_EXP -#define LDBL_MAX_10_EXP 4932 - -#endif /* _FLOAT_H_ */ diff --git a/gcc/config/float-i32.h b/gcc/config/float-i32.h deleted file mode 100755 index c834926..0000000 --- a/gcc/config/float-i32.h +++ /dev/null @@ -1,96 +0,0 @@ -/* float.h for target with only IEEE 32 bit floating point format */ -#ifndef _FLOAT_H_ -#define _FLOAT_H_ -/* Produced by enquire version 4.3, CWI, Amsterdam */ - - /* Radix of exponent representation */ -#undef FLT_RADIX -#define FLT_RADIX 2 - /* Number of base-FLT_RADIX digits in the significand of a float */ -#undef FLT_MANT_DIG -#define FLT_MANT_DIG 24 - /* Number of decimal digits of precision in a float */ -#undef FLT_DIG -#define FLT_DIG 6 - /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ -#undef FLT_ROUNDS -#define FLT_ROUNDS 1 - /* Difference between 1.0 and the minimum float greater than 1.0 */ -#undef FLT_EPSILON -#define FLT_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ -#undef FLT_MIN_EXP -#define FLT_MIN_EXP (-125) - /* Minimum normalised float */ -#undef FLT_MIN -#define FLT_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised float */ -#undef FLT_MIN_10_EXP -#define FLT_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ -#undef FLT_MAX_EXP -#define FLT_MAX_EXP 128 - /* Maximum float */ -#undef FLT_MAX -#define FLT_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable float */ -#undef FLT_MAX_10_EXP -#define FLT_MAX_10_EXP 38 - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#undef DBL_MANT_DIG -#define DBL_MANT_DIG 24 - /* Number of decimal digits of precision in a double */ -#undef DBL_DIG -#define DBL_DIG 6 - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#undef DBL_EPSILON -#define DBL_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#undef DBL_MIN_EXP -#define DBL_MIN_EXP (-125) - /* Minimum normalised double */ -#undef DBL_MIN -#define DBL_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised double */ -#undef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#undef DBL_MAX_EXP -#define DBL_MAX_EXP 128 - /* Maximum double */ -#undef DBL_MAX -#define DBL_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable double */ -#undef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 38 - - /* Number of base-FLT_RADIX digits in the significand of a long double */ -#undef LDBL_MANT_DIG -#define LDBL_MANT_DIG 24 - /* Number of decimal digits of precision in a long double */ -#undef LDBL_DIG -#define LDBL_DIG 6 - /* Difference between 1.0 and the minimum long double greater than 1.0 */ -#undef LDBL_EPSILON -#define LDBL_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ -#undef LDBL_MIN_EXP -#define LDBL_MIN_EXP (-125) - /* Minimum normalised long double */ -#undef LDBL_MIN -#define LDBL_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised long double */ -#undef LDBL_MIN_10_EXP -#define LDBL_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ -#undef LDBL_MAX_EXP -#define LDBL_MAX_EXP 128 - /* Maximum long double */ -#undef LDBL_MAX -#define LDBL_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable long double */ -#undef LDBL_MAX_10_EXP -#define LDBL_MAX_10_EXP 38 - -#endif /* _FLOAT_H_ */ diff --git a/gcc/config/float-i386.h b/gcc/config/float-i386.h deleted file mode 100755 index 2d14f70..0000000 --- a/gcc/config/float-i386.h +++ /dev/null @@ -1,104 +0,0 @@ -/* float.h for target with IEEE 32/64 bit and Intel 386 style 80 bit - floating point formats */ -#ifndef _FLOAT_H_ -#define _FLOAT_H_ -/* Produced by enquire version 4.3, CWI, Amsterdam */ - - /* Radix of exponent representation */ -#undef FLT_RADIX -#define FLT_RADIX 2 - /* Number of base-FLT_RADIX digits in the significand of a float */ -#undef FLT_MANT_DIG -#define FLT_MANT_DIG 24 - /* Number of decimal digits of precision in a float */ -#undef FLT_DIG -#define FLT_DIG 6 - /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ -#undef FLT_ROUNDS -#define FLT_ROUNDS 1 - /* Difference between 1.0 and the minimum float greater than 1.0 */ -#undef FLT_EPSILON -#define FLT_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ -#undef FLT_MIN_EXP -#define FLT_MIN_EXP (-125) - /* Minimum normalised float */ -#undef FLT_MIN -#define FLT_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised float */ -#undef FLT_MIN_10_EXP -#define FLT_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ -#undef FLT_MAX_EXP -#define FLT_MAX_EXP 128 - /* Maximum float */ -#undef FLT_MAX -#define FLT_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable float */ -#undef FLT_MAX_10_EXP -#define FLT_MAX_10_EXP 38 - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#undef DBL_MANT_DIG -#define DBL_MANT_DIG 53 - /* Number of decimal digits of precision in a double */ -#undef DBL_DIG -#define DBL_DIG 15 - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#undef DBL_EPSILON -#define DBL_EPSILON 2.2204460492503131e-16 - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#undef DBL_MIN_EXP -#define DBL_MIN_EXP (-1021) - /* Minimum normalised double */ -#undef DBL_MIN -#define DBL_MIN 2.2250738585072014e-308 - /* Minimum int x such that 10**x is a normalised double */ -#undef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-307) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#undef DBL_MAX_EXP -#define DBL_MAX_EXP 1024 - /* Maximum double */ -#undef DBL_MAX -#define DBL_MAX 1.7976931348623157e+308 - /* Maximum int x such that 10**x is a representable double */ -#undef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 308 - - /* Number of base-FLT_RADIX digits in the significand of a long double */ -#undef LDBL_MANT_DIG -#define LDBL_MANT_DIG 64 - /* Number of decimal digits of precision in a long double */ -#undef LDBL_DIG -#define LDBL_DIG 18 - /* Difference between 1.0 and the minimum long double greater than 1.0 */ -#undef LDBL_EPSILON -#ifndef __LDBL_UNION__ -#define __LDBL_UNION__ -union __convert_long_double { - unsigned __convert_long_double_i[4]; - long double __convert_long_double_d; -}; -#endif -#define LDBL_EPSILON (__extension__ ((union __convert_long_double) {__convert_long_double_i: {0x0, 0x80000000, 0x3fc0, 0x0}}).__convert_long_double_d) - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ -#undef LDBL_MIN_EXP -#define LDBL_MIN_EXP (-16381) - /* Minimum normalised long double */ -#undef LDBL_MIN -#define LDBL_MIN (__extension__ ((union __convert_long_double) {__convert_long_double_i: {0x0, 0x80000000, 0x1, 0x0}}).__convert_long_double_d) - /* Minimum int x such that 10**x is a normalised long double */ -#undef LDBL_MIN_10_EXP -#define LDBL_MIN_10_EXP (-4931) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ -#undef LDBL_MAX_EXP -#define LDBL_MAX_EXP 16384 - /* Maximum long double */ -#undef LDBL_MAX -#define LDBL_MAX (__extension__ ((union __convert_long_double) {__convert_long_double_i: {0xffffffff, 0xffffffff, 0x107ffe, 0x0}}).__convert_long_double_d) - /* Maximum int x such that 10**x is a representable long double */ -#undef LDBL_MAX_10_EXP -#define LDBL_MAX_10_EXP 4932 - -#endif /* _FLOAT_H___ */ diff --git a/gcc/config/float-m68k.h b/gcc/config/float-m68k.h deleted file mode 100755 index b36d447..0000000 --- a/gcc/config/float-m68k.h +++ /dev/null @@ -1,97 +0,0 @@ -/* float.h for target with IEEE 32 bit and 64 bit and Motorola style 96 bit - floating point formats */ -#ifndef _FLOAT_H_ -#define _FLOAT_H_ -/* Produced by enquire version 4.3, CWI, Amsterdam */ - - /* Radix of exponent representation */ -#undef FLT_RADIX -#define FLT_RADIX 2 - /* Number of base-FLT_RADIX digits in the significand of a float */ -#undef FLT_MANT_DIG -#define FLT_MANT_DIG 24 - /* Number of decimal digits of precision in a float */ -#undef FLT_DIG -#define FLT_DIG 6 - /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ -#undef FLT_ROUNDS -#define FLT_ROUNDS 1 - /* Difference between 1.0 and the minimum float greater than 1.0 */ -#undef FLT_EPSILON -#define FLT_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ -#undef FLT_MIN_EXP -#define FLT_MIN_EXP (-125) - /* Minimum normalised float */ -#undef FLT_MIN -#define FLT_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised float */ -#undef FLT_MIN_10_EXP -#define FLT_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ -#undef FLT_MAX_EXP -#define FLT_MAX_EXP 128 - /* Maximum float */ -#undef FLT_MAX -#define FLT_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable float */ -#undef FLT_MAX_10_EXP -#define FLT_MAX_10_EXP 38 - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#undef DBL_MANT_DIG -#define DBL_MANT_DIG 53 - /* Number of decimal digits of precision in a double */ -#undef DBL_DIG -#define DBL_DIG 15 - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#undef DBL_EPSILON -#define DBL_EPSILON 2.2204460492503131e-16 - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#undef DBL_MIN_EXP -#define DBL_MIN_EXP (-1021) - /* Minimum normalised double */ -#undef DBL_MIN -#define DBL_MIN 2.2250738585072014e-308 - /* Minimum int x such that 10**x is a normalised double */ -#undef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-307) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#undef DBL_MAX_EXP -#define DBL_MAX_EXP 1024 - /* Maximum double */ -#undef DBL_MAX -#define DBL_MAX 1.7976931348623157e+308 - /* Maximum int x such that 10**x is a representable double */ -#undef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 308 - - /* Number of base-FLT_RADIX digits in the significand of a long double */ -#undef LDBL_MANT_DIG -#define LDBL_MANT_DIG 64 - /* Number of decimal digits of precision in a long double */ -#undef LDBL_DIG -#define LDBL_DIG 18 - /* Difference between 1.0 and the minimum long double greater than 1.0 */ -#undef LDBL_EPSILON -#define LDBL_EPSILON 1.08420217248550443401e-19L - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ -#undef LDBL_MIN_EXP -#define LDBL_MIN_EXP (-16382) - /* Minimum normalised long double */ -#undef LDBL_MIN -#define LDBL_MIN 1.68105157155604675313e-4932L - /* Minimum int x such that 10**x is a normalised long double */ -#undef LDBL_MIN_10_EXP -#define LDBL_MIN_10_EXP (-4931) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ -#undef LDBL_MAX_EXP -#define LDBL_MAX_EXP 16384 - /* Maximum long double */ -#undef LDBL_MAX -#define LDBL_MAX 1.18973149535723176502e+4932L - /* Maximum int x such that 10**x is a representable long double */ -#undef LDBL_MAX_10_EXP -#define LDBL_MAX_10_EXP 4932 - -#endif /* _FLOAT_H_ */ diff --git a/gcc/config/float-sh.h b/gcc/config/float-sh.h deleted file mode 100755 index 4466924..0000000 --- a/gcc/config/float-sh.h +++ /dev/null @@ -1,130 +0,0 @@ -/* float.h for target sh3e with optional IEEE 32 bit double format */ -#ifndef _FLOAT_H_ -#define _FLOAT_H_ -/* Produced by enquire version 4.3, CWI, Amsterdam */ - - /* Radix of exponent representation */ -#undef FLT_RADIX -#define FLT_RADIX 2 - /* Number of base-FLT_RADIX digits in the significand of a float */ -#undef FLT_MANT_DIG -#define FLT_MANT_DIG 24 - /* Number of decimal digits of precision in a float */ -#undef FLT_DIG -#define FLT_DIG 6 - /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ -#undef FLT_ROUNDS -#define FLT_ROUNDS 1 - /* Difference between 1.0 and the minimum float greater than 1.0 */ -#undef FLT_EPSILON -#define FLT_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ -#undef FLT_MIN_EXP -#define FLT_MIN_EXP (-125) - /* Minimum normalised float */ -#undef FLT_MIN -#define FLT_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised float */ -#undef FLT_MIN_10_EXP -#define FLT_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ -#undef FLT_MAX_EXP -#define FLT_MAX_EXP 128 - /* Maximum float */ -#undef FLT_MAX -#define FLT_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable float */ -#undef FLT_MAX_10_EXP -#define FLT_MAX_10_EXP 38 - -#if defined (__SH3E__) || defined (__SH4_SINGLE_ONLY__) - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#undef DBL_MANT_DIG -#define DBL_MANT_DIG 24 - /* Number of decimal digits of precision in a double */ -#undef DBL_DIG -#define DBL_DIG 6 - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#undef DBL_EPSILON -#define DBL_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#undef DBL_MIN_EXP -#define DBL_MIN_EXP (-125) - /* Minimum normalised double */ -#undef DBL_MIN -#define DBL_MIN 1.17549435e-38F - /* Minimum int x such that 10**x is a normalised double */ -#undef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-37) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#undef DBL_MAX_EXP -#define DBL_MAX_EXP 128 - /* Maximum double */ -#undef DBL_MAX -#define DBL_MAX 3.40282347e+38F - /* Maximum int x such that 10**x is a representable double */ -#undef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 38 - -#else - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#undef DBL_MANT_DIG -#define DBL_MANT_DIG 53 - /* Number of decimal digits of precision in a double */ -#undef DBL_DIG -#define DBL_DIG 15 - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#undef DBL_EPSILON -#define DBL_EPSILON 2.2204460492503131e-16 - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#undef DBL_MIN_EXP -#define DBL_MIN_EXP (-1021) - /* Minimum normalised double */ -#undef DBL_MIN -#define DBL_MIN 2.2250738585072014e-308 - /* Minimum int x such that 10**x is a normalised double */ -#undef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-307) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#undef DBL_MAX_EXP -#define DBL_MAX_EXP 1024 - /* Maximum double */ -#undef DBL_MAX -#define DBL_MAX 1.7976931348623157e+308 - /* Maximum int x such that 10**x is a representable double */ -#undef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 308 - -#endif - - /* Number of base-FLT_RADIX digits in the significand of a long double */ -#undef LDBL_MANT_DIG -#define LDBL_MANT_DIG 53 - /* Number of decimal digits of precision in a long double */ -#undef LDBL_DIG -#define LDBL_DIG 15 - /* Difference between 1.0 and the minimum long double greater than 1.0 */ -#undef LDBL_EPSILON -#define LDBL_EPSILON 2.2204460492503131e-16 - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ -#undef LDBL_MIN_EXP -#define LDBL_MIN_EXP (-1021) - /* Minimum normalised long double */ -#undef LDBL_MIN -#define LDBL_MIN 2.2250738585072014e-308 - /* Minimum int x such that 10**x is a normalised long double */ -#undef LDBL_MIN_10_EXP -#define LDBL_MIN_10_EXP (-307) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ -#undef LDBL_MAX_EXP -#define LDBL_MAX_EXP 1024 - /* Maximum long double */ -#undef LDBL_MAX -#define LDBL_MAX 1.7976931348623157e+308 - /* Maximum int x such that 10**x is a representable long double */ -#undef LDBL_MAX_10_EXP -#define LDBL_MAX_10_EXP 308 - -#endif /* _FLOAT_H_ */ diff --git a/gcc/config/float-vax.h b/gcc/config/float-vax.h deleted file mode 100755 index 3c87f79..0000000 --- a/gcc/config/float-vax.h +++ /dev/null @@ -1,96 +0,0 @@ -/* float.h for target with VAX floating point formats */ -#ifndef _FLOAT_H_ -#define _FLOAT_H_ -/* Produced by enquire version 4.3, CWI, Amsterdam */ - - /* Radix of exponent representation */ -#undef FLT_RADIX -#define FLT_RADIX 2 - /* Number of base-FLT_RADIX digits in the significand of a float */ -#undef FLT_MANT_DIG -#define FLT_MANT_DIG 24 - /* Number of decimal digits of precision in a float */ -#undef FLT_DIG -#define FLT_DIG 6 - /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ -#undef FLT_ROUNDS -#define FLT_ROUNDS 1 - /* Difference between 1.0 and the minimum float greater than 1.0 */ -#undef FLT_EPSILON -#define FLT_EPSILON 1.19209290e-07F - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ -#undef FLT_MIN_EXP -#define FLT_MIN_EXP (-127) - /* Minimum normalised float */ -#undef FLT_MIN -#define FLT_MIN 2.93873588e-39F - /* Minimum int x such that 10**x is a normalised float */ -#undef FLT_MIN_10_EXP -#define FLT_MIN_10_EXP (-38) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ -#undef FLT_MAX_EXP -#define FLT_MAX_EXP 127 - /* Maximum float */ -#undef FLT_MAX -#define FLT_MAX 1.70141173e+38F - /* Maximum int x such that 10**x is a representable float */ -#undef FLT_MAX_10_EXP -#define FLT_MAX_10_EXP 38 - - /* Number of base-FLT_RADIX digits in the significand of a double */ -#undef DBL_MANT_DIG -#define DBL_MANT_DIG 56 - /* Number of decimal digits of precision in a double */ -#undef DBL_DIG -#define DBL_DIG 16 - /* Difference between 1.0 and the minimum double greater than 1.0 */ -#undef DBL_EPSILON -#define DBL_EPSILON 2.77555756156289135e-17 - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ -#undef DBL_MIN_EXP -#define DBL_MIN_EXP (-127) - /* Minimum normalised double */ -#undef DBL_MIN -#define DBL_MIN 2.93873587705571877e-39 - /* Minimum int x such that 10**x is a normalised double */ -#undef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-38) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ -#undef DBL_MAX_EXP -#define DBL_MAX_EXP 127 - /* Maximum double */ -#undef DBL_MAX -#define DBL_MAX 1.70141183460469229e+38 - /* Maximum int x such that 10**x is a representable double */ -#undef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 38 - - /* Number of base-FLT_RADIX digits in the significand of a long double */ -#undef LDBL_MANT_DIG -#define LDBL_MANT_DIG 56 - /* Number of decimal digits of precision in a long double */ -#undef LDBL_DIG -#define LDBL_DIG 16 - /* Difference between 1.0 and the minimum long double greater than 1.0 */ -#undef LDBL_EPSILON -#define LDBL_EPSILON 2.77555756156289135e-17 - /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ -#undef LDBL_MIN_EXP -#define LDBL_MIN_EXP (-127) - /* Minimum normalised long double */ -#undef LDBL_MIN -#define LDBL_MIN 2.93873587705571877e-39 - /* Minimum int x such that 10**x is a normalised long double */ -#undef LDBL_MIN_10_EXP -#define LDBL_MIN_10_EXP (-38) - /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ -#undef LDBL_MAX_EXP -#define LDBL_MAX_EXP 127 - /* Maximum long double */ -#undef LDBL_MAX -#define LDBL_MAX 1.70141183460469229e+38 - /* Maximum int x such that 10**x is a representable long double */ -#undef LDBL_MAX_10_EXP -#define LDBL_MAX_10_EXP 38 - -#endif /* _FLOAT_H_ */ diff --git a/gcc/config/fr30/crti.asm b/gcc/config/fr30/crti.asm deleted file mode 100755 index 9182366..0000000 --- a/gcc/config/fr30/crti.asm +++ /dev/null @@ -1,75 +0,0 @@ -# crti.s for ELF - -# Copyright (C) 1992, 1998 Free Software Foundation, Inc. -# Written By David Vinayak Henkel-Wallace, June 1992 -# -# 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, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, 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. -# - -# This file just make a stack frame for the contents of the .fini and -# .init sections. Users may put any desired instructions in those -# sections. - - .file "crti.asm" - - .section ".init" - .global _init - .type _init,#function - .align 4 -_init: - st rp, @-r15 - enter #0 - - # These nops are here to align the end of this code with a 16 byte - # boundary. The linker will start inserting code into the .init - # section at such a boundary. - - nop - nop - nop - nop - nop - nop - - - .section ".fini" - .global _fini - .type _fini,#function - .align 4 -_fini: - st rp, @-r15 - enter #0 - nop - nop - nop - nop - nop - nop - \ No newline at end of file diff --git a/gcc/config/fr30/crtn.asm b/gcc/config/fr30/crtn.asm deleted file mode 100755 index 93b52c2..0000000 --- a/gcc/config/fr30/crtn.asm +++ /dev/null @@ -1,57 +0,0 @@ -# crtn.asm for ELF - -# Copyright (C) 1992, 1999 Free Software Foundation, Inc. -# Written By David Vinayak Henkel-Wallace, June 1992 -# -# 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, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, 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. -# - -# This file just makes sure that the .fini and .init sections do in -# fact return. Users may put any desired instructions in those sections. -# This file is the last thing linked into any executable. - - .file "crtn.s" - - .section ".init" - .align 4 - - leave - ld @r15+,rp - ret - - - .section ".fini" - .align 4 - - leave - ld @r15+,rp - ret - -# Th-th-th-that is all folks! diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c deleted file mode 100755 index dcf8a39..0000000 --- a/gcc/config/fr30/fr30.c +++ /dev/null @@ -1,804 +0,0 @@ -/* CYGNUS LOCAL -- nickc/fr30 */ - -/*{{{ Introduction */ - -/* FR30 specific functions. - Copyright (C) 1998, 1999 Free Software Foundation, Inc. - Contributed by Cygnus Solutions. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/*}}}*/ -/*{{{ Includes */ - -#include -#include -#include /* so that MIn and MAX are defined before machmode.h */ -#include "config.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "recog.h" -#include "expr.h" -#include "obstack.h" -#include "tree.h" -#include "except.h" -#include "function.h" - -/*}}}*/ -/*{{{ Function Prologues & Epilogues */ - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -struct rtx_def * fr30_compare_op0; -struct rtx_def * fr30_compare_op1; - -/* The FR30 stack looks like this: - - Before call After call - FP ->| | | | - +-----------------------+ +-----------------------+ high - | | | | memory - | local variables, | | local variables, | - | reg save area, etc. | | reg save area, etc. | - | | | | - +-----------------------+ +-----------------------+ - | | | | - | args to the func that | | args to this func. | - | is being called that | | | - SP ->| do not fit in regs | | | - +-----------------------+ +-----------------------+ - | args that used to be | \ - | in regs; only created | | pretend_size - AP-> | for vararg funcs | / - +-----------------------+ - | | \ - | register save area | | - | | | - +-----------------------+ | reg_size - | return address | | - +-----------------------+ | - FP ->| previous frame ptr | / - +-----------------------+ - | | \ - | local variables | | var_size - | | / - +-----------------------+ - | | \ - low | room for args to | | - memory | other funcs called | | args_size - | from this one | | - SP ->| | / - +-----------------------+ - - Note, AP is a fake hard register. It will be eliminated in favour of - SP or FP as appropriate. - - Note, Some or all of the stack sections above may be omitted if they - are not needed. */ - -/* Structure to be filled in by fr30_compute_frame_size() with register - save masks, and offsets for the current function. */ -struct fr30_frame_info -{ - unsigned int total_size; /* # Bytes that the entire frame takes up. */ - unsigned int pretend_size; /* # Bytes we push and pretend caller did. */ - unsigned int args_size; /* # Bytes that outgoing arguments take up. */ - unsigned int reg_size; /* # Bytes needed to store regs. */ - unsigned int var_size; /* # Bytes that variables take up. */ - unsigned int frame_size; /* # Bytes in current frame. */ - unsigned int gmask; /* Mask of saved registers. */ - unsigned int save_fp; /* Nonzero if frame pointer must be saved. */ - unsigned int save_rp; /* Nonzero if return popinter must be saved. */ - int initialised; /* Nonzero if frame size already calculated. */ -}; - -/* Current frame information calculated by fr30_compute_frame_size(). */ -static struct fr30_frame_info current_frame_info; - -/* Zero structure to initialize current_frame_info. */ -static struct fr30_frame_info zero_frame_info; - -#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) -#define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM)) - -/* Tell prologue and epilogue if register REGNO should be saved / restored. - The return address and frame pointer are treated separately. - Don't consider them here. */ -#define MUST_SAVE_REGISTER(regno) \ - ( (regno) != RETURN_POINTER_REGNUM \ - && (regno) != FRAME_POINTER_REGNUM \ - && regs_ever_live [regno] \ - && ! call_used_regs [regno] ) - -#define MUST_SAVE_FRAME_POINTER (regs_ever_live [FRAME_POINTER_REGNUM] || frame_pointer_needed) -#define MUST_SAVE_RETURN_POINTER (regs_ever_live [RETURN_POINTER_REGNUM] || profile_flag) - -#if UNITS_PER_WORD == 4 -#define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3) -#endif - -/* Returns the number of bytes offset between FROM_REG and TO_REG - for the current function. As a side effect it fills in the - current_frame_info structure, if the data is available. */ -unsigned int -fr30_compute_frame_size (from_reg, to_reg) - int from_reg; - int to_reg; -{ - int regno; - unsigned int return_value; - unsigned int var_size; - unsigned int args_size; - unsigned int pretend_size; - unsigned int extra_size; - unsigned int reg_size; - unsigned int gmask; - - var_size = WORD_ALIGN (get_frame_size ()); - args_size = WORD_ALIGN (current_function_outgoing_args_size); - pretend_size = current_function_pretend_args_size; - - reg_size = 0; - gmask = 0; - - /* Calculate space needed for registers. */ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++) - { - if (MUST_SAVE_REGISTER (regno)) - { - reg_size += UNITS_PER_WORD; - gmask |= 1 << regno; - } - } - - current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER; - current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER; - - reg_size += (current_frame_info.save_fp + current_frame_info.save_rp) - * UNITS_PER_WORD; - - /* Save computed information. */ - current_frame_info.pretend_size = pretend_size; - current_frame_info.var_size = var_size; - current_frame_info.args_size = args_size; - current_frame_info.reg_size = reg_size; - current_frame_info.frame_size = args_size + var_size; - current_frame_info.total_size = args_size + var_size + reg_size + pretend_size; - current_frame_info.gmask = gmask; - current_frame_info.initialised = reload_completed; - - /* Calculate the required distance. */ - return_value = 0; - - if (to_reg == STACK_POINTER_REGNUM) - return_value += args_size + var_size; - - if (from_reg == ARG_POINTER_REGNUM) - return_value += reg_size; - - return return_value; -} - -/* Called after register allocation to add any instructions needed for the - prologue. Using a prologue insn is favored compared to putting all of the - instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler - to intermix instructions with the saves of the caller saved registers. In - some cases, it might be necessary to emit a barrier instruction as the last - insn to prevent such scheduling. */ - -void -fr30_expand_prologue () -{ - int regno; - - if (! current_frame_info.initialised) - fr30_compute_frame_size (0, 0); - - /* This cases shouldn't happen. Catch it now. */ - if (current_frame_info.total_size == 0 - && current_frame_info.gmask) - abort (); - - /* Allocate space for register arguments if this is a variadic function. */ - if (current_frame_info.pretend_size) - { - int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD; - - /* Push argument registers into the pretend arg area. */ - for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;) - emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno))); - } - - if (current_frame_info.gmask) - { - /* Save any needed call-saved regs. */ - for (regno = STACK_POINTER_REGNUM; regno--;) - { - if ((current_frame_info.gmask & (1 << regno)) != 0) - emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno))); - } - } - - /* Save return address if necessary. */ - if (current_frame_info.save_rp) - emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM))); - - /* Save old frame pointer and create new one, if necessary. */ - if (current_frame_info.save_fp) - { - if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD)) - emit_insn (gen_enter_func (GEN_INT (current_frame_info.frame_size + UNITS_PER_WORD))); - else - { - emit_insn (gen_movsi_push (frame_pointer_rtx)); - emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); - } - } - - /* Allocate the stack frame. */ - if (current_frame_info.frame_size == 0) - ; /* Nothing to do. */ - else if (current_frame_info.save_fp - && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD)) - ; /* Nothing to do. */ - else if (current_frame_info.frame_size <= 512) - emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size))); - else - { - rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM); - emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size))); - emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp)); - } - - if (profile_flag || profile_block_flag) - emit_insn (gen_blockage ()); -} - -/* Called after register allocation to add any instructions needed for the - epilogue. Using a epilogue insn is favored compared to putting all of the - instructions in the FUNCTION_EPILOGUE macro, since it allows the scheduler - to intermix instructions with the restores of the caller saved registers. - In some cases, it might be necessary to emit a barrier instruction as the - first insn to prevent such scheduling. */ -void -fr30_expand_epilogue () -{ - int regno; - - /* Perform the inversion operations of the prologue. */ - if (! current_frame_info.initialised) - abort (); - - /* Pop local variables and arguments off the stack. - If frame_pointer_needed is TRUE then the frame pointer register - has actually been used as a frame pointer, and we can recover - the stack pointer from it, otherwise we must unwind the stack - manually. */ - if (current_frame_info.frame_size > 0) - { - if (current_frame_info.save_fp && frame_pointer_needed) - { - emit_insn (gen_leave_func ()); - current_frame_info.save_fp = 0; - } - else if (current_frame_info.frame_size <= 508) - emit_insn (gen_add_to_stack - (GEN_INT (current_frame_info.frame_size))); - else - { - rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM); - emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size))); - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp)); - } - } - - if (current_frame_info.save_fp) - emit_insn (gen_movsi_pop (frame_pointer_rtx)); - - /* Pop all the registers that were pushed. */ - if (current_frame_info.save_rp) - emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM))); - - for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++) - if (current_frame_info.gmask & (1 << regno)) - emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno))); - - if (current_frame_info.pretend_size) - emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size))); - - /* Reset state info for each function. */ - current_frame_info = zero_frame_info; - - emit_insn (gen_return_from_func ()); -} - -/* Do any needed setup for a variadic function. We must create a register - parameter block, and then copy any anonymous arguments, plus the last - named argument, from registers into memory. * copying actually done in - fr30_expand_prologue(). - - ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument - which has type TYPE and mode MODE, and we rely on this fact. */ -void -fr30_setup_incoming_varargs (arg_regs_used_so_far, int_mode, type, pretend_size) - CUMULATIVE_ARGS arg_regs_used_so_far; - int int_mode; - tree type; - int * pretend_size; -{ - enum machine_mode mode = (enum machine_mode)int_mode; - int first_anon_arg; - int size; - rtx regblock; - - - /* All BLKmode values are passed by reference. */ - if (mode == BLKmode) - abort (); - -#if STRICT_ARGUMENT_NAMING - /* We must treat `__builtin_va_alist' as an anonymous arg. - But otherwise if STRICT_ARGUMENT_NAMING is true then the - last named arg must not be treated as an anonymous arg. */ - if (! current_function_varargs) - arg_regs_used_so_far += fr30_num_arg_regs (int_mode, type); -#endif - - size = FR30_NUM_ARG_REGS - arg_regs_used_so_far; - - if (size <= 0) - return; - - * pretend_size = (size * UNITS_PER_WORD); -} - -/*}}}*/ -/*{{{ Printing operands */ - -/* Print a memory address as an operand to reference that memory location. */ - -void -fr30_print_operand_address (stream, address) - FILE * stream; - rtx address; -{ - switch (GET_CODE (address)) - { - case SYMBOL_REF: - output_addr_const (stream, address); - break; - - default: - fprintf (stderr, "code = %x\n", GET_CODE (address)); - debug_rtx (address); - output_operand_lossage ("fr30_print_operand_address: unhandled address"); - break; - } -} - -/* Print an operand. */ - -void -fr30_print_operand (file, x, code) - FILE * file; - rtx x; - int code; -{ - rtx x0; - - switch (code) - { - case '#': - /* Output a :D if this instruction is delayed. */ - if (dbr_sequence_length () != 0) - fputs (":D", file); - return; - - case 'p': - /* Compute the register name of the second register in a hi/lo - register pair. */ - if (GET_CODE (x) != REG) - output_operand_lossage ("fr30_print_operand: unrecognised %p code"); - else - fprintf (file, "r%d", REGNO (x) + 1); - return; - - case 'b': - /* Convert GCC's comparison operators into FR30 comparison codes. */ - switch (GET_CODE (x)) - { - case EQ: fprintf (file, "eq"); break; - case NE: fprintf (file, "ne"); break; - case LT: fprintf (file, "lt"); break; - case LE: fprintf (file, "le"); break; - case GT: fprintf (file, "gt"); break; - case GE: fprintf (file, "ge"); break; - case LTU: fprintf (file, "c"); break; - case LEU: fprintf (file, "ls"); break; - case GTU: fprintf (file, "hi"); break; - case GEU: fprintf (file, "nc"); break; - default: - output_operand_lossage ("fr30_print_operand: unrecognised %b code"); - break; - } - return; - - case 'B': - /* Convert GCC's comparison operators into the complimentary FR30 - comparison codes. */ - switch (GET_CODE (x)) - { - case EQ: fprintf (file, "ne"); break; - case NE: fprintf (file, "eq"); break; - case LT: fprintf (file, "ge"); break; - case LE: fprintf (file, "gt"); break; - case GT: fprintf (file, "le"); break; - case GE: fprintf (file, "lt"); break; - case LTU: fprintf (file, "nc"); break; - case LEU: fprintf (file, "hi"); break; - case GTU: fprintf (file, "ls"); break; - case GEU: fprintf (file, "c"); break; - default: - output_operand_lossage ("fr30_print_operand: unrecognised %B code"); - break; - } - return; - - case 'A': - /* Print a signed byte value as an unsigned value. */ - if (GET_CODE (x) != CONST_INT) - output_operand_lossage ("fr30_print_operand: invalid operand to %A code"); - else - { - HOST_WIDE_INT val; - - val = INTVAL (x); - - val &= 0xff; - - fprintf (file, "%d", val); - } - return; - - case 'x': - if (GET_CODE (x) != CONST_INT - || INTVAL (x) < 16 - || INTVAL (x) > 32) - output_operand_lossage ("fr30_print_operand: invalid %x code"); - else - fprintf (file, "%d", INTVAL (x) - 16); - return; - - case 'F': - if (GET_CODE (x) != CONST_DOUBLE) - output_operand_lossage ("fr30_print_operand: invalid %F code"); - else - { - REAL_VALUE_TYPE d; - - REAL_VALUE_FROM_CONST_DOUBLE (d, x); - fprintf (file, "%.8f", d); - } - return; - - case 0: - /* Handled below. */ - break; - - default: - fprintf (stderr, "unknown code = %x\n", code); - output_operand_lossage ("fr30_print_operand: unknown code"); - return; - } - - switch (GET_CODE (x)) - { - case REG: - fputs (reg_names [REGNO (x)], file); - break; - - case MEM: - x0 = XEXP (x,0); - - switch (GET_CODE (x0)) - { - case REG: - if (REGNO (x0) >= (sizeof (reg_names) / sizeof (reg_names[0]))) - abort (); - fprintf (file, "@%s", reg_names [REGNO (x0)]); - break; - - case PLUS: - if (GET_CODE (XEXP (x0, 0)) != REG - || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM - || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM - || GET_CODE (XEXP (x0, 1)) != CONST_INT) - { - fprintf (stderr, "bad INDEXed address:"); - debug_rtx (x); - output_operand_lossage ("fr30_print_operand: unhandled MEM"); - } - else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM) - { - HOST_WIDE_INT val = INTVAL (XEXP (x0, 1)); - if (val < -(1 << 9) || val > ((1 << 9) - 4)) - { - fprintf (stderr, "frame INDEX out of range:"); - debug_rtx (x); - output_operand_lossage ("fr30_print_operand: unhandled MEM"); - } - fprintf (file, "@(r14, #%d)", val); - } - else - { - HOST_WIDE_INT val = INTVAL (XEXP (x0, 1)); - if (val < 0 || val > ((1 << 6) - 4)) - { - fprintf (stderr, "stack INDEX out of range:"); - debug_rtx (x); - output_operand_lossage ("fr30_print_operand: unhandled MEM"); - } - fprintf (file, "@(r15, #%d)", val); - } - break; - - case SYMBOL_REF: - output_address (x0); - break; - - default: - fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0)); - debug_rtx (x); - output_operand_lossage ("fr30_print_operand: unhandled MEM"); - break; - } - break; - - case CONST_DOUBLE : - /* We handle SFmode constants here as output_addr_const doesn't. */ - if (GET_MODE (x) == SFmode) - { - REAL_VALUE_TYPE d; - long l; - - REAL_VALUE_FROM_CONST_DOUBLE (d, x); - REAL_VALUE_TO_TARGET_SINGLE (d, l); - fprintf (file, "0x%08lx", l); - break; - } - - /* Fall through. Let output_addr_const deal with it. */ - default: - output_addr_const (file, x); - break; - } - - return; -} - -/*}}}*/ -/*{{{ Function arguments */ - -/* Compute the number of word sized registers needed to hold a - function argument of mode INT_MODE and tree type TYPE. */ -int -fr30_num_arg_regs (int_mode, type) - int int_mode; - tree type; -{ - enum machine_mode mode = (enum machine_mode) int_mode; - int size; - - if (MUST_PASS_IN_STACK (mode, type)) - return 0; - - if (type && mode == BLKmode) - size = int_size_in_bytes (type); - else - size = GET_MODE_SIZE (mode); - - return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; -} - -/* Implements the FUNCTION_ARG_PARTIAL_NREGS macro. - Returns the number of argument registers required to hold *part* of - a parameter of machine mode MODE and tree type TYPE (which may be - NULL if the type is not known). If the argument fits entirly in - the argument registers, or entirely on the stack, then 0 is returned. - CUM is the number of argument registers already used by earlier - parameters to the function. */ - -int -fr30_function_arg_partial_nregs (cum, int_mode, type, named) - CUMULATIVE_ARGS cum; - int int_mode; - tree type; - int named; -{ - /* Unnamed arguments, ie those that are prototyped as ... - are always passed on the stack. - Also check here to see if all the argument registers are full. */ - if (named == 0 || cum >= FR30_NUM_ARG_REGS) - return 0; - - /* Work out how many argument registers would be needed if this - parameter were to be passed entirely in registers. If there - are sufficient argument registers available (or if no registers - are needed because the parameter must be passed on the stack) - then return zero, as this parameter does not require partial - register, partial stack stack space. */ - if (cum + fr30_num_arg_regs (int_mode, type) <= FR30_NUM_ARG_REGS) - return 0; - - /* Otherwise return the number of registers that would be used. */ - return FR30_NUM_ARG_REGS - cum; -} - -/*}}}*/ -/*{{{ Operand predicates */ - -/* Returns true if OPERAND is an integer value suitable for use in - an ADDSP instruction. */ -int -stack_add_operand (operand, int_mode) - rtx operand; - int int_mode; -{ - return - (GET_CODE (operand) == CONST_INT - && INTVAL (operand) >= -512 - && INTVAL (operand) <= 508 - && ((INTVAL (operand) & 3) == 0)); -} - -/* Returns true if OPERAND is an integer value suitable for use in - an ADD por ADD2 instruction, or if it is a register. */ -int -add_immediate_operand (operand, int_mode) - rtx operand; - int int_mode; -{ - return - (GET_CODE (operand) == REG - || (GET_CODE (operand) == CONST_INT - && INTVAL (operand) >= -16 - && INTVAL (operand) <= 15)); -} - -/* Returns true if OPERAND is hard register in the range 8 - 15. */ -int -high_register_operand (operand, int_mode) - rtx operand; - int int_mode; -{ - return - (GET_CODE (operand) == REG - && REGNO (operand) <= 15 - && REGNO (operand) >= 8); -} - -/* Returns true if OPERAND is hard register in the range 0 - 7. */ -int -low_register_operand (operand, int_mode) - rtx operand; - int int_mode; -{ - return - (GET_CODE (operand) == REG - && REGNO (operand) <= 7 - && REGNO (operand) >= 0); -} - -/* Returns true if OPERAND is suitable for use in a CALL insn. */ -int -call_operand (operand, int_mode) - rtx operand; - int int_mode; -{ - enum machine_mode mode = (enum machine_mode) int_mode; - - return nonimmediate_operand (operand, mode) - || (GET_CODE (operand) == MEM - && GET_CODE (XEXP (operand, 0)) == SYMBOL_REF); -} - -/* Returns true if OPERAND is a displacement suitable for use in a - frame pointer based load or store. */ -int -fp_displacement_operand (operand, int_mode) - rtx operand; - int int_mode; -{ - return (GET_CODE (operand) == CONST_INT - && ((INTVAL (operand) & 0x3) == 0) - && (INTVAL (operand) <= ((1 << 9) - 1)) - && (INTVAL (operand) >= (- (1 << 9)))); -} - -/* Returns true if OPERAND is a displacement suitable for use in a - stack pointer based load or store. */ -int -sp_displacement_operand (operand, int_mode) - rtx operand; - int int_mode; -{ - return (GET_CODE (operand) == CONST_INT - && ((INTVAL (operand) & 0x3) == 0) - && (INTVAL (operand) <= ((1 << 6) - 1)) - && (INTVAL (operand) >= 0)); -} - -/* Returns true iff all the registers in the operands array - are in descending or ascending order. */ -int -fr30_check_multiple_regs (operands, num_operands, descending) - rtx * operands; - int num_operands; - int descending; -{ - if (descending) - { - int prev_regno = -1; - - while (num_operands--) - { - if (GET_CODE (operands [num_operands]) != REG) - return 0; - - if (REGNO (operands [num_operands]) < prev_regno) - return 0; - - prev_regno = REGNO (operands [num_operands]); - } - } - else - { - int prev_regno = CONDITION_CODE_REGNUM; - - while (num_operands--) - { - if (GET_CODE (operands [num_operands]) != REG) - return 0; - - if (REGNO (operands [num_operands]) > prev_regno) - return 0; - - prev_regno = REGNO (operands [num_operands]); - } - } - - return 1; -} - -/*}}}*/ - -/* Local Variables: */ -/* folded-file: t */ -/* End: */ - -/* END CYGNUS LOCAL -- nickc/fr30 */ - diff --git a/gcc/config/fr30/fr30.h b/gcc/config/fr30/fr30.h deleted file mode 100755 index e0b37b1..0000000 --- a/gcc/config/fr30/fr30.h +++ /dev/null @@ -1,4496 +0,0 @@ -/* CYGNUS LOCAL -- nickc/entire file */ - -/*{{{ Comment */ - -/* Definitions of FR30 target. - Copyright (C) 1998, 1999 Free Software Foundation, Inc. - Contributed by Cygnus Solutions. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/*}}}*/ -/*{{{ Includes */ - -/* Set up System V.4 (aka ELF) defaults. */ -#include "svr4.h" - -/* Include prototyping macros */ -#include "gansidecl.h" - -/*}}}*/ -/*{{{ Forward strcuture declarations for use in prototypes. */ - -#ifdef BUFSIZ /* stdio.h has been included, ok to use FILE * */ -#define STDIO_PROTO(ARGS) PROTO(ARGS) -#else -#define STDIO_PROTO(ARGS) () -#endif - -#ifndef RTX_CODE -struct rtx_def; -#define Rtx struct rtx_def * -#else -#define Rtx rtx -#endif - -#ifndef TREE_CODE -union tree_node; -#define Tree union tree_node * -#else -#define Tree tree -#endif - -/*}}}*/ -/*{{{ Driver configuration */ - -/* A C expression which determines whether the option `-CHAR' takes arguments. - The value should be the number of arguments that option takes-zero, for many - options. - - By default, this macro is defined to handle the standard options properly. - You need not define it unless you wish to add additional options which take - arguments. - - Defined in svr4.h. */ -#undef SWITCH_TAKES_ARG - -/* A C expression which determines whether the option `-NAME' takes arguments. - The value should be the number of arguments that option takes-zero, for many - options. This macro rather than `SWITCH_TAKES_ARG' is used for - multi-character option names. - - By default, this macro is defined as `DEFAULT_WORD_SWITCH_TAKES_ARG', which - handles the standard options properly. You need not define - `WORD_SWITCH_TAKES_ARG' unless you wish to add additional options which take - arguments. Any redefinition should call `DEFAULT_WORD_SWITCH_TAKES_ARG' and - then check for additional options. - - Defined in svr4.h. */ -#undef WORD_SWITCH_TAKES_ARG - -/*}}}*/ -/*{{{ Run-time target specifications */ - -#undef ASM_SPEC -#define ASM_SPEC "%{v}" - -/* Define this to be a string constant containing `-D' options to define the - predefined macros that identify this machine and system. These macros will - be predefined unless the `-ansi' option is specified. */ - -#define CPP_PREDEFINES "-Dfr30 -D__fr30__ -Amachine(fr30)" - -/* Use LDI:20 instead of LDI:32 to load addresses. */ -#define TARGET_SMALL_MODEL_MASK (1 << 0) -#define TARGET_SMALL_MODEL (target_flags & TARGET_SMALL_MODEL_MASK) - -#define TARGET_DEFAULT 0 - -/* This declaration should be present. */ -extern int target_flags; - -#define TARGET_SWITCHES \ -{ \ - { "small-model", TARGET_SMALL_MODEL_MASK, "Assume small address space" }, \ - { "no-small-model", - TARGET_SMALL_MODEL_MASK, "" }, \ - { "", TARGET_DEFAULT } \ -} - -#define TARGET_VERSION fprintf (stderr, " (fr30)"); - -/* Define this macro if debugging can be performed even without a frame - pointer. If this macro is defined, GNU CC will turn on the - `-fomit-frame-pointer' option whenever `-O' is specified. */ -#define CAN_DEBUG_WITHOUT_FP - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s" - -/* Include the OS stub library, so that the code can be simulated. - This is not the right way to do this. Ideally this kind of thing - should be done in the linker script - but I have not worked out how - to specify the location of a linker script in a gcc command line yet... */ -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "-lsim crtend.o%s crtn.o%s" - -/*}}}*/ -/*{{{ Storage Layout */ - -/* Define this macro to have the value 1 if the most significant bit in a byte - has the lowest number; otherwise define it to have the value zero. This - means that bit-field instructions count from the most significant bit. If - the machine has no bit-field instructions, then this must still be defined, - but it doesn't matter which value it is defined to. This macro need not be - a constant. - - This macro does not affect the way structure fields are packed into bytes or - words; that is controlled by `BYTES_BIG_ENDIAN'. */ -#define BITS_BIG_ENDIAN 1 - -/* Define this macro to have the value 1 if the most significant byte in a word - has the lowest number. This macro need not be a constant. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this macro to have the value 1 if, in a multiword object, the most - significant word has the lowest number. This applies to both memory - locations and registers; GNU CC fundamentally assumes that the order of - words in memory is the same as the order in registers. This macro need not - be a constant. */ -#define WORDS_BIG_ENDIAN 1 - -/* Define this macro to be the number of bits in an addressable storage unit - (byte); normally 8. */ -#define BITS_PER_UNIT 8 - -/* Number of bits in a word; normally 32. */ -#define BITS_PER_WORD 32 - -/* Number of storage units in a word; normally 4. */ -#define UNITS_PER_WORD 4 - -/* Width of a pointer, in bits. You must specify a value no wider than the - width of `Pmode'. If it is not equal to the width of `Pmode', you must - define `POINTERS_EXTEND_UNSIGNED'. */ -#define POINTER_SIZE 32 - -/* 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. - - On most RISC machines, which only have operations that operate on a full - register, define this macro to set M to `word_mode' if M is an integer mode - narrower than `BITS_PER_WORD'. In most cases, only integer modes should be - widened because wider-precision floating-point operations are usually more - expensive than their narrower counterparts. - - For most machines, the macro definition does not change UNSIGNEDP. However, - some machines, have instructions that preferentially handle either signed or - unsigned quantities of certain modes. For example, on the DEC Alpha, 32-bit - loads from memory and 32-bit add instructions sign-extend the result to 64 - bits. On such machines, set UNSIGNEDP according to which kind of extension - is more efficient. - - Do not define this macro if it would never modify MODE. */ -#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ -do { \ - if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < 4) \ - (MODE) = SImode; \ -} while (0) - -/* Normal alignment required for function parameters on the stack, in bits. - All stack parameters receive at least this much alignment regardless of data - type. On most machines, this is the same as the size of an integer. */ -#define PARM_BOUNDARY 32 - -/* Define this macro if you wish to preserve a certain alignment for the stack - pointer. The definition is a C expression for the desired alignment - (measured in bits). - - If `PUSH_ROUNDING' is not defined, the stack will always be aligned to the - specified boundary. If `PUSH_ROUNDING' is defined and specifies a less - strict alignment than `STACK_BOUNDARY', the stack may be momentarily - unaligned while pushing arguments. */ -#define STACK_BOUNDARY 32 - -/* Alignment required for a function entry point, in bits. */ -#define FUNCTION_BOUNDARY 32 - -/* Biggest alignment that any data type can require on this machine, - in bits. */ -#define BIGGEST_ALIGNMENT 32 - -/* 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. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -/* 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 \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -/* Alignment in bits to be given to a structure bit field that follows an empty - field such as `int : 0;'. - - Note that `PCC_BITFIELD_TYPE_MATTERS' also affects the alignment that - results from an empty field. */ -/* #define EMPTY_FIELD_BOUNDARY */ - -/* Number of bits which any structure or union's size must be a multiple of. - Each structure or union's size is rounded up to a multiple of this. - - If you do not define this macro, the default is the same as `BITS_PER_UNIT'. */ -/* #define STRUCTURE_SIZE_BOUNDARY */ - -/* Define this macro to be the value 1 if instructions will fail to work if - given data not on the nominal alignment. If instructions will merely go - slower in that case, define this macro as 0. */ -#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 bitfield (`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 bitfield 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 bitfield 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. - - Note that if this macro is not defined, or its value is zero, some bitfields - may cross more than one alignment boundary. The compiler can support such - references if there are `insv', `extv', and `extzv' insns that can directly - reference memory. - - The other known way of making bitfields work is to define - `STRUCTURE_SIZE_BOUNDARY' as large as `BIGGEST_ALIGNMENT'. Then every - structure can be accessed with fullwords. - - Unless the machine has bitfield instructions or you define - `STRUCTURE_SIZE_BOUNDARY' that way, you must define - `PCC_BITFIELD_TYPE_MATTERS' to have a nonzero value. - - If your aim is to make GNU CC use the same conventions for laying out - bitfields as are used by another compiler, here is how to investigate what - the other compiler does. Compile and run this program: - - struct foo1 - { - char x; - char :0; - char y; - }; - - struct foo2 - { - char x; - int :0; - char y; - }; - - main () - { - printf ("Size of foo1 is %d\n", - sizeof (struct foo1)); - printf ("Size of foo2 is %d\n", - sizeof (struct foo2)); - exit (0); - } - - If this prints 2 and 5, then the compiler's behavior is what you would get - from `PCC_BITFIELD_TYPE_MATTERS'. - - Defined in svr4.h. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* A code distinguishing the floating point format of the target machine. - There are three defined values: - - IEEE_FLOAT_FORMAT' - This code indicates IEEE floating point. It is the default; - there is no need to define this macro when the format is IEEE. - - VAX_FLOAT_FORMAT' - This code indicates the peculiar format used on the Vax. - - UNKNOWN_FLOAT_FORMAT' - This code indicates any other format. - - The value of this macro is compared with `HOST_FLOAT_FORMAT' - to determine whether the target machine has the same format as - the host machine. If any other formats are actually in use on supported - machines, new codes should be defined for them. - - The ordering of the component words of floating point values stored in - memory is controlled by `FLOAT_WORDS_BIG_ENDIAN' for the target machine and - `HOST_FLOAT_WORDS_BIG_ENDIAN' for the host. */ -#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT - -/* GNU CC supports two ways of implementing C++ vtables: traditional or with - so-called "thunks". The flag `-fvtable-thunk' chooses between them. Define - this macro to be a C expression for the default value of that flag. If - `DEFAULT_VTABLE_THUNKS' is 0, GNU CC uses the traditional implementation by - default. The "thunk" implementation is more efficient (especially if you - have provided an implementation of `ASM_OUTPUT_MI_THUNK', but is not binary - compatible with code compiled using the traditional implementation. If you - are writing a new ports, define `DEFAULT_VTABLE_THUNKS' to 1. - - If you do not define this macro, the default for `-fvtable-thunk' is 0. */ -#define DEFAULT_VTABLE_THUNKS 1 - -/*}}}*/ -/*{{{ Layout of Source Language Data Types */ - -#define CHAR_TYPE_SIZE 8 -#define SHORT_TYPE_SIZE 16 -#define INT_TYPE_SIZE 32 -#define LONG_TYPE_SIZE 32 -#define LONG_LONG_TYPE_SIZE 64 -#define FLOAT_TYPE_SIZE 32 -#define DOUBLE_TYPE_SIZE 64 -#define LONG_DOUBLE_TYPE_SIZE 64 - -/* An expression whose value is 1 or 0, according to whether the type `char' - should be signed or unsigned by default. The user can always override this - default with the options `-fsigned-char' and `-funsigned-char'. */ -#define DEFAULT_SIGNED_CHAR 1 - -#define TARGET_BELL 0x7 /* '\a' */ -#define TARGET_BS 0x8 /* '\b' */ -#define TARGET_TAB 0x9 /* '\t' */ -#define TARGET_NEWLINE 0xa /* '\n' */ -#define TARGET_VT 0xb /* '\v' */ -#define TARGET_FF 0xc /* '\f' */ -#define TARGET_CR 0xd /* '\r' */ - -/*}}}*/ -/*{{{ Register Basics */ - -/* Number of hardware registers known to the compiler. They receive numbers 0 - through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number - really is assigned the number `FIRST_PSEUDO_REGISTER'. */ -#define FIRST_PSEUDO_REGISTER 21 - -/* Fixed register assignments: */ - -/* Here we do a bad thing - reserve a register for use by the machine - description file. There are too many places in compiler where it - assumes that it can issue a branch or jump instruction without - providing a scratch register for it, and reload just cannot cope, so - we keepo a register back for these situations. */ -#define COMPILER_SCRATCH_REGISTER 0 - -/* The register that contains the result of a function call. */ -#define RETURN_VALUE_REGNUM 4 - -/* The first register that can contain the arguments to a function. */ -#define FIRST_ARG_REGNUM 4 - -/* A call-used register that can be used during the function prologue. */ -#define PROLOGUE_TMP_REGNUM COMPILER_SCRATCH_REGISTER - -/* Register numbers used for passing a function's static chain pointer. If - register windows are used, the register number as seen by the called - function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as - seen by the calling function is `STATIC_CHAIN_REGNUM'. If these registers - are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined. - - The static chain register need not be a fixed register. - - If the static chain is passed in memory, these macros should not be defined; - instead, the next two macros should be defined. */ -#define STATIC_CHAIN_REGNUM 12 -/* #define STATIC_CHAIN_INCOMING_REGNUM */ - -/* An FR30 specific hardware register. */ -#define ACCUMULATOR_REGNUM 13 - -/* The register number of the frame pointer register, which is used to access - automatic variables in the stack frame. On some machines, the hardware - determines which register this is. On other machines, you can choose any - register you wish for this purpose. */ -#define FRAME_POINTER_REGNUM 14 - -/* The register number of the stack pointer register, which must also be a - fixed register according to `FIXED_REGISTERS'. On most machines, the - hardware determines which register this is. */ -#define STACK_POINTER_REGNUM 15 - -/* The following a fake hard registers that describe some of the dedicated - registers on the FR30. */ -#define CONDITION_CODE_REGNUM 16 -#define RETURN_POINTER_REGNUM 17 -#define MD_HIGH_REGNUM 18 -#define MD_LOW_REGNUM 19 - -/* An initializer that says which registers are used for fixed purposes all - throughout the compiled code and are therefore not available for general - allocation. These would include the stack pointer, the frame pointer - (except on machines where that can be used as a general register when no - frame pointer is needed), the program counter on machines where that is - considered one of the addressable registers, and any other numbered register - with a standard use. - - This information is expressed as a sequence of numbers, separated by commas - and surrounded by braces. The Nth number is 1 if register N is fixed, 0 - otherwise. - - The table initialized from this macro, and the table initialized by the - following one, may be overridden at run time either automatically, by the - actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the - command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'. */ -#define FIXED_REGISTERS \ - { 1, 0, 0, 0, 0, 0, 0, 0, /* 0 - 7 */ \ - 0, 0, 0, 0, 0, 0, 0, 1, /* 8 - 15 */ \ - 1, 1, 1, 1, 1 } /* 16 - 20 */ - -/* XXX - MDL and MDH set as fixed for now - this is until I can get the - mul patterns working. */ - -/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in - general) by function calls as well as for fixed registers. This macro - therefore identifies the registers that are not available for general - allocation of values that must live across function calls. - - If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically - saves it on function entry and restores it on function exit, if the register - is used within the function. */ -#define CALL_USED_REGISTERS \ - { 1, 1, 1, 1, 1, 1, 1, 1, /* 0 - 7 */ \ - 0, 0, 0, 0, 1, 1, 0, 1, /* 8 - 15 */ \ - 1, 1, 1, 1, 1 } /* 16 - 20 */ - -/* A C initializer containing the assembler's names for the machine registers, - each one as a C string constant. This is what translates register numbers - in the compiler into assembler language. */ -#define REGISTER_NAMES \ -{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "ac", "fp", "sp", \ - "cc", "rp", "mdh", "mdl", "ap" \ -} - -/* If defined, a C initializer for an array of structures containing a name and - a register number. This macro defines additional names for hard registers, - thus allowing the `asm' option in declarations to refer to registers using - alternate names. */ -#define ADDITIONAL_REGISTER_NAMES \ -{ \ - {"r13", 13}, {"r14", 14}, {"r15", 15}, {"usp", 15}, {"ps", 16}\ -} - -/*}}}*/ -/*{{{ How Values Fit in Registers */ - -/* A C expression for the number of consecutive hard registers, starting at - register number REGNO, required to hold a value of mode MODE. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* A C expression that is nonzero if it is permissible to store a value of mode - MODE in hard register number REGNO (or in several registers starting with - that one). */ - -#define HARD_REGNO_MODE_OK(REGNO, MODE) 1 - -/* A C expression that is nonzero if it is desirable to choose register - allocation so as to avoid move instructions between a value of mode MODE1 - and a value of mode MODE2. - - If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are - ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be - zero. */ -#define MODES_TIEABLE_P(MODE1, MODE2) 1 - -/* Define this macro if the compiler should avoid copies to/from CCmode - registers. You should only define this macro if support fo copying to/from - CCmode is incomplete. */ -/* #define AVOID_CCMODE_COPIES */ - -/*}}}*/ -/*{{{ Register Classes */ - -/* An enumeral type that must be defined with all the register class names as - enumeral values. `NO_REGS' must be first. `ALL_REGS' must be the last - register class, followed by one more enumeral value, `LIM_REG_CLASSES', - which is not a register class but rather tells how many classes there are. - - Each register class has a number, which is the value of casting the class - name to type `int'. The number serves as an index in many of the tables - described below. */ -enum reg_class -{ - NO_REGS, - MULTIPLY_32_REG, /* the MDL register as used by the MULH, MULUH insns */ - MULTIPLY_64_REG, /* the MDH,MDL register pair as used by MUL and MULU */ - LOW_REGS, /* registers 0 through 7 */ - HIGH_REGS, /* registers 8 through 15 */ - REAL_REGS, /* ie all the general hardware registers on the FR30 */ - ALL_REGS, - LIM_REG_CLASSES -}; - -#define GENERAL_REGS REAL_REGS -#define N_REG_CLASSES ((int) LIM_REG_CLASSES) - -/* An initializer containing the names of the register classes as C string - constants. These names are used in writing some of the debugging dumps. */ -#define REG_CLASS_NAMES \ -{ \ - "NO_REGS", \ - "MULTIPLY_32_REG", \ - "MULTIPLY_64_REG", \ - "LOW_REGS", \ - "HIGH_REGS", \ - "REAL_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 \ -{ \ - 0, \ - 1 << MD_LOW_REGNUM, \ - (1 << MD_LOW_REGNUM) | (1 << MD_HIGH_REGNUM), \ - (1 << 8) - 1, \ - ((1 << 8) - 1) << 8, \ - (1 << CONDITION_CODE_REGNUM) - 1, \ - (1 << FIRST_PSEUDO_REGISTER) - 1 \ -} - -/* A C expression whose value is a register class containing hard register - REGNO. In general there is more than one such class; choose a class which - is "minimal", meaning that no smaller class also contains the register. */ -#define REGNO_REG_CLASS(REGNO) \ - ( (REGNO) < 8 ? LOW_REGS \ - : (REGNO) < CONDITION_CODE_REGNUM ? HIGH_REGS \ - : (REGNO) == MD_LOW_REGNUM ? MULTIPLY_32_REG \ - : (REGNO) == MD_HIGH_REGNUM ? MULTIPLY_64_REG \ - : ALL_REGS) - -/* 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 REAL_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 REAL_REGS - -/* A C expression which defines the machine-dependent operand constraint - letters for register classes. If CHAR is such a letter, the value should be - the register class corresponding to it. Otherwise, the value should be - `NO_REGS'. The register letter `r', corresponding to class `GENERAL_REGS', - will not be passed to this macro; you do not need to handle it. - - The following letters are unavailable, due to being used as - constraints: - '0'..'9' - '<', '>' - 'E', 'F', 'G', 'H' - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' - 'Q', 'R', 'S', 'T', 'U' - 'V', 'X' - 'g', 'i', 'm', 'n', 'o', 'p', 'r', 's' */ - -#define REG_CLASS_FROM_LETTER(CHAR) \ - ( (CHAR) == 'd' ? MULTIPLY_64_REG \ - : (CHAR) == 'e' ? MULTIPLY_32_REG \ - : (CHAR) == 'h' ? HIGH_REGS \ - : (CHAR) == 'l' ? LOW_REGS \ - : (CHAR) == 'a' ? ALL_REGS \ - : NO_REGS) - -/* A C expression which is nonzero if register number NUM is suitable for use - as a base register in operand addresses. It may be either a suitable hard - register or a pseudo register that has been allocated such a hard register. */ -#define REGNO_OK_FOR_BASE_P(NUM) 1 - -/* A C expression which is nonzero if register number NUM is suitable for use - as an index register in operand addresses. It may be either a suitable hard - register or a pseudo register that has been allocated such a hard register. - - The difference between an index register and a base register is that the - index register may be scaled. If an address involves the sum of two - registers, neither one of them scaled, then either one may be labeled the - "base" and the other the "index"; but whichever labeling is used must fit - the machine's constraints of which registers may serve in each capacity. - The compiler will try both labelings, looking for one that is valid, and - will reload one or both registers only if neither labeling works. */ -#define REGNO_OK_FOR_INDEX_P(NUM) 1 - -/* A C expression that places additional restrictions on the register class to - use when it is necessary to copy value X into a register in class CLASS. - The value is a register class; perhaps CLASS, or perhaps another, smaller - class. On many machines, the following definition is safe: - - #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS - - Sometimes returning a more restrictive class makes better code. For - example, on the 68000, when X is an integer constant that is in range for a - `moveq' instruction, the value of this macro is always `DATA_REGS' as long - as CLASS includes the data registers. Requiring a data register guarantees - that a `moveq' will be used. - - If X is a `const_double', by returning `NO_REGS' you can force X into a - memory constant. This is useful on certain machines where immediate - floating values cannot be loaded into certain kinds of registers. */ -#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS - -/* Like `PREFERRED_RELOAD_CLASS', but for output reloads instead of input - reloads. If you don't define this macro, the default is to use CLASS, - unchanged. */ -/* #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) */ - -/* A C expression that places additional restrictions on the register class to - use when it is necessary to be able to hold a value of mode MODE in a reload - register for which class CLASS would ordinarily be used. - - Unlike `PREFERRED_RELOAD_CLASS', this macro should be used when there are - certain modes that simply can't go in certain reload classes. - - The value is a register class; perhaps CLASS, or perhaps another, smaller - class. - - Don't define this macro unless the target machine has limitations which - require the macro to do something nontrivial. */ -/* #define LIMIT_RELOAD_CLASS(MODE, CLASS) */ - -/* Many machines have some registers that cannot be copied directly to or from - memory or even from other types of registers. An example is the `MQ' - register, which on most machines, can only be copied to or from general - registers, but not memory. Some machines allow copying all registers to and - from memory, but require a scratch register for stores to some memory - locations (e.g., those with symbolic address on the RT, and those with - certain symbolic address on the Sparc when compiling PIC). In some cases, - both an intermediate and a scratch register are required. - - You should define these macros to indicate to the reload phase that it may - need to allocate at least one register for a reload in addition to the - register to contain the data. Specifically, if copying X to a register - CLASS in MODE requires an intermediate register, you should define - `SECONDARY_INPUT_RELOAD_CLASS' to return the largest register class all of - whose registers can be used as intermediate registers or scratch registers. - - If copying a register CLASS in MODE to X requires an intermediate or scratch - register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be defined to return the - largest register class required. If the requirements for input and output - reloads are the same, the macro `SECONDARY_RELOAD_CLASS' should be used - instead of defining both macros identically. - - The values returned by these macros are often `GENERAL_REGS'. Return - `NO_REGS' if no spare register is needed; i.e., if X can be directly copied - to or from a register of CLASS in MODE without requiring a scratch register. - Do not define this macro if it would always return `NO_REGS'. - - If a scratch register is required (either with or without an intermediate - register), you should define patterns for `reload_inM' or `reload_outM', as - required. These patterns, which will normally be implemented with a - `define_expand', should be similar to the `movM' patterns, except that - operand 2 is the scratch register. - - Define constraints for the reload register and scratch register that contain - a single register class. If the original reload register (whose class is - CLASS) can meet the constraint given in the pattern, the value returned by - these macros is used for the class of the scratch register. Otherwise, two - additional reload registers are required. Their classes are obtained from - the constraints in the insn pattern. - - X might be a pseudo-register or a `subreg' of a pseudo-register, which could - either be in a hard register or in memory. Use `true_regnum' to find out; - it will return -1 if the pseudo is in memory and the hard register number if - it is in a register. - - These macros should not be used in the case where a particular class of - registers can only be copied to memory and not to another class of - registers. In that case, secondary reload registers are not needed and - would not be helpful. Instead, a stack location must be used to perform the - copy and the `movM' pattern should use memory as a intermediate storage. - This case often occurs between floating-point and general registers. */ -/* #define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) */ -/* #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) */ -/* #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) */ - -/* Normally the compiler avoids choosing registers that have been explicitly - mentioned in the rtl as spill registers (these registers are normally those - used to pass parameters and return values). However, some machines have so - few registers of certain classes that there would not be enough registers to - use as spill registers if this were done. - - Define `SMALL_REGISTER_CLASSES' to be an expression with a non-zero value on - these machines. When this macro has a non-zero value, the compiler allows - registers explicitly used in the rtl to be used as spill registers but - avoids extending the lifetime of these registers. - - It is always safe to define this macro with a non-zero value, but if you - unnecessarily define it, you will reduce the amount of optimizations that - can be performed in some cases. If you do not define this macro with a - non-zero value when it is required, the compiler will run out of spill - registers and print a fatal error message. For most machines, you should - not define this macro at all. */ -/* #define SMALL_REGISTER_CLASSES */ - -/* A C expression whose value is nonzero if pseudos that have been assigned to - registers of class CLASS would likely be spilled because registers of CLASS - are needed for spill registers. - - The default value of this macro returns 1 if CLASS has exactly one register - and zero otherwise. On most machines, this default should be used. Only - define this macro to some other expression if pseudo allocated by - `local-alloc.c' end up in memory because their hard registers were needed - for spill registers. If this macro returns nonzero for those classes, those - pseudos will only be allocated by `global.c', which knows how to reallocate - the pseudo to another register. If there would not be another register - available for reallocation, you should not change the definition of this - macro since the only effect of such a definition would be to slow down - register allocation. */ -/* #define CLASS_LIKELY_SPILLED_P(CLASS) */ - -/* A C expression for the maximum number of consecutive registers of - class CLASS needed to hold a value of mode MODE. - - This is closely related to the macro `HARD_REGNO_NREGS'. In fact, the value - of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be the maximum value of - `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO values in the class CLASS. - - This macro helps control the handling of multiple-word values in - the reload pass. */ -#define CLASS_MAX_NREGS(CLASS, MODE) HARD_REGNO_NREGS (0, MODE) - -/* If defined, a C expression for a class that contains registers which the - compiler must always access in a mode that is the same size as the mode in - which it loaded the register. - - For the example, loading 32-bit integer or floating-point objects into - floating-point registers on the Alpha extends them to 64-bits. Therefore - loading a 64-bit object and then storing it as a 32-bit object does not - store the low-order 32-bits, as would be the case for a normal register. - Therefore, `alpha.h' defines this macro as `FLOAT_REGS'. */ -/* #define CLASS_CANNOT_CHANGE_SIZE */ - -/*}}}*/ -/*{{{ CONSTANTS */ - -/* Return true if a value is inside a range */ -#define IN_RANGE(VALUE, LOW, HIGH) \ - ( ((unsigned HOST_WIDE_INT)((VALUE) - (LOW))) \ - <= ((unsigned HOST_WIDE_INT)( (HIGH) - (LOW)))) - -/* A C expression that defines the machine-dependent operand constraint letters - (`I', `J', `K', .. 'P') that specify particular ranges of integer values. - If C is one of those letters, the expression should check that VALUE, an - integer, is in the appropriate range and return 1 if so, 0 otherwise. If C - is not one of those letters, the value should be 0 regardless of VALUE. */ -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ( (C) == 'I' ? IN_RANGE (VALUE, 0, 15) \ - : (C) == 'J' ? IN_RANGE (VALUE, -16, -1) \ - : (C) == 'K' ? IN_RANGE (VALUE, 16, 31) \ - : (C) == 'L' ? IN_RANGE (VALUE, 0, (1 << 8) - 1) \ - : (C) == 'M' ? IN_RANGE (VALUE, 0, (1 << 20) - 1) \ - : (C) == 'P' ? IN_RANGE (VALUE, -(1 << 8), (1 << 8) - 1) \ - : 0) - -/* A C expression that defines the machine-dependent operand constraint letters - (`G', `H') that specify particular ranges of `const_double' values. - - If C is one of those letters, the expression should check that VALUE, an RTX - of code `const_double', is in the appropriate range and return 1 if so, 0 - otherwise. If C is not one of those letters, the value should be 0 - regardless of VALUE. - - `const_double' is used for all floating-point constants and for `DImode' - fixed-point constants. A given letter can accept either or both kinds of - values. It can use `GET_MODE' to distinguish between these kinds. */ -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 - -/* A C expression that defines the optional machine-dependent constraint - letters (`Q', `R', `S', `T', `U') that can be used to segregate specific - types of operands, usually memory references, for the target machine. - Normally this macro will not be defined. If it is required for a particular - target machine, it should return 1 if VALUE corresponds to the operand type - represented by the constraint letter C. If C is not defined as an extra - constraint, the value returned should be 0 regardless of VALUE. - - For example, on the ROMP, load instructions cannot have their output in r0 - if the memory reference contains a symbolic address. Constraint letter `Q' - is defined as representing a memory address that does *not* contain a - symbolic address. An alternative is specified with a `Q' constraint on the - input and `r' on the output. The next alternative specifies `m' on the - input and a register class that does not include r0 on the output. */ -#define EXTRA_CONSTRAINT(VALUE, C) \ - ((C) == 'Q' ? (GET_CODE (VALUE) == MEM && GET_CODE (XEXP (VALUE, 0)) == SYMBOL_REF) : 0) - -/*}}}*/ -/*{{{ Basic Stack Layout */ - -/* Define this macro if pushing a word onto the stack moves the stack pointer - 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 1 - -/* Define this macro if successive arguments to a function occupy decreasing - addresses on the stack. */ -/* #define ARGS_GROW_DOWNWARD */ - -/* Offset from the frame pointer to the first local variable slot to be - allocated. - - If `FRAME_GROWS_DOWNWARD', find the next slot's offset by subtracting the - first slot's length from `STARTING_FRAME_OFFSET'. Otherwise, it is found by - adding the length of the first slot to the value `STARTING_FRAME_OFFSET'. */ -/* #define STARTING_FRAME_OFFSET -4 */ -#define STARTING_FRAME_OFFSET 0 - -/* Offset from the stack pointer register to the first location at which - outgoing arguments are placed. If not specified, the default value of zero - is used. This is the proper value for most machines. - - If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first - location at which outgoing arguments are placed. */ -#define STACK_POINTER_OFFSET 0 - -/* Offset from the argument pointer register to the first argument's address. - On some machines it may depend on the data type of the function. - - If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first - argument's address. */ -#define FIRST_PARM_OFFSET(FUNDECL) 0 - -/* Offset from the stack pointer register to an item dynamically allocated on - the stack, e.g., by `alloca'. - - The default value for this macro is `STACK_POINTER_OFFSET' plus the length - of the outgoing arguments. The default is correct for most machines. See - `function.c' for details. */ -/* #define STACK_DYNAMIC_OFFSET(FUNDECL) */ - -/* A C expression whose value is RTL representing the address in a stack frame - where the pointer to the caller's frame is stored. Assume that FRAMEADDR is - an RTL expression for the address of the stack frame itself. - - If you don't define this macro, the default is to return the value of - FRAMEADDR--that is, the stack frame address is also the address of the stack - word that points to the previous frame. */ -/* #define DYNAMIC_CHAIN_ADDRESS(FRAMEADDR) */ - -/* A C expression whose value is RTL representing the value of the return - address for the frame COUNT steps up from the current frame, after the - prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame - pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is - defined. - - The value of the expression must always be the correct address when COUNT is - zero, but may be `NULL_RTX' if there is not way to determine the return - address of other frames. */ -/* #define RETURN_ADDR_RTX(COUNT, FRAMEADDR) */ - -/* Define this if the return address of a particular stack frame is - accessed from the frame pointer of the previous stack frame. */ -/* #define RETURN_ADDR_IN_PREVIOUS_FRAME */ - -/* A C expression whose value is RTL representing the location of the incoming - return address at the beginning of any function, before the prologue. This - RTL is either a `REG', indicating that the return value is saved in `REG', - or a `MEM' representing a location in the stack. - - You only need to define this macro if you want to support call frame - debugging information like that provided by DWARF 2. */ -#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (SImode, RETURN_POINTER_REGNUM) - -/* A C expression whose value is an integer giving the offset, in bytes, from - the value of the stack pointer register to the top of the stack frame at the - beginning of any function, before the prologue. The top of the frame is - defined to be the value of the stack pointer in the previous frame, just - before the call instruction. - - You only need to define this macro if you want to support call frame - debugging information like that provided by DWARF 2. */ -/* #define INCOMING_FRAME_SP_OFFSET */ - -/*}}}*/ -/*{{{ Register That Address the Stack Frame. */ - -/* On some machines the offset between the frame pointer and starting offset of - the automatic variables is not known until after register allocation has - been done (for example, because the saved registers are between these two - locations). On those machines, define `FRAME_POINTER_REGNUM' the number of - a special, fixed register to be used internally until the offset is known, - and define `HARD_FRAME_POINTER_REGNUM' to be actual the hard register number - used for the frame pointer. - - You should define this macro only in the very rare circumstances when it is - not possible to calculate the offset between the frame pointer and the - automatic variables until after register allocation has been completed. - When this macro is defined, you must also indicate in your definition of - `ELIMINABLE_REGS' how to eliminate `FRAME_POINTER_REGNUM' into either - `HARD_FRAME_POINTER_REGNUM' or `STACK_POINTER_REGNUM'. - - Do not define this macro if it would be the same as `FRAME_POINTER_REGNUM'. */ -/* #define HARD_FRAME_POINTER_REGNUM */ - -/* The register number of the arg pointer register, which is used to access the - function's argument list. On some machines, this is the same as the frame - pointer register. On some machines, the hardware determines which register - this is. On other machines, you can choose any register you wish for this - purpose. If this is not the same register as the frame pointer register, - then you must mark it as a fixed register according to `FIXED_REGISTERS', or - arrange to be able to eliminate it. */ -#define ARG_POINTER_REGNUM 20 - -/* The register number of the return address pointer register, which is used to - access the current function's return address from the stack. On some - machines, the return address is not at a fixed offset from the frame pointer - or stack pointer or argument pointer. This register can be defined to point - to the return address on the stack, and then be converted by - `ELIMINABLE_REGS' into either the frame pointer or stack pointer. - - Do not define this macro unless there is no other way to get the return - address from the stack. */ -/* #define RETURN_ADDRESS_POINTER_REGNUM */ - -/* If the static chain is passed in memory, these macros provide rtx giving - `mem' expressions that denote where they are stored. `STATIC_CHAIN' and - `STATIC_CHAIN_INCOMING' give the locations as seen by the calling and called - functions, respectively. Often the former will be at an offset from the - stack pointer and the latter at an offset from the frame pointer. - - The variables `stack_pointer_rtx', `frame_pointer_rtx', and - `arg_pointer_rtx' will have been initialized prior to the use of these - macros and should be used to refer to those items. - - If the static chain is passed in a register, the two previous - macros should be defined instead. */ -/* #define STATIC_CHAIN */ -/* #define STATIC_CHAIN_INCOMING */ - -/*}}}*/ -/*{{{ Eliminating the Frame Pointer and the Arg Pointer */ - -/* A C expression which is nonzero if a function must have and use a frame - pointer. This expression is evaluated in the reload pass. If its value is - nonzero the function will have a frame pointer. - - The expression can in principle examine the current function and decide - according to the facts, but on most machines the constant 0 or the constant - 1 suffices. Use 0 when the machine allows code to be generated with no - frame pointer, and doing so saves some time or space. Use 1 when there is - no possible advantage to avoiding a frame pointer. - - In certain cases, the compiler does not know how to produce valid code - without a frame pointer. The compiler recognizes those cases and - automatically gives the function a frame pointer regardless of what - `FRAME_POINTER_REQUIRED' says. You don't need to worry about them. - - In a function that does not require a frame pointer, the frame pointer - register can be allocated for ordinary usage, unless you mark it as a fixed - register. See `FIXED_REGISTERS' for more information. */ -/* #define FRAME_POINTER_REQUIRED 0 */ -#define FRAME_POINTER_REQUIRED \ - (flag_omit_frame_pointer == 0 || current_function_pretend_args_size > 0) - -/* A C statement to store in the variable DEPTH_VAR the difference between the - frame pointer and the stack pointer values immediately after the function - prologue. The value would be computed from information such as the result - of `get_frame_size ()' and the tables of registers `regs_ever_live' and - `call_used_regs'. - - If `ELIMINABLE_REGS' is defined, this macro will be not be used and need not - be defined. Otherwise, it must be defined even if `FRAME_POINTER_REQUIRED' - is defined to always be true; in that case, you may set DEPTH-VAR to - anything. */ -/* #define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR) */ - -/* If defined, this macro specifies a table of register pairs used to eliminate - unneeded registers that point into the stack frame. If it is not defined, - the only elimination attempted by the compiler is to replace references to - the frame pointer with references to the stack pointer. - - The definition of this macro is a list of structure initializations, each of - which specifies an original and replacement register. - - On some machines, the position of the argument pointer is not known until - the compilation is completed. In such a case, a separate hard register must - be used for the argument pointer. This register can be eliminated by - replacing it with either the frame pointer or the argument pointer, - depending on whether or not the frame pointer has been eliminated. - - In this case, you might specify: - #define ELIMINABLE_REGS \ - {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} - - Note that the elimination of the argument pointer with the stack pointer is - specified first since that is the preferred elimination. */ - -#define ELIMINABLE_REGS \ -{ \ - {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \ -} - -/* A C expression that returns non-zero if the compiler is allowed to try to - replace register number FROM with register number TO. This macro - need only be defined if `ELIMINABLE_REGS' is defined, and will usually be - the constant 1, since most of the cases preventing register elimination are - things that the compiler already knows about. */ - -#define CAN_ELIMINATE(FROM, TO) \ - ((TO) == FRAME_POINTER_REGNUM || ! frame_pointer_needed) - -/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the - initial difference between the specified pair of registers. This macro must - be defined if `ELIMINABLE_REGS' is defined. */ -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ - (OFFSET) = fr30_compute_frame_size (FROM, TO) - -/* Define this macro if the `longjmp' function restores registers from the - stack frames, rather than from those saved specifically by `setjmp'. - Certain quantities must not be kept in registers across a call to `setjmp' - on such machines. */ -/* #define LONGJMP_RESTORE_FROM_STACK */ - -/*}}}*/ -/*{{{ 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. */ -#define PROMOTE_PROTOTYPES - -/* A C expression that is the number of bytes actually pushed onto the stack - when an instruction attempts to push NPUSHED bytes. - - If the target machine does not have a push instruction, do not define this - macro. That directs GNU CC to use an alternate strategy: to allocate the - entire argument block and then store the arguments into it. - - On some machines, the definition - - #define PUSH_ROUNDING(BYTES) (BYTES) - - will suffice. But on other machines, instructions that appear to push one - byte actually push two bytes in an attempt to maintain alignment. Then the - definition should be - - #define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1) */ -/* #define PUSH_ROUNDING(NPUSHED) */ - -/* If defined, the maximum amount of space required for outgoing arguments will - be computed and placed into the variable - `current_function_outgoing_args_size'. No space will be pushed onto the - stack for each call; instead, the function prologue should increase the - stack frame size by this amount. - - Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not - proper. */ -#define ACCUMULATE_OUTGOING_ARGS - -/* Define this macro if functions should assume that stack space has been - allocated for arguments even when their values are passed in registers. - - The value of this macro is the size, in bytes, of the area reserved for - arguments passed in registers for the function represented by FNDECL. - - This space can be allocated by the caller, or be a part of the - machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says - which. */ -/* #define REG_PARM_STACK_SPACE(FNDECL) */ - -/* Define these macros in addition to the one above if functions might allocate - stack space for arguments even when their values are passed in registers. - These should be used when the stack space allocated for arguments in - registers is not a simple constant independent of the function declaration. - - The value of the first macro is the size, in bytes, of the area that we - should initially assume would be reserved for arguments passed in registers. - - The value of the second macro is the actual size, in bytes, of the area that - will be reserved for arguments passed in registers. This takes two - arguments: an integer representing the number of bytes of fixed sized - arguments on the stack, and a tree representing the number of bytes of - variable sized arguments on the stack. - - When these macros are defined, `REG_PARM_STACK_SPACE' will only be called - for libcall functions, the current function, or for a function being called - when it is known that such stack space must be allocated. In each case this - value can be easily computed. - - When deciding whether a called function needs such stack space, and how much - space to reserve, GNU CC uses these two macros instead of - `REG_PARM_STACK_SPACE'. */ -/* #define MAYBE_REG_PARM_STACK_SPACE */ -/* #define FINAL_REG_PARM_STACK_SPACE(CONST_SIZE, VAR_SIZE) */ - -/* 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 defined, this macro controls whether the - space for these arguments counts in the value of - `current_function_outgoing_args_size'. */ -/* #define OUTGOING_REG_PARM_STACK_SPACE */ - -/* Define this macro if `REG_PARM_STACK_SPACE' is defined, but the stack - parameters don't skip the area specified by it. - - Normally, when a parameter is not passed in registers, it is placed on the - stack beyond the `REG_PARM_STACK_SPACE' area. Defining this macro - suppresses this behavior and causes the parameter to be passed on the stack - in its natural location. */ -/* #define STACK_PARMS_IN_REG_PARM_AREA */ - -/* A C expression that should indicate the number of bytes of its own arguments - that a function pops on returning, or 0 if the function pops no arguments - and the caller must therefore pop them all after the function returns. - - FUNDECL is a C variable whose value is a tree node that describes the - function in question. Normally it is a node of type `FUNCTION_DECL' that - describes the declaration of the function. From this it is possible to - obtain the DECL_MACHINE_ATTRIBUTES of the function. - - FUNTYPE is a C variable whose value is a tree node that describes the - function in question. Normally it is a node of type `FUNCTION_TYPE' that - describes the data type of the function. From this it is possible to obtain - the data types of the value and arguments (if known). - - When a call to a library function is being considered, FUNTYPE will contain - an identifier node for the library function. Thus, if you need to - distinguish among various library functions, you can do so by their names. - Note that "library function" in this context means a function used to - perform arithmetic, whose name is known specially in the compiler and was - not mentioned in the C code being compiled. - - STACK-SIZE is the number of bytes of arguments passed on the stack. If a - variable number of bytes is passed, it is zero, and argument popping will - always be the responsibility of the calling function. - - On the Vax, all functions always pop their arguments, so the definition of - this macro is STACK-SIZE. On the 68000, using the standard calling - convention, no functions pop their arguments, so the value of the macro is - always 0 in this case. But an alternative calling convention is available - in which functions that take a fixed number of arguments pop them but other - functions (such as `printf') pop nothing (the caller pops all). When this - convention is in use, FUNTYPE is examined to determine whether a function - takes a fixed number of arguments. */ -#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 - -/*}}}*/ -/*{{{ Function Arguments in Registers */ - -/* Nonzero if we do not know how to pass TYPE solely in registers. - We cannot do so in the following cases: - - - if the type has variable size - - if the type is marked as addressable (it is required to be constructed - into the stack) - - if the type is a structure or union. */ - -#define MUST_PASS_IN_STACK(MODE,TYPE) \ - (((MODE) == BLKmode) \ - || ((TYPE) != 0 \ - && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \ - || TREE_CODE (TYPE) == RECORD_TYPE \ - || TREE_CODE (TYPE) == UNION_TYPE \ - || TREE_CODE (TYPE) == QUAL_UNION_TYPE \ - || TREE_ADDRESSABLE (TYPE)))) - -/* The number of register assigned to holding function arguments. */ - -#define FR30_NUM_ARG_REGS 4 - -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The usual way to make the ANSI library `stdarg.h' work on a machine where - some arguments are usually passed in registers, is to cause nameless - arguments to be passed on the stack instead. This is done by making - `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of - this macro to determine if this argument is of a type that must be passed in - the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' - returns non-zero for such an argument, the compiler will abort. If - `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the - stack and then loaded into a register. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - ( (NAMED) == 0 ? NULL_RTX \ - : MUST_PASS_IN_STACK (MODE, TYPE) ? NULL_RTX \ - : (CUM) >= FR30_NUM_ARG_REGS ? NULL_RTX \ - : gen_rtx (REG, MODE, CUM + FIRST_ARG_REGNUM)) - -/* A C type for declaring a variable that is used as the first argument of - `FUNCTION_ARG' and other related values. For some target machines, the type - `int' suffices and can hold the number of bytes of argument so far. - - There is no need to record in `CUMULATIVE_ARGS' anything about the arguments - that have been passed on the stack. The compiler has other variables to - keep track of that. For target machines on which all arguments are passed - on the stack, there is no need to store anything in `CUMULATIVE_ARGS'; - however, the data structure must exist and should not be empty, so use - `int'. */ -/* On the FR30 this value is an accumulating count of the number of argument - registers that have been filled with argument values, as opposed to say, - the number of bytes of argument accumulated so far. */ -typedef int CUMULATIVE_ARGS; - -/* A C expression for the number of words, at the beginning of an argument, - must be put in registers. The value must be zero for arguments that are - passed entirely in registers or that are entirely pushed on the stack. - - On some machines, certain arguments must be passed partially in registers - and partially in memory. On these machines, typically the first N words of - arguments are passed in registers, and the rest on the stack. If a - multi-word argument (a `double' or a structure) crosses that boundary, its - first few words must be passed in registers and the rest must be pushed. - This macro tells the compiler when this occurs, and how many of the words - should go in registers. - - `FUNCTION_ARG' for these arguments should return the first register to be - used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for - the called function. */ -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ - fr30_function_arg_partial_nregs (CUM, MODE, TYPE, NAMED) - -extern int fr30_function_arg_partial_nregs PROTO ((CUMULATIVE_ARGS, int, Tree, int)); - -/* A C expression that indicates when an argument must be passed by reference. - If nonzero for an argument, a copy of that argument is made in memory and a - pointer to the argument is passed instead of the argument itself. The - pointer is passed in whatever way is appropriate for passing a pointer to - that type. - - On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable - definition of this macro might be: - #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) */ -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) - -/* If defined, a C expression that indicates when it is more - desirable to keep an argument passed by invisible reference as a - reference, rather than copying it to a pseudo register. */ -/* #define FUNCTION_ARG_KEEP_AS_REFERENCE(CUM, MODE, TYPE, NAMED) */ - -/* If defined, a C expression that indicates when it is the called function's - responsibility to make a copy of arguments passed by invisible reference. - Normally, the caller makes a copy and passes the address of the copy to the - routine being called. When FUNCTION_ARG_CALLEE_COPIES is defined and is - nonzero, the caller does not make a copy. Instead, it passes a pointer to - the "live" value. The called function must not modify this value. If it - can be determined that the value won't be modified, it need not make a copy; - otherwise a copy must be made. */ -/* #define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) */ - -/* If defined, a C expression that indicates when it is more desirable to keep - an argument passed by invisible reference as a reference, rather than - copying it to a pseudo register. */ -/* #define FUNCTION_ARG_KEEP_AS_REFERENCE(CUM, MODE, TYPE, NAMED) */ - -/* A C statement (sans semicolon) for initializing the variable CUM for the - state at the beginning of the argument list. The variable has type - `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node for the data type - of the function which will receive the args, or 0 if the args are to a - compiler support library function. The value of INDIRECT is nonzero when - processing an indirect call, for example a call through a function pointer. - The value of INDIRECT is zero for a call to an explicitly named function, a - library function call, or when `INIT_CUMULATIVE_ARGS' is used to find - arguments for the function being compiled. - - When processing a call to a compiler support library function, LIBNAME - identifies which one. It is a `symbol_ref' rtx which contains the name of - the function, as a string. LIBNAME is 0 when an ordinary C function call is - being processed. Thus, each time this macro is called, either LIBNAME or - FNTYPE is nonzero, but never both of them at once. */ -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) (CUM) = 0 - -/* Like `INIT_CUMULATIVE_ARGS' but overrides it for the purposes of finding the - arguments for the function being compiled. If this macro is undefined, - `INIT_CUMULATIVE_ARGS' is used instead. - - The value passed for LIBNAME is always 0, since library routines with - special calling conventions are never compiled with GNU CC. The argument - LIBNAME exists for symmetry with `INIT_CUMULATIVE_ARGS'. */ -/* #define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) */ - -/* A C statement (sans semicolon) to update the summarizer variable CUM to - advance past an argument in the argument list. The values MODE, TYPE and - NAMED describe that argument. Once this is done, the variable CUM is - suitable for analyzing the *following* argument with `FUNCTION_ARG', etc. - - This macro need not do anything if the argument in question was passed on - the stack. The compiler knows how to track the amount of stack space used - for arguments without any special help. */ -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - (CUM) += (NAMED) * fr30_num_arg_regs (MODE, TYPE) - -extern int fr30_num_arg_regs PROTO ((int, Tree)); - -/* If defined, a C expression which determines whether, and in which direction, - to pad out an argument with extra space. The value should be of type `enum - direction': either `upward' to pad above the argument, `downward' to pad - below, or `none' to inhibit padding. - - The *amount* of padding is always just enough to reach the next multiple of - `FUNCTION_ARG_BOUNDARY'; this macro does not control it. - - This macro has a default definition which is right for most systems. For - little-endian machines, the default is to pad upward. For big-endian - machines, the default is to pad downward for an argument of constant size - shorter than an `int', and upward otherwise. */ -/* #define FUNCTION_ARG_PADDING(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) */ - -/* A C expression that is nonzero if REGNO is the number of a hard register in - which function arguments are sometimes passed. This does *not* include - implicit arguments such as the static chain and the structure-value address. - On many machines, no registers can be used for this purpose since all - function arguments are pushed on the stack. */ -#define FUNCTION_ARG_REGNO_P(REGNO) \ - ((REGNO) >= FIRST_ARG_REGNUM && ((REGNO) < FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS)) - -/*}}}*/ -/*{{{ How Scalar Function Values are Returned */ - -/* Define this macro if `-traditional' should not cause functions declared to - return `float' to convert the value to `double'. */ -/* #define TRADITIONAL_RETURN_FLOAT */ - -/* A C expression to create an RTX representing the place where a function - returns a value of data type VALTYPE. VALTYPE is a tree node representing a - data type. Write `TYPE_MODE (VALTYPE)' to get the machine mode used to - represent that type. On many machines, only the mode is relevant. - (Actually, on most machines, scalar values are returned in the same place - regardless of mode). - - If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion - rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type. - - If the precise function being called is known, FUNC is a tree node - (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This makes it - possible to use a different value-returning convention for specific - functions when all their calls are known. - - `FUNCTION_VALUE' is not used for return vales with aggregate data types, - because these are returned in another way. See `STRUCT_VALUE_REGNUM' and - related macros, below. */ -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx_REG (TYPE_MODE (VALTYPE), RETURN_VALUE_REGNUM) - -/* A C expression to create an RTX representing the place where a library - function returns a value of mode MODE. If the precise function being called - is known, FUNC is a tree node (`FUNCTION_DECL') for it; otherwise, FUNC is a - null pointer. This makes it possible to use a different value-returning - convention for specific functions when all their calls are known. - - Note that "library function" in this context means a compiler support - routine, used to perform arithmetic, whose name is known specially by the - compiler and was not mentioned in the C code being compiled. - - The definition of `LIBRARY_VALUE' need not be concerned aggregate data - types, because none of the library functions returns such types. */ -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, RETURN_VALUE_REGNUM) - -/* A C expression that is nonzero if REGNO is the number of a hard register in - which the values of called function may come back. */ - -#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == RETURN_VALUE_REGNUM) - -/* Define this macro if `untyped_call' and `untyped_return' need more space - than is implied by `FUNCTION_VALUE_REGNO_P' for saving and restoring an - arbitrary return value. */ -/* #define APPLY_RESULT_SIZE */ - -/*}}}*/ -/*{{{ How Large Values are Returned */ - -/* A C expression which can inhibit the returning of certain function values in - registers, based on the type of value. A nonzero value says to return the - function value in memory, just as large structures are always returned. - Here TYPE will be a C expression of type `tree', representing the data type - of the value. - - Note that values of mode `BLKmode' must be explicitly handled by this macro. - Also, the option `-fpcc-struct-return' takes effect regardless of this - macro. On most systems, it is possible to leave the macro undefined; this - causes a default definition to be used, whose value is the constant 1 for - `BLKmode' values, and 0 otherwise. - - Do not use this macro to indicate that structures and unions should always - be returned in memory. You should instead use `DEFAULT_PCC_STRUCT_RETURN' - to indicate this. */ -/* #define RETURN_IN_MEMORY(TYPE) */ - -/* Define this macro to be 1 if all structure and union return values must be - in memory. Since this results in slower code, this should be defined only - if needed for compatibility with other compilers or with an ABI. 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. - - If not defined, this defaults to the value 1. */ -#define DEFAULT_PCC_STRUCT_RETURN 1 - -/* If the structure value address is passed in a register, then - `STRUCT_VALUE_REGNUM' should be the number of that register. */ -/* #define STRUCT_VALUE_REGNUM */ - -/* If the structure value address is not passed in a register, define - `STRUCT_VALUE' as an expression returning an RTX for the place where the - address is passed. If it returns 0, the address is passed as an "invisible" - first argument. */ -#define STRUCT_VALUE 0 - -/* On some architectures the place where the structure value address is found - by the called function is not the same place that the caller put it. This - can be due to register windows, or it could be because the function prologue - moves it to a different place. - - If the incoming location of the structure value address is in a register, - define this macro as the register number. */ -/* #define STRUCT_VALUE_INCOMING_REGNUM */ - -/* If the incoming location is not a register, then you should define - `STRUCT_VALUE_INCOMING' as an expression for an RTX for where the called - function should find the value. If it should find the value on the stack, - define this to create a `mem' which refers to the frame pointer. A - definition of 0 means that the address is passed as an "invisible" first - argument. */ -/* #define STRUCT_VALUE_INCOMING */ - -/* Define this macro if the usual system convention on the target machine for - returning structures and unions is for the called function to return the - address of a static variable containing the value. - - Do not define this if the usual system convention is for the caller to pass - an address to the subroutine. - - This macro has effect in `-fpcc-struct-return' mode, but it does nothing - when you use `-freg-struct-return' mode. */ -/* #define PCC_STATIC_STRUCT_RETURN */ - -/*}}}*/ -/*{{{ Caller-Saves Register Allocation */ - -/* Define this macro if function calls on the target machine do not preserve - any registers; in other words, if `CALL_USED_REGISTERS' has 1 for all - registers. This macro enables `-fcaller-saves' by default. Eventually that - option will be enabled by default on all machines and both the option and - this macro will be eliminated. */ -/* #define DEFAULT_CALLER_SAVES */ - -/* A C expression to determine whether it is worthwhile to consider placing a - pseudo-register in a call-clobbered hard register and saving and restoring - it around each function call. The expression should be 1 when this is worth - doing, and 0 otherwise. - - If you don't define this macro, a default is used which is good on most - machines: `4 * CALLS < REFS'. */ -/* #define CALLER_SAVE_PROFITABLE(REFS, CALLS) */ - -/*}}}*/ -/*{{{ Function Entry and Exit */ - -/* A C compound statement that outputs the assembler code for entry to a - function. The prologue is responsible for setting up the stack frame, - initializing the frame pointer register, saving registers that must be - saved, and allocating SIZE additional bytes of storage for the local - variables. SIZE is an integer. FILE is a stdio stream to which the - assembler code should be output. - - The label for the beginning of the function need not be output by this - macro. That has already been done when the macro is run. - - To determine which registers to save, the macro can refer to the array - `regs_ever_live': element R is nonzero if hard register R is used anywhere - within the function. This implies the function prologue should save - register R, provided it is not one of the call-used registers. - (`FUNCTION_EPILOGUE' must likewise use `regs_ever_live'.) - - On machines that have "register windows", the function entry code does not - save on the stack the registers that are in the windows, even if they are - supposed to be preserved by function calls; instead it takes appropriate - steps to "push" the register stack, if any non-call-used registers are used - in the function. - - On machines where functions may or may not have frame-pointers, the function - entry code must vary accordingly; it must set up the frame pointer if one is - wanted, and not otherwise. To determine whether a frame pointer is in - wanted, the macro can refer to the variable `frame_pointer_needed'. The - variable's value will be 1 at run time in a function that needs a frame - pointer. *Note Elimination::. - - The function entry code is responsible for allocating any stack space - required for the function. This stack space consists of the regions listed - below. In most cases, these regions are allocated in the order listed, with - the last listed region closest to the top of the stack (the lowest address - if `STACK_GROWS_DOWNWARD' is defined, and the highest address if it is not - defined). You can use a different order for a machine if doing so is more - convenient or required for compatibility reasons. Except in cases where - required by standard or by a debugger, there is no reason why the stack - layout used by GCC need agree with that used by other compilers for a - machine. - - * A region of `current_function_pretend_args_size' bytes of - uninitialized space just underneath the first argument - arriving on the stack. (This may not be at the very start of - the allocated stack region if the calling sequence has pushed - anything else since pushing the stack arguments. But - usually, on such machines, nothing else has been pushed yet, - because the function prologue itself does all the pushing.) - This region is used on machines where an argument may be - passed partly in registers and partly in memory, and, in some - cases to support the features in `varargs.h' and `stdargs.h'. - - * An area of memory used to save certain registers used by the - function. The size of this area, which may also include - space for such things as the return address and pointers to - previous stack frames, is machine-specific and usually - depends on which registers have been used in the function. - Machines with register windows often do not require a save - area. - - * A region of at least SIZE bytes, possibly rounded up to an - allocation boundary, to contain the local variables of the - function. On some machines, this region and the save area - may occur in the opposite order, with the save area closer to - the top of the stack. - - * Optionally, when `ACCUMULATE_OUTGOING_ARGS' is defined, a - region of `current_function_outgoing_args_size' bytes to be - used for outgoing argument lists of the function. - - Normally, it is necessary for the macros `FUNCTION_PROLOGUE' and - `FUNCTION_EPILOGUE' to treat leaf functions specially. The C variable - `leaf_function' is nonzero for such a function. */ -/* #define FUNCTION_PROLOGUE(FILE, SIZE) */ - -/* Define this macro as a C expression that is nonzero if the return - instruction or the function epilogue ignores the value of the stack pointer; - in other words, if it is safe to delete an instruction to adjust the stack - pointer before a return from the function. - - Note that this macro's value is relevant only for functions for which frame - pointers are maintained. It is never safe to delete a final stack - adjustment in a function that has no frame pointer, and the compiler knows - this regardless of `EXIT_IGNORE_STACK'. */ -/* #define EXIT_IGNORE_STACK */ - -/* Define this macro as a C expression that is nonzero for registers - are used by the epilogue or the `return' pattern. The stack and - frame pointer registers are already be assumed to be used as - needed. */ -/* #define EPILOGUE_USES(REGNO) */ - -/* A C compound statement that outputs the assembler code for exit from a - function. The epilogue is responsible for restoring the saved registers and - stack pointer to their values when the function was called, and returning - control to the caller. This macro takes the same arguments as the macro - `FUNCTION_PROLOGUE', and the registers to restore are determined from - `regs_ever_live' and `CALL_USED_REGISTERS' in the same way. - - On some machines, there is a single instruction that does all the work of - returning from the function. On these machines, give that instruction the - name `return' and do not define the macro `FUNCTION_EPILOGUE' at all. - - Do not define a pattern named `return' if you want the `FUNCTION_EPILOGUE' - to be used. If you want the target switches to control whether return - instructions or epilogues are used, define a `return' pattern with a - validity condition that tests the target switches appropriately. If the - `return' pattern's validity condition is false, epilogues will be used. - - On machines where functions may or may not have frame-pointers, the function - exit code must vary accordingly. Sometimes the code for these two cases is - completely different. To determine whether a frame pointer is wanted, the - macro can refer to the variable `frame_pointer_needed'. The variable's - value will be 1 when compiling a function that needs a frame pointer. - - Normally, `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' must treat leaf - functions specially. The C variable `leaf_function' is nonzero for such a - function. - - On some machines, some functions pop their arguments on exit while others - leave that for the caller to do. For example, the 68020 when given `-mrtd' - pops arguments in functions that take a fixed number of arguments. - - Your definition of the macro `RETURN_POPS_ARGS' decides which functions pop - their own arguments. `FUNCTION_EPILOGUE' needs to know what was decided. - The variable that is called `current_function_pops_args' is the number of - bytes of its arguments that a function should pop. *Note Scalar Return::. */ -/* #define FUNCTION_EPILOGUE(FILE, SIZE) */ - -/* Define this macro if the function epilogue contains delay slots to which - instructions from the rest of the function can be "moved". The definition - should be a C expression whose value is an integer representing the number - of delay slots there. */ -/* #define DELAY_SLOTS_FOR_EPILOGUE */ - -/* A C expression that returns 1 if INSN can be placed in delay slot number N - of the epilogue. - - The argument N is an integer which identifies the delay slot now being - considered (since different slots may have different rules of eligibility). - It is never negative and is always less than the number of epilogue delay - slots (what `DELAY_SLOTS_FOR_EPILOGUE' returns). If you reject a particular - insn for a given delay slot, in principle, it may be reconsidered for a - subsequent delay slot. Also, other insns may (at least in principle) be - considered for the so far unfilled delay slot. - - The insns accepted to fill the epilogue delay slots are put in an - RTL list made with `insn_list' objects, stored in the variable - `current_function_epilogue_delay_list'. The insn for the first - delay slot comes first in the list. Your definition of the macro - `FUNCTION_EPILOGUE' should fill the delay slots by outputting the - insns in this list, usually by calling `final_scan_insn'. - - You need not define this macro if you did not define - `DELAY_SLOTS_FOR_EPILOGUE'. */ -/* #define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN, N) */ - -/* A C compound statement that outputs the assembler code for a thunk function, - used to implement C++ virtual function calls with multiple inheritance. The - thunk acts as a wrapper around a virtual function, adjusting the implicit - object parameter before handing control off to the real function. - - First, emit code to add the integer DELTA to the location that contains the - incoming first argument. Assume that this argument contains a pointer, and - is the one used to pass the `this' pointer in C++. This is the incoming - argument *before* the function prologue, e.g. `%o0' on a sparc. The - addition must preserve the values of all other incoming arguments. - - After the addition, emit code to jump to FUNCTION, which is a - `FUNCTION_DECL'. This is a direct pure jump, not a call, and does not touch - the return address. Hence returning from FUNCTION will return to whoever - called the current `thunk'. - - The effect must be as if FUNCTION had been called directly with the adjusted - first argument. This macro is responsible for emitting all of the code for - a thunk function; `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' are not - invoked. - - The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already been - extracted from it.) It might possibly be useful on some targets, but - probably not. - - If you do not define this macro, the target-independent code in the C++ - frontend will generate a less efficient heavyweight thunk that calls - FUNCTION instead of jumping to it. The generic approach does not support - varargs. */ -/* #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) */ - -/*}}}*/ -/*{{{ Generating Code for Profiling. */ - -/* A C statement or compound statement to output to FILE some assembler code to - call the profiling subroutine `mcount'. Before calling, the assembler code - must load the address of a counter variable into a register where `mcount' - expects to find the address. The name of this variable is `LP' followed by - the number LABELNO, so you would generate the name using `LP%d' in a - `fprintf'. - - The details of how the address should be passed to `mcount' are determined - by your operating system environment, not by GNU CC. To figure them out, - compile a small program for profiling using the system's installed C - compiler and look at the assembler code that results. */ -#define FUNCTION_PROFILER(FILE, LABELNO) \ -{ \ - fprintf (FILE, "\t mov rp, r1\n" ); \ - fprintf (FILE, "\t ldi:32 mcount, r0\n" ); \ - fprintf (FILE, "\t call @r0\n" ); \ - fprintf (FILE, ".word\tLP%d\n", LABELNO); \ -} - -/* 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 */ - -/* A C statement or compound statement to output to FILE some assembler code to - initialize basic-block profiling for the current object module. The global - compile flag `profile_block_flag' distingishes two profile modes. - - profile_block_flag != 2' - Output code to call the subroutine `__bb_init_func' once per - object module, passing it as its sole argument the address of - a block allocated in the object module. - - The name of the block is a local symbol made with this - statement: - - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); - - Of course, since you are writing the definition of - `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, - you can take a short cut in the definition of this macro and - use the name that you know will result. - - The first word of this block is a flag which will be nonzero - if the object module has already been initialized. So test - this word first, and do not call `__bb_init_func' if the flag - is nonzero. BLOCK_OR_LABEL contains a unique number which - may be used to generate a label as a branch destination when - `__bb_init_func' will not be called. - - Described in assembler language, the code to be output looks - like: - - cmp (LPBX0),0 - bne local_label - parameter1 <- LPBX0 - call __bb_init_func - local_label: - - profile_block_flag == 2' - Output code to call the subroutine `__bb_init_trace_func' and - pass two parameters to it. The first parameter is the same as - for `__bb_init_func'. The second parameter is the number of - the first basic block of the function as given by - BLOCK_OR_LABEL. Note that `__bb_init_trace_func' has to be - called, even if the object module has been initialized - already. - - Described in assembler language, the code to be output looks - like: - parameter1 <- LPBX0 - parameter2 <- BLOCK_OR_LABEL - call __bb_init_trace_func */ -/* #define FUNCTION_BLOCK_PROFILER (FILE, LABELNO) */ - -/* A C statement or compound statement to output to FILE some assembler code to - increment the count associated with the basic block number BLOCKNO. The - global compile flag `profile_block_flag' distingishes two profile modes. - - profile_block_flag != 2' - Output code to increment the counter directly. Basic blocks - are numbered separately from zero within each compilation. - The count associated with block number BLOCKNO is at index - BLOCKNO in a vector of words; the name of this array is a - local symbol made with this statement: - - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2); - - Of course, since you are writing the definition of - `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, - you can take a short cut in the definition of this macro and - use the name that you know will result. - - Described in assembler language, the code to be output looks - like: - - inc (LPBX2+4*BLOCKNO) - - profile_block_flag == 2' - Output code to initialize the global structure `__bb' and - call the function `__bb_trace_func', which will increment the - counter. - - `__bb' consists of two words. In the first word, the current - basic block number, as given by BLOCKNO, has to be stored. In - the second word, the address of a block allocated in the - object module has to be stored. The address is given by the - label created with this statement: - - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); - - Described in assembler language, the code to be output looks - like: - move BLOCKNO -> (__bb) - move LPBX0 -> (__bb+4) - call __bb_trace_func */ -/* #define BLOCK_PROFILER(FILE, BLOCKNO) */ - -/* A C statement or compound statement to output to FILE assembler - code to call function `__bb_trace_ret'. The assembler code should - only be output if the global compile flag `profile_block_flag' == - 2. This macro has to be used at every place where code for - returning from a function is generated (e.g. `FUNCTION_EPILOGUE'). - Although you have to write the definition of `FUNCTION_EPILOGUE' - as well, you have to define this macro to tell the compiler, that - the proper call to `__bb_trace_ret' is produced. */ -/* #define FUNCTION_BLOCK_PROFILER_EXIT(FILE) */ - -/* A C statement or compound statement to save all registers, which may be - clobbered by a function call, including condition codes. The `asm' - statement will be mostly likely needed to handle this task. Local labels in - the assembler code can be concatenated with the string ID, to obtain a - unique lable name. - - Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or - `FUNCTION_EPILOGUE' must be saved in the macros `FUNCTION_BLOCK_PROFILER', - `FUNCTION_BLOCK_PROFILER_EXIT' and `BLOCK_PROFILER' prior calling - `__bb_init_trace_func', `__bb_trace_ret' and `__bb_trace_func' respectively. */ -/* #define MACHINE_STATE_SAVE(ID) */ - -/* A C statement or compound statement to restore all registers, including - condition codes, saved by `MACHINE_STATE_SAVE'. - - Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or - `FUNCTION_EPILOGUE' must be restored in the macros - `FUNCTION_BLOCK_PROFILER', `FUNCTION_BLOCK_PROFILER_EXIT' and - `BLOCK_PROFILER' after calling `__bb_init_trace_func', `__bb_trace_ret' and - `__bb_trace_func' respectively. */ -/* #define MACHINE_STATE_RESTORE(ID) */ - -/* A C function or functions which are needed in the library to support block - profiling. */ -/* #define BLOCK_PROFILER_CODE */ - -/*}}}*/ -/*{{{ Implementing the VARARGS Macros. */ - -/* If defined, is a C expression that produces the machine-specific code for a - call to `__builtin_saveregs'. This code will be moved to the very beginning - of the function, before any parameter access are made. The return value of - this function should be an RTX that contains the value to use as the return - of `__builtin_saveregs'. - - The argument ARGS is a `tree_list' containing the arguments that were passed - to `__builtin_saveregs'. - - If this macro is not defined, the compiler will output an ordinary call to - the library function `__builtin_saveregs'. */ -/* #define EXPAND_BUILTIN_SAVEREGS(ARGS) */ - -/* This macro offers an alternative to using `__builtin_saveregs' and defining - the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register - arguments into the stack so that all the arguments appear to have been - passed consecutively on the stack. Once this is done, you can use the - standard implementation of varargs that works for machines that pass all - their arguments on the stack. - - The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, containing - the values that obtain after processing of the named arguments. The - arguments MODE and TYPE describe the last named argument--its machine mode - and its data type as a tree node. - - The macro implementation should do two things: first, push onto the stack - all the argument registers *not* used for the named arguments, and second, - store the size of the data thus pushed into the `int'-valued variable whose - name is supplied as the argument PRETEND_ARGS_SIZE. The value that you - store here will serve as additional offset for setting up the stack frame. - - Because you must generate code to push the anonymous arguments at compile - time without knowing their data types, `SETUP_INCOMING_VARARGS' is only - useful on machines that have just a single category of argument register and - use it uniformly for all data types. - - If the argument SECOND_TIME is nonzero, it means that the arguments of the - function are being analyzed for the second time. This happens for an inline - function, which is not actually compiled until the end of the source file. - The macro `SETUP_INCOMING_VARARGS' should not generate any instructions in - this case. */ -#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_ARGS_SIZE, SECOND_TIME) \ - if (! SECOND_TIME) \ - fr30_setup_incoming_varargs (ARGS_SO_FAR, MODE, TYPE, & PRETEND_ARGS_SIZE) - -extern void fr30_setup_incoming_varargs - PROTO ((CUMULATIVE_ARGS, int, Tree, int *)); - -/* 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. */ -#define STRICT_ARGUMENT_NAMING 0 - -/*}}}*/ -/*{{{ Trampolines for Nested Functions. */ - -/* On the FR30, the trampoline is: - - ldi:32 STATIC, r12 - ldi:32 FUNCTION, r0 - jmp @r0 - -/* 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(FILE) \ -{ \ - fprintf (FILE, "\tldi:32\t#0, %s\n", reg_names [STATIC_CHAIN_REGNUM]); \ - fprintf (FILE, "\tldi:32\t#0, %s\n", reg_names [COMPILER_SCRATCH_REGISTER]); \ - fprintf (FILE, "\tjmp\t@%s\n", reg_names [COMPILER_SCRATCH_REGISTER]); \ -} - -/* The name of a subroutine to switch to the section in which the trampoline - template is to be placed. The default is a value of - `readonly_data_section', which places the trampoline in the section - containing read-only data. */ -/* #define TRAMPOLINE_SECTION */ - -/* A C expression for the size in bytes of the trampoline, as an integer. */ -#define TRAMPOLINE_SIZE 14 - -/* Alignment required for trampolines, in bits. - - If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for - aligning trampolines. */ -/* #define TRAMPOLINE_ALIGNMENT */ - -/* A C statement to initialize the variable parts of a trampoline. ADDR is an - RTX for the address of the trampoline; FNADDR is an RTX for the address of - the nested function; STATIC_CHAIN is an RTX for the static chain value that - should be passed to the function when it is called. */ -#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \ -do \ -{ \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (ADDR, 2)), STATIC_CHAIN);\ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (ADDR, 8)), FNADDR); \ -} while (0); - -/* A C expression to allocate run-time space for a trampoline. The expression - value should be an RTX representing a memory reference to the space for the - trampoline. - - If this macro is not defined, by default the trampoline is allocated as a - stack slot. This default is right for most machines. The exceptions are - machines where it is impossible to execute instructions in the stack area. - On such machines, you may have to implement a separate stack, using this - macro in conjunction with `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE'. - - FP points to a data structure, a `struct function', which describes the - compilation status of the immediate containing function of the function - which the trampoline is for. Normally (when `ALLOCATE_TRAMPOLINE' is not - defined), the stack slot for the trampoline is in the stack frame of this - containing function. Other allocation strategies probably must do something - analogous with this information. */ -/* #define ALLOCATE_TRAMPOLINE(FP) */ - -/* Implementing trampolines is difficult on many machines because they have - separate instruction and data caches. Writing into a stack location fails - to clear the memory in the instruction cache, so when the program jumps to - that location, it executes the old contents. - - Here are two possible solutions. One is to clear the relevant parts of the - instruction cache whenever a trampoline is set up. The other is to make all - trampolines identical, by having them jump to a standard subroutine. The - former technique makes trampoline execution faster; the latter makes - initialization faster. - - To clear the instruction cache when a trampoline is initialized, define the - following macros which describe the shape of the cache. */ - -/* The total size in bytes of the cache. */ -/* #define INSN_CACHE_SIZE */ - -/* The length in bytes of each cache line. The cache is divided into cache - lines which are disjoint slots, each holding a contiguous chunk of data - fetched from memory. Each time data is brought into the cache, an entire - line is read at once. The data loaded into a cache line is always aligned - on a boundary equal to the line size. */ -/* #define INSN_CACHE_LINE_WIDTH */ - -/* The number of alternative cache lines that can hold any particular memory - location. */ -/* #define INSN_CACHE_DEPTH */ - -/* Alternatively, if the machine has system calls or instructions to clear the - instruction cache directly, you can define the following macro. */ - -/* If defined, expands to a C expression clearing the *instruction cache* in - the specified interval. If it is not defined, and the macro INSN_CACHE_SIZE - is defined, some generic code is generated to clear the cache. The - definition of this macro would typically be a series of `asm' statements. - Both BEG and END are both pointer expressions. */ -/* #define CLEAR_INSN_CACHE (BEG, END) */ - -/* To use a standard subroutine, define the following macro. In addition, you - must make sure that the instructions in a trampoline fill an entire cache - line with identical instructions, or else ensure that the beginning of the - trampoline code is always aligned at the same point in its cache line. Look - in `m68k.h' as a guide. */ - -/* Define this macro if trampolines need a special subroutine to do their work. - The macro should expand to a series of `asm' statements which will be - compiled with GNU CC. They go in a library function named - `__transfer_from_trampoline'. - - If you need to avoid executing the ordinary prologue code of a compiled C - function when you jump to the subroutine, you can do so by placing a special - label of your own in the assembler code. Use one `asm' statement to - generate an assembler label, and another to make the label global. Then - trampolines can use that label to jump directly to your special assembler - code. */ -/* #define TRANSFER_FROM_TRAMPOLINE */ - -/*}}}*/ -/*{{{ Implicit Calls to Library Routines */ - -/* A C string constant giving the name of the function to call for - multiplication of one signed full-word by another. If you do not define - this macro, the default name is used, which is `__mulsi3', a function - defined in `libgcc.a'. */ -/* #define MULSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for division of - one signed full-word by another. If you do not define this macro, the - default name is used, which is `__divsi3', a function defined in `libgcc.a'. */ -/* #define DIVSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for division of - one unsigned full-word by another. If you do not define this macro, the - default name is used, which is `__udivsi3', a function defined in - `libgcc.a'. */ -/* #define UDIVSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for the - remainder in division of one signed full-word by another. If you do not - define this macro, the default name is used, which is `__modsi3', a function - defined in `libgcc.a'. */ -/* #define MODSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for the - remainder in division of one unsigned full-word by another. If you do not - define this macro, the default name is used, which is `__umodsi3', a - function defined in `libgcc.a'. */ -/* #define UMODSI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for - multiplication of one signed double-word by another. If you do not define - this macro, the default name is used, which is `__muldi3', a function - defined in `libgcc.a'. */ -/* #define MULDI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for division of - one signed double-word by another. If you do not define this macro, the - default name is used, which is `__divdi3', a function defined in `libgcc.a'. */ -/* #define DIVDI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for division of - one unsigned full-word by another. If you do not define this macro, the - default name is used, which is `__udivdi3', a function defined in - `libgcc.a'. */ -/* #define UDIVDI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for the - remainder in division of one signed double-word by another. If you do not - define this macro, the default name is used, which is `__moddi3', a function - defined in `libgcc.a'. */ -/* #define MODDI3_LIBCALL */ - -/* A C string constant giving the name of the function to call for the - remainder in division of one unsigned full-word by another. If you do not - define this macro, the default name is used, which is `__umoddi3', a - function defined in `libgcc.a'. */ -/* #define UMODDI3_LIBCALL */ - -/* Define this macro as a C statement that declares additional library routines - renames existing ones. `init_optabs' calls this macro after initializing all - the normal library routines. */ -/* #define INIT_TARGET_OPTABS */ - -/* The value of `EDOM' on the target machine, as a C integer constant - expression. If you don't define this macro, GNU CC does not attempt to - deposit the value of `EDOM' into `errno' directly. Look in - `/usr/include/errno.h' to find the value of `EDOM' on your system. - - If you do not define `TARGET_EDOM', then compiled code reports domain errors - by calling the library function and letting it report the error. If - mathematical functions on your system use `matherr' when there is an error, - then you should leave `TARGET_EDOM' undefined so that `matherr' is used - normally. */ -/* #define TARGET_EDOM */ - -/* Define this macro as a C expression to create an rtl expression that refers - to the global "variable" `errno'. (On certain systems, `errno' may not - actually be a variable.) If you don't define this macro, a reasonable - default is used. */ -/* #define GEN_ERRNO_RTX */ - -/* Define this macro if GNU CC should generate calls to the System V (and ANSI - C) library functions `memcpy' and `memset' rather than the BSD functions - `bcopy' and `bzero'. - - Defined in svr4.h. */ -#define TARGET_MEM_FUNCTIONS - -/* Define this macro if only `float' arguments cannot be passed to library - routines (so they must be converted to `double'). This macro affects both - how library calls are generated and how the library routines in `libgcc1.c' - accept their arguments. It is useful on machines where floating and fixed - point arguments are passed differently, such as the i860. */ -/* #define LIBGCC_NEEDS_DOUBLE */ - -/* Define this macro to override the type used by the library routines to pick - up arguments of type `float'. (By default, they use a union of `float' and - `int'.) - - The obvious choice would be `float'--but that won't work with traditional C - compilers that expect all arguments declared as `float' to arrive as - `double'. To avoid this conversion, the library routines ask for the value - as some other type and then treat it as a `float'. - - On some systems, no other type will work for this. For these systems, you - must use `LIBGCC_NEEDS_DOUBLE' instead, to force conversion of the values - `double' before they are passed. */ -/* #define FLOAT_ARG_TYPE */ - -/* Define this macro to override the way library routines redesignate a `float' - argument as a `float' instead of the type it was passed as. The default is - an expression which takes the `float' field of the union. */ -/* #define FLOATIFY(PASSED_VALUE) */ - -/* Define this macro to override the type used by the library routines to - return values that ought to have type `float'. (By default, they use - `int'.) - - The obvious choice would be `float'--but that won't work with traditional C - compilers gratuitously convert values declared as `float' into `double'. */ -/* #define FLOAT_VALUE_TYPE */ - -/* Define this macro to override the way the value of a `float'-returning - library routine should be packaged in order to return it. These functions - are actually declared to return type `FLOAT_VALUE_TYPE' (normally `int'). - - These values can't be returned as type `float' because traditional C - compilers would gratuitously convert the value to a `double'. - - A local variable named `intify' is always available when the macro `INTIFY' - is used. It is a union of a `float' field named `f' and a field named `i' - whose type is `FLOAT_VALUE_TYPE' or `int'. - - If you don't define this macro, the default definition works by copying the - value through that union. */ -/* #define INTIFY(FLOAT_VALUE) */ - -/* Define this macro as the name of the data type corresponding to `SImode' in - the system's own C compiler. - - You need not define this macro if that type is `long int', as it usually is. */ -/* #define nongcc_SI_type */ - -/* Define this macro as the name of the data type corresponding to the - word_mode in the system's own C compiler. - - You need not define this macro if that type is `long int', as it usually is. */ -/* #define nongcc_word_type */ - -/* Define these macros to supply explicit C statements to carry out various - arithmetic operations on types `float' and `double' in the library routines - in `libgcc1.c'. See that file for a full list of these macros and their - arguments. - - On most machines, you don't need to define any of these macros, because the - C compiler that comes with the system takes care of doing them. */ -/* #define perform_... */ - -/* Define this macro to generate code for Objective C message sending using the - calling convention of the NeXT system. This calling convention involves - passing the object, the selector and the method arguments all at once to the - method-lookup library function. - - The default calling convention passes just the object and the selector to - the lookup function, which returns a pointer to the method. */ -/* #define NEXT_OBJC_RUNTIME */ - -/*}}}*/ -/*{{{ Addressing Modes */ - -/* Define this macro if the machine supports post-increment addressing. */ -/* #define HAVE_POST_INCREMENT 0 */ - -/* Similar for other kinds of addressing. */ -/* #define HAVE_PRE_INCREMENT 0 */ -/* #define HAVE_POST_DECREMENT 0 */ -/* #define HAVE_PRE_DECREMENT 0 */ - -/* A C expression that is 1 if the RTX X is a constant which is a valid - address. On most machines, this can be defined as `CONSTANT_P (X)', but a - few machines are more restrictive in which constant addresses are supported. - - `CONSTANT_P' accepts integer-values expressions whose values are not - explicitly known, such as `symbol_ref', `label_ref', and `high' expressions - and `const' arithmetic expressions, in addition to `const_int' and - `const_double' expressions. */ -#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) - -/* A number, the maximum number of registers that can appear in a valid memory - address. Note that it is up to you to specify a value equal to the maximum - number that `GO_IF_LEGITIMATE_ADDRESS' would ever accept. */ -#define MAX_REGS_PER_ADDRESS 1 - -/* A C compound statement with a conditional `goto LABEL;' executed if X (an - RTX) is a legitimate memory address on the target machine for a memory - operand of mode MODE. - - It usually pays to define several simpler macros to serve as subroutines for - this one. Otherwise it may be too complicated to understand. - - This macro must exist in two variants: a strict variant and a non-strict - one. The strict variant is used in the reload pass. It must be defined so - that any pseudo-register that has not been allocated a hard register is - considered a memory reference. In contexts where some kind of register is - required, a pseudo-register with no hard register must be rejected. - - The non-strict variant is used in other passes. It must be defined to - accept all pseudo-registers in every context where some kind of register is - required. - - Compiler source files that want to use the strict variant of this macro - define the macro `REG_OK_STRICT'. You should use an `#ifdef REG_OK_STRICT' - conditional to define the strict variant in that case and the non-strict - variant otherwise. - - Subroutines to check for acceptable registers for various purposes (one for - base registers, one for index registers, and so on) are typically among the - subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'. Then only these - subroutine macros need have two variants; the higher levels of macros may be - the same whether strict or not. - - Normally, constant addresses which are the sum of a `symbol_ref' and an - integer are stored inside a `const' RTX to mark them as constant. - Therefore, there is no need to recognize such sums specifically as - legitimate addresses. Normally you would simply recognize any `const' as - legitimate. - - Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that - are not marked with `const'. It assumes that a naked `plus' indicates - indexing. If so, then you *must* reject such naked constant sums as - illegitimate addresses, so that none of them will be given to - `PRINT_OPERAND_ADDRESS'. - - On some machines, whether a symbolic address is legitimate depends on the - section that the address refers to. On these machines, define the macro - `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and - then check for it here. When you see a `const', you will have to look - inside it to find the `symbol_ref' in order to determine the section. - - The best way to modify the name string is by adding text to the beginning, - with suitable punctuation to prevent any ambiguity. Allocate the new name - in `saveable_obstack'. You will have to modify `ASM_OUTPUT_LABELREF' to - remove and decode the added text and output the name accordingly, and define - `STRIP_NAME_ENCODING' to access the original name string. - - You can check the information stored here into the `symbol_ref' in the - definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and - `PRINT_OPERAND_ADDRESS'. - - Used in explow.c, recog.c, reload.c. */ - -/* On the FR30 we only have one real addressing mode - an address in a - register. There are three special cases however: - - * indexed addressing using small positive offsets from the stack pointer - - * indexed addressing using small signed offsets from the frame pointer - - * register plus register addresing using R13 as the base register. - - At the moment we only support the first two of these special cases. */ - -#ifdef REG_OK_STRICT -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \ - do \ - { \ - if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ - goto LABEL; \ - if (GET_CODE (X) == PLUS \ - && ((MODE) == SImode || (MODE) == SFmode) \ - && XEXP (X, 0) == stack_pointer_rtx \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && IN_RANGE (INTVAL (XEXP (X, 1)), 0, (1 << 6) - 4)) \ - goto LABEL; \ - if (GET_CODE (X) == PLUS \ - && ((MODE) == SImode || (MODE) == SFmode) \ - && XEXP (X, 0) == frame_pointer_rtx \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && IN_RANGE (INTVAL (XEXP (X, 1)), -(1 << 9), (1 << 9) - 4)) \ - goto LABEL; \ - } \ - while (0) -#else -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \ - do \ - { \ - if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ - goto LABEL; \ - if (GET_CODE (X) == PLUS \ - && ((MODE) == SImode || (MODE) == SFmode) \ - && XEXP (X, 0) == stack_pointer_rtx \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && IN_RANGE (INTVAL (XEXP (X, 1)), 0, (1 << 6) - 4)) \ - goto LABEL; \ - if (GET_CODE (X) == PLUS \ - && ((MODE) == SImode || (MODE) == SFmode) \ - && (XEXP (X, 0) == frame_pointer_rtx \ - || XEXP(X,0) == arg_pointer_rtx) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && IN_RANGE (INTVAL (XEXP (X, 1)), -(1 << 9), (1 << 9) - 4)) \ - goto LABEL; \ - } \ - while (0) -#endif - -/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for - use as a base register. For hard registers, it should always accept those - which the hardware permits and reject the others. Whether the macro accepts - or rejects pseudo registers must be controlled by `REG_OK_STRICT' as - described above. This usually requires two variant definitions, of which - `REG_OK_STRICT' controls the one actually used. */ -#ifdef REG_OK_STRICT -#define REG_OK_FOR_BASE_P(X) (((unsigned) REGNO (X)) <= STACK_POINTER_REGNUM) -#else -#define REG_OK_FOR_BASE_P(X) 1 -#endif - -/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for - use as an index register. - - The difference between an index register and a base register is that the - index register may be scaled. If an address involves the sum of two - registers, neither one of them scaled, then either one may be labeled the - "base" and the other the "index"; but whichever labeling is used must fit - the machine's constraints of which registers may serve in each capacity. - The compiler will try both labelings, looking for one that is valid, and - will reload one or both registers only if neither labeling works. */ -#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X) - -/* A C compound statement that attempts to replace X with a valid memory - address for an operand of mode MODE. WIN will be a C statement label - elsewhere in the code; the macro definition may use - - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); - - to avoid further processing if the address has become legitimate. - - X will always be the result of a call to `break_out_memory_refs', and OLDX - will be the operand that was given to that function to produce X. - - The code generated by this macro should not alter the substructure of X. If - it transforms X into a more legitimate form, it should assign X (which will - always be a C variable) a new value. - - It is not necessary for this macro to come up with a legitimate address. - The compiler has standard ways of doing so in all cases. In fact, it is - safe for this macro to do nothing. But often a machine-dependent strategy - can generate better code. */ -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) - -/* A C statement or compound statement with a conditional `goto LABEL;' - executed if memory address X (an RTX) can have different meanings depending - on the machine mode of the memory reference it is used for or if the address - is valid for some modes but not others. - - Autoincrement and autodecrement addresses typically have mode-dependent - effects because the amount of the increment or decrement is the size of the - operand being addressed. Some machines have other mode-dependent addresses. - Many RISC machines have no mode-dependent addresses. - - You may assume that ADDR is a valid address for the machine. */ -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) - -/* A C expression that is nonzero if X is a legitimate constant for an - immediate operand on the target machine. You can assume that X satisfies - `CONSTANT_P', so you need not check this. In fact, `1' is a suitable - definition for this macro on machines where anything `CONSTANT_P' is valid. */ -#define LEGITIMATE_CONSTANT_P(X) 1 - -/*}}}*/ -/*{{{ Condition Code Status */ - -/* C code for a data type which is used for declaring the `mdep' component of - `cc_status'. It defaults to `int'. - - This macro is not used on machines that do not use `cc0'. */ -/* #define CC_STATUS_MDEP */ - -/* A C expression to initialize the `mdep' field to "empty". The default - definition does nothing, since most machines don't use the field anyway. If - you want to use the field, you should probably define this macro to - initialize it. - - This macro is not used on machines that do not use `cc0'. */ -/* #define CC_STATUS_MDEP_INIT */ - -/* A C compound statement to set the components of `cc_status' appropriately - for an insn INSN whose body is EXP. It is this macro's responsibility to - recognize insns that set the condition code as a byproduct of other activity - as well as those that explicitly set `(cc0)'. - - This macro is not used on machines that do not use `cc0'. - - If there are insns that do not set the condition code but do alter other - machine registers, this macro must check to see whether they invalidate the - expressions that the condition code is recorded as reflecting. For example, - on the 68000, insns that store in address registers do not set the condition - code, which means that usually `NOTICE_UPDATE_CC' can leave `cc_status' - unaltered for such insns. But suppose that the previous insn set the - condition code based on location `a4@(102)' and the current insn stores a - new value in `a4'. Although the condition code is not changed by this, it - will no longer be true that it reflects the contents of `a4@(102)'. - Therefore, `NOTICE_UPDATE_CC' must alter `cc_status' in this case to say - that nothing is known about the condition code value. - - The definition of `NOTICE_UPDATE_CC' must be prepared to deal with the - results of peephole optimization: insns whose patterns are `parallel' RTXs - containing various `reg', `mem' or constants which are just the operands. - The RTL structure of these insns is not sufficient to indicate what the - insns actually do. What `NOTICE_UPDATE_CC' should do when it sees one is - just to run `CC_STATUS_INIT'. - - A possible definition of `NOTICE_UPDATE_CC' is to call a function that looks - at an attribute named, for example, `cc'. This - avoids having detailed information about patterns in two places, the `md' - file and in `NOTICE_UPDATE_CC'. */ -/* #define NOTICE_UPDATE_CC(EXP, INSN) fr30_notice_update_cc (INSN) - extern int fr30_notice_update_cc PROTO ((Rtx)); */ - -/* A list of names to be used for additional modes for condition code values in - registers. These names are added to `enum - machine_mode' and all have class `MODE_CC'. By convention, they should - start with `CC' and end with `mode'. - - You should only define this macro if your machine does not use `cc0' and - only if additional modes are required. */ -/* #define EXTRA_CC_MODES */ - -/* A list of C strings giving the names for the modes listed in - `EXTRA_CC_MODES'. For example, the Sparc defines this macro and - `EXTRA_CC_MODES' as - - #define EXTRA_CC_MODES CC_NOOVmode, CCFPmode, CCFPEmode - #define EXTRA_CC_NAMES "CC_NOOV", "CCFP", "CCFPE" - - This macro is not required if `EXTRA_CC_MODES' is not defined. */ -/* #define EXTRA_CC_NAMES */ - -/* Returns a mode from class `MODE_CC' to be used when comparison operation - code OP is applied to rtx X and Y. For example, on the Sparc, - `SELECT_CC_MODE' is defined as (see *note Jump Patterns::. for a - description of the reason for this definition) - - #define SELECT_CC_MODE(OP,X,Y) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ - : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ - || GET_CODE (X) == NEG) \ - ? CC_NOOVmode : CCmode)) - - You need not define this macro if `EXTRA_CC_MODES' is not defined. */ -/* #define SELECT_CC_MODE(OP, X, Y) */ - -/* One some machines not all possible comparisons are defined, but you can - convert an invalid comparison into a valid one. For example, the Alpha does - not have a `GT' comparison, but you can use an `LT' comparison instead and - swap the order of the operands. - - On such machines, define this macro to be a C statement to do any required - conversions. CODE is the initial comparison code and OP0 and OP1 are the - left and right operands of the comparison, respectively. You should modify - CODE, OP0, and OP1 as required. - - GNU CC will not assume that the comparison resulting from this macro is - valid but will see if the resulting insn matches a pattern in the `md' file. - - You need not define this macro if it would never change the comparison code - or operands. */ -/* #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) */ - -/* A C expression whose value is one if it is always safe to reverse a - comparison whose mode is MODE. If `SELECT_CC_MODE' can ever return MODE for - a floating-point inequality comparison, then `REVERSIBLE_CC_MODE (MODE)' - must be zero. - - You need not define this macro if it would always returns zero or if the - floating-point format is anything other than `IEEE_FLOAT_FORMAT'. For - example, here is the definition used on the Sparc, where floating-point - inequality comparisons are always given `CCFPEmode': - - #define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode) */ -/* #define REVERSIBLE_CC_MODE(MODE) */ - -/*}}}*/ -/*{{{ Describing Relative Costs of Operations */ - -/* A part of a C `switch' statement that describes the relative costs of - constant RTL expressions. It must contain `case' labels for expression - codes `const_int', `const', `symbol_ref', `label_ref' and `const_double'. - Each case must ultimately reach a `return' statement to return the relative - cost of the use of that kind of constant value in an expression. The cost - may depend on the precise value of the constant, which is available for - examination in X, and the rtx code of the expression in which it is - contained, found in OUTER_CODE. - - CODE is the expression code--redundant, since it can be obtained with - `GET_CODE (X)'. */ -/* #define CONST_COSTS(X, CODE, OUTER_CODE) */ - -/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. This can be - used, for example, to indicate how costly a multiply instruction is. In - writing this macro, you can use the construct `COSTS_N_INSNS (N)' to specify - a cost equal to N fast instructions. OUTER_CODE is the code of the - expression in which X is contained. - - This macro is optional; do not define it if the default cost assumptions are - adequate for the target machine. */ -/* #define RTX_COSTS(X, CODE, OUTER_CODE) */ - -/* An expression giving the cost of an addressing mode that contains ADDRESS. - If not defined, the cost is computed from the ADDRESS expression and the - `CONST_COSTS' values. - - For most CISC machines, the default cost is a good approximation of the true - cost of the addressing mode. However, on RISC machines, all instructions - normally have the same length and execution time. Hence all addresses will - have equal costs. - - In cases where more than one form of an address is known, the form with the - lowest cost will be used. If multiple forms have the same, lowest, cost, - the one that is the most complex will be used. - - For example, suppose an address that is equal to the sum of a register and a - constant is used twice in the same basic block. When this macro is not - defined, the address will be computed in a register and memory references - will be indirect through that register. On machines where the cost of the - addressing mode containing the sum is no higher than that of a simple - indirect reference, this will produce an additional instruction and possibly - require an additional register. Proper specification of this macro - eliminates this overhead for such machines. - - Similar use of this macro is made in strength reduction of loops. - - ADDRESS need not be valid as an address. In such a case, the cost is not - relevant and can be any value; invalid addresses need not be assigned a - different cost. - - On machines where an address involving more than one register is as cheap as - an address computation involving only one register, defining `ADDRESS_COST' - to reflect this can cause two registers to be live over a region of code - where only one would have been if `ADDRESS_COST' were not defined in that - manner. This effect should be considered in the definition of this macro. - Equivalent costs should probably only be given to addresses with different - numbers of registers on machines with lots of registers. - - This macro will normally either not be defined or be defined as a constant. */ -/* #define ADDRESS_COST(ADDRESS) */ - -/* A C expression for the cost of moving data from a register in class FROM to - one in class TO. The classes are expressed using the enumeration values - such as `GENERAL_REGS'. A value of 4 is the default; other values are - interpreted relative to that. - - It is not required that the cost always equal 2 when FROM is the same as TO; - on some machines it is expensive to move between registers if they are not - general registers. - - If reload sees an insn consisting of a single `set' between two hard - registers, and if `REGISTER_MOVE_COST' applied to their classes returns a - value of 2, reload does not check to ensure that the constraints of the insn - are met. Setting a cost of other than 2 will allow reload to verify that - the constraints are met. You should do this if the `movM' pattern's - constraints do not allow such copying. */ -/* #define REGISTER_MOVE_COST(FROM, TO) */ - -/* A C expression for the cost of moving data of mode M between a register and - memory. A value of 2 is the default; this cost is relative to those in - `REGISTER_MOVE_COST'. - - If moving between registers and memory is more expensive than between two - registers, you should define this macro to express the relative cost. */ -/* #define MEMORY_MOVE_COST(M,C,I) */ - -/* A C expression for the cost of a branch instruction. A value of 1 is the - default; other values are interpreted relative to that. - -/* Here are additional macros which do not specify precise relative costs, but - only that certain actions are more expensive than GNU CC would ordinarily - expect. */ - -/* #define BRANCH_COST */ - -/* Define this macro as a C expression which is nonzero if accessing less than - a word of memory (i.e. a `char' or a `short') is no faster than accessing a - word of memory, i.e., if such access require more than one instruction or if - there is no difference in cost between byte and (aligned) word loads. - - When this macro is not defined, the compiler will access a field by finding - the smallest containing object; when it is defined, a fullword load will be - used if alignment permits. Unless bytes accesses are faster than word - accesses, using word accesses is preferable since it may eliminate - subsequent memory access if subsequent accesses occur to other fields in the - same word of the structure, but to different bytes. */ -#define SLOW_BYTE_ACCESS 1 - -/* Define this macro if zero-extension (of a `char' or `short' to an `int') can - be done faster if the destination is a register that is known to be zero. - - If you define this macro, you must have instruction patterns that recognize - RTL structures like this: - - (set (strict_low_part (subreg:QI (reg:SI ...) 0)) ...) - - and likewise for `HImode'. */ -#define SLOW_ZERO_EXTEND 0 - -/* Define this macro to be the value 1 if unaligned accesses have a cost many - times greater than aligned accesses, for example if they are emulated in a - trap handler. - - When this macro is non-zero, the compiler will act as if `STRICT_ALIGNMENT' - were non-zero when generating code for block moves. This can cause - significantly more instructions to be produced. Therefore, do not set this - macro non-zero if unaligned accesses only add a cycle or two to the time for - a memory access. - - If the value of this macro is always zero, it need not be defined. */ -/* #define SLOW_UNALIGNED_ACCESS */ - -/* Define this macro to inhibit strength reduction of memory addresses. (On - some machines, such strength reduction seems to do harm rather than good.) */ -/* #define DONT_REDUCE_ADDR */ - -/* The number of scalar move insns which should be generated instead of a - string move insn or a library call. Increasing the value will always make - code faster, but eventually incurs high cost in increased code size. - - If you don't define this, a reasonable default is used. */ -/* #define MOVE_RATIO */ - -/* 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 */ - -/* Define this macro if it is as good or better for a function to call itself - with an explicit address than to call an address kept in a register. */ -/* #define NO_RECURSIVE_FUNCTION_CSE */ - -/* A C statement (sans semicolon) to update the integer variable COST based on - the relationship between INSN that is dependent on DEP_INSN through the - dependence LINK. The default is to make no adjustment to COST. This can be - used for example to specify to the scheduler that an output- or - anti-dependence does not incur the same cost as a data-dependence. */ -/* #define ADJUST_COST(INSN, LINK, DEP_INSN, COST) */ - -/* A C statement (sans semicolon) to update the integer scheduling - priority `INSN_PRIORITY(INSN)'. Reduce the priority to execute - the INSN earlier, increase the priority to execute INSN later. - Do not define this macro if you do not need to adjust the - scheduling priorities of insns. */ -/* #define ADJUST_PRIORITY (INSN) */ - -/*}}}*/ -/*{{{ Dividing the output into sections. */ - -/* A C expression whose value is a string containing the assembler operation - that should precede instructions and read-only data. Normally `".text"' is - right. */ -#define TEXT_SECTION_ASM_OP ".text" - -/* A C expression whose value is a string containing the assembler operation to - identify the following data as writable initialized data. Normally - `".data"' is right. */ -#define DATA_SECTION_ASM_OP ".data" - -/* if defined, a C expression whose value is a string containing the assembler - operation to identify the following data as shared data. If not defined, - `DATA_SECTION_ASM_OP' will be used. */ -/* #define SHARED_SECTION_ASM_OP */ - -/* 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 ".bss" - -/* If defined, a C expression whose value is a string containing the - assembler operation to identify the following data as - uninitialized global shared data. If not defined, and - `BSS_SECTION_ASM_OP' is, the latter will be used. */ -/* #define SHARED_BSS_SECTION_ASM_OP */ - -/* A list of names for sections other than the standard two, which are - `in_text' and `in_data'. You need not define this macro on a system with no - other sections (that GCC needs to use). - - Defined in svr4.h. */ -/* #define EXTRA_SECTIONS */ - -/* One or more functions to be defined in `varasm.c'. These functions should - do jobs analogous to those of `text_section' and `data_section', for your - additional sections. Do not define this macro if you do not define - `EXTRA_SECTIONS'. - - Defined in svr4.h. */ -/* #define EXTRA_SECTION_FUNCTIONS */ - -/* On most machines, read-only variables, constants, and jump tables are placed - in the text section. If this is not the case on your machine, this macro - should be defined to be the name of a function (either `data_section' or a - function defined in `EXTRA_SECTIONS') that switches to the section to be - used for read-only items. - - If these items should be placed in the text section, this macro should not - be defined. */ -/* #define READONLY_DATA_SECTION */ - -/* A C statement or statements to switch to the appropriate section for output - of EXP. You can assume that EXP is either a `VAR_DECL' node or a constant - of some sort. RELOC indicates whether the initial value of EXP requires - link-time relocations. Select the section by calling `text_section' or one - of the alternatives for other sections. - - Do not define this macro if you put all read-only variables and constants in - the read-only data section (usually the text section). - - Defined in svr4.h. */ -/* #define SELECT_SECTION(EXP, RELOC) */ - -/* 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. - - Do not define this macro if you put all constants in the read-only data - section. - - Defined in svr4.h. */ -/* #define SELECT_RTX_SECTION(MODE, RTX) */ - -/* Define this macro if jump tables (for `tablejump' insns) should be output in - the text section, along with the assembler instructions. Otherwise, the - readonly data section is used. - - This macro is irrelevant if there is no separate readonly data section. */ -/* #define JUMP_TABLES_IN_TEXT_SECTION */ - -/* Define this macro if references to a symbol must be treated differently - depending on something about the variable or function named by the symbol - (such as what section it is in). - - The macro definition, if any, is executed immediately after the rtl for DECL - has been created and stored in `DECL_RTL (DECL)'. The value of the rtl will - be a `mem' whose address is a `symbol_ref'. - - The usual thing for this macro to do is to record a flag in the `symbol_ref' - (such as `SYMBOL_REF_FLAG') or to store a modified name string in the - `symbol_ref' (if one bit is not enough information). */ -/* #define ENCODE_SECTION_INFO(DECL) */ - -/* Decode SYM_NAME and store the real name part in VAR, sans the characters - that encode section info. Define this macro if `ENCODE_SECTION_INFO' alters - the symbol's name string. */ -/* #define STRIP_NAME_ENCODING(VAR, SYM_NAME) */ - -/* A C expression which evaluates to true if DECL should be placed - into a unique section for some target-specific reason. If you do - not define this macro, the default is `0'. Note that the flag - `-ffunction-sections' will also cause functions to be placed into - unique sections. - - Defined in svr4.h. */ -/* #define UNIQUE_SECTION_P(DECL) */ - -/* 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, GNU CC - will use the symbol name prefixed by `.' as the section name. - - Defined in svr4.h. */ -/* #define UNIQUE_SECTION(DECL, RELOC) */ - -/*}}}*/ -/*{{{ Position Independent Code. */ - -/* The register number of the register used to address a table of static data - addresses in memory. In some cases this register is defined by a - processor's "application binary interface" (ABI). When this macro is - defined, RTL is generated for this register once, as with the stack pointer - and frame pointer registers. If this macro is not defined, it is up to the - machine-dependent files to allocate such a register (if necessary). */ -/* #define PIC_OFFSET_TABLE_REGNUM */ - -/* Define this macro if the register defined by `PIC_OFFSET_TABLE_REGNUM' is - clobbered by calls. Do not define this macro if `PPIC_OFFSET_TABLE_REGNUM' - is not defined. */ -/* #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 not check this. You can also - assume FLAG_PIC is true, so you need not check it either. You need not - define this macro if all constants (including `SYMBOL_REF') can be immediate - operands when generating position independent code. */ -/* #define LEGITIMATE_PIC_OPERAND_P(X) */ - -/*}}}*/ -/*{{{ The Overall Framework of an Assembler File. */ - -/* A C expression which outputs to the stdio stream STREAM some appropriate - text to go at the end of an assembler file. - - If this macro is not defined, the default is to output nothing special at - the end of the file. Most systems don't require any definition. - - On systems that use SDB, it is necessary to output certain commands; see - `attasm.h'. - - Defined in svr4.h. */ -/* #define ASM_FILE_END(STREAM) */ - -/* A C statement to output assembler commands which will identify the object - file as having been compiled with GNU CC (or another GNU compiler). - - If you don't define this macro, the string `gcc_compiled.:' is output. This - string is calculated to define a symbol which, on BSD systems, will never be - defined for any other reason. GDB checks for the presence of this symbol - when reading the symbol table of an executable. - - On non-BSD systems, you must arrange communication with GDB in some other - fashion. If GDB is not used on your system, you can define this macro with - an empty body. - - Defined in svr4.h. */ -/* #define ASM_IDENTIFY_GCC(FILE) */ - -/* Like ASM_IDENTIFY_GCC, but used when dbx debugging is selected to emit - a stab the debugger uses to identify gcc as the compiler that is emitted - after the stabs for the filename, which makes it easier for GDB to parse. - - Defined in svr4.h. */ -/* #define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) */ - -/* A C string constant describing how to begin a comment in the target - assembler language. The compiler assumes that the comment will end at the - end of the line. */ -#define ASM_COMMENT_START ";" - -/* A C string constant for text to be output before each `asm' statement or - group of consecutive ones. Normally this is `"#APP"', which is a comment - that has no effect on most assemblers but tells the GNU assembler that it - must check the lines that follow for all valid assembler constructs. */ -#define ASM_APP_ON "#APP\n" - -/* A C string constant for text to be output after each `asm' statement or - group of consecutive ones. Normally this is `"#NO_APP"', which tells the - GNU assembler to resume making the time-saving assumptions that are valid - for ordinary compiler output. */ -#define ASM_APP_OFF "#NO_APP\n" - -/* A C statement to output COFF information or DWARF debugging information - which indicates that filename NAME is the current source file to the stdio - stream STREAM. - - This macro need not be defined if the standard form of output for the file - format in use is appropriate. */ -/* #define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) */ - -/* A C statement to output DBX or SDB debugging information before code for - line number LINE of the current source file to the stdio stream STREAM. - - This macro need not be defined if the standard form of debugging information - for the debugger in use is appropriate. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) */ - -/* A C statement to output something to the assembler file to handle a `#ident' - directive containing the text STRING. If this macro is not defined, nothing - is output for a `#ident' directive. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_IDENT(STREAM, STRING) */ - -/* A C statement to output something to the assembler file to switch to section - NAME for object DECL which is either a `FUNCTION_DECL', a `VAR_DECL' or - `NULL_TREE'. Some target formats do not support arbitrary sections. Do not - define this macro in such cases. - - At present this macro is only used to support section attributes. When this - macro is undefined, section attributes are disabled. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME) */ - -/* A C statement to output any assembler statements which are required to - precede any Objective C object definitions or message sending. The - statement is executed only when compiling an Objective C program. */ -/* #define OBJC_PROLOGUE */ - -/*}}}*/ -/*{{{ Output of Data. */ - -/* A C statement to output to the stdio stream STREAM an assembler instruction - to assemble a floating-point constant of `TFmode', `DFmode', `SFmode', - `TQFmode', `HFmode', or `QFmode', respectively, whose value is VALUE. VALUE - will be a C expression of type `REAL_VALUE_TYPE'. Macros such as - `REAL_VALUE_TO_TARGET_DOUBLE' are useful for writing these definitions. */ -/* #define ASM_OUTPUT_LONG_DOUBLE(STREAM, VALUE) */ -/* #define ASM_OUTPUT_THREE_QUARTER_FLOAT(STREAM, VALUE) */ -/* #define ASM_OUTPUT_SHORT_FLOAT(STREAM, VALUE) */ -/* #define ASM_OUTPUT_BYTE_FLOAT(STREAM, VALUE) */ - -/* This is how to output an assembler line defining a `float' constant. */ -#define ASM_OUTPUT_FLOAT(FILE, VALUE) \ -do { \ - long t; \ - char str[30]; \ - REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ - fprintf (FILE, "\t.word\t0x%lx %s %s\n", \ - t, ASM_COMMENT_START, str); \ -} while (0) - -/* This is how to output an assembler line defining a `double' constant. */ -#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \ -do { \ - long t[2]; \ - char str[30]; \ - REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \ - REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \ - fprintf (FILE, "\t.word\t0x%lx %s %s\n\t.word\t0x%lx\n", \ - t[0], ASM_COMMENT_START, str, t[1]); \ -} while (0) - - -/* A C statement to output to the stdio stream STREAM an assembler instruction - to assemble an integer of 16, 8, 4, 2 or 1 bytes, respectively, whose value - is VALUE. The argument EXP will be an RTL expression which represents a - constant value. Use `output_addr_const (STREAM, EXP)' to output this value - as an assembler expression. - - For sizes larger than `UNITS_PER_WORD', if the action of a macro would be - identical to repeatedly calling the macro corresponding to a size of - `UNITS_PER_WORD', once for each word, you need not define the macro. */ -/* #define ASM_OUTPUT_QUADRUPLE_INT(STREAM, EXP) */ -/* #define ASM_OUTPUT_DOUBLE_INT(STREAM, EXP) */ - -/* This is how to output an assembler line defining a `char' constant. */ -#define ASM_OUTPUT_CHAR(FILE, VALUE) \ -do { \ - fprintf (FILE, "\t.byte\t"); \ - output_addr_const (FILE, (VALUE)); \ - fprintf (FILE, "\n"); \ -} while (0) - -/* This is how to output an assembler line defining a `short' constant. */ -#define ASM_OUTPUT_SHORT(FILE, VALUE) \ -do { \ - fprintf (FILE, "\t.hword\t"); \ - output_addr_const (FILE, (VALUE)); \ - fprintf (FILE, "\n"); \ -} while (0) - -/* This is how to output an assembler line defining an `int' constant. - We also handle symbol output here. */ -#define ASM_OUTPUT_INT(FILE, VALUE) \ -do { \ - fprintf (FILE, "\t.word\t"); \ - output_addr_const (FILE, (VALUE)); \ - fprintf (FILE, "\n"); \ -} while (0) - -/* A C statement to output to the stdio stream STREAM an assembler instruction - to assemble a single byte containing the number VALUE. */ -#define ASM_OUTPUT_BYTE(STREAM, VALUE) \ - fprintf (STREAM, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE)) - -/* A C string constant giving the pseudo-op to use for a sequence of - single-byte constants. If this macro is not defined, the default - is `"byte"'. - - Defined in svr4.h. */ -/* #define ASM_BYTE_OP */ - -/* A C statement to output to the stdio stream STREAM an assembler instruction - to assemble a string constant containing the LEN bytes at PTR. PTR will be - a C expression of type `char *' and LEN a C expression of type `int'. - - If the assembler has a `.ascii' pseudo-op as found in the Berkeley Unix - assembler, do not define the macro `ASM_OUTPUT_ASCII'. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_ASCII(STREAM, PTR, LEN) */ - -/* You may define this macro as a C expression. You should define the - expression to have a non-zero value if GNU CC should output the - constant pool for a function before the code for the function, or - a zero value if GNU CC should output the constant pool after the - function. If you do not define this macro, the usual case, GNU CC - will output the constant pool before the function. */ -/* #define CONSTANT_POOL_BEFORE_FUNCTION */ - -/* A C statement to output assembler commands to define the start of the - constant pool for a function. FUNNAME is a string giving the name of the - function. Should the return type of the function be required, it can be - obtained via FUNDECL. SIZE is the size, in bytes, of the constant pool that - will be written immediately after this call. - - If no constant-pool prefix is required, the usual case, this macro need not - be defined. */ -/* #define ASM_OUTPUT_POOL_PROLOGUE(FILE FUNNAME FUNDECL SIZE) */ - -/* A C statement (with or without semicolon) to output a constant in the - constant pool, if it needs special treatment. (This macro need not do - anything for RTL expressions that can be output normally.) - - The argument FILE is the standard I/O stream to output the assembler code - on. X is the RTL expression for the constant to output, and MODE is the - machine mode (in case X is a `const_int'). ALIGN is the required alignment - for the value X; you should output an assembler directive to force this much - alignment. - - The argument LABELNO is a number to use in an internal label for the address - of this pool entry. The definition of this macro is responsible for - outputting the label definition at the proper place. Here is how to do - this: - - ASM_OUTPUT_INTERNAL_LABEL (FILE, "LC", LABELNO); - - When you output a pool entry specially, you should end with a `goto' to the - label JUMPTO. This will prevent the same pool entry from being output a - second time in the usual manner. - - You need not define this macro if it would do nothing. */ -/* #define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, JUMPTO) */ - -/* Define this macro as a C expression which is nonzero if the constant EXP, of - type `tree', should be output after the code for a function. The compiler - will normally output all constants before the function; you need not define - this macro if this is OK. */ -/* #define CONSTANT_AFTER_FUNCTION_P(EXP) */ - -/* A C statement to output assembler commands to at the end of the constant - pool for a function. FUNNAME is a string giving the name of the function. - Should the return type of the function be required, you can obtain it via - FUNDECL. SIZE is the size, in bytes, of the constant pool that GNU CC wrote - immediately before this call. - - If no constant-pool epilogue is required, the usual case, you need not - define this macro. */ -/* #define ASM_OUTPUT_POOL_EPILOGUE (FILE FUNNAME FUNDECL SIZE) */ - -/* Define this macro as a C expression which is nonzero if C is used as a - logical line separator by the assembler. - - If you do not define this macro, the default is that only the character `;' - is treated as a logical line separator. */ -/* #define IS_ASM_LOGICAL_LINE_SEPARATOR(C) */ - -/* These macros are defined as C string constant, describing the syntax in the - assembler for grouping arithmetic expressions. The following definitions - are correct for most assemblers: - - #define ASM_OPEN_PAREN "(" - #define ASM_CLOSE_PAREN ")" */ -#define ASM_OPEN_PAREN "(" -#define ASM_CLOSE_PAREN ")" - -/* These macros are provided by `real.h' for writing the definitions of - `ASM_OUTPUT_DOUBLE' and the like: */ - -/* These translate X, of type `REAL_VALUE_TYPE', to the target's floating point - representation, and store its bit pattern in the array of `long int' whose - address is L. The number of elements in the output array is determined by - the size of the desired target floating point data type: 32 bits of it go in - each `long int' array element. Each array element holds 32 bits of the - result, even if `long int' is wider than 32 bits on the host machine. - - The array element values are designed so that you can print them out using - `fprintf' in the order they should appear in the target machine's memory. */ -/* #define REAL_VALUE_TO_TARGET_SINGLE(X, L) */ -/* #define REAL_VALUE_TO_TARGET_DOUBLE(X, L) */ -/* #define REAL_VALUE_TO_TARGET_LONG_DOUBLE(X, L) */ - -/* This macro converts X, of type `REAL_VALUE_TYPE', to a decimal number and - stores it as a string into STRING. You must pass, as STRING, the address of - a long enough block of space to hold the result. - - The argument FORMAT is a `printf'-specification that serves as a suggestion - for how to format the output string. */ -/* #define REAL_VALUE_TO_DECIMAL(X, FORMAT, STRING) */ - -/*}}}*/ -/*{{{ Output of Uninitialized Variables. */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM the - assembler definition of a common-label named NAME whose size is SIZE bytes. - The variable ROUNDED is the size rounded up to whatever alignment the caller - wants. - - Use the expression `assemble_name (STREAM, NAME)' to output the name itself; - before and after that, output the additional assembler syntax for defining - the name, and a newline. - - This macro controls how the assembler definitions of uninitialized global - variables are output. */ -/* #define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) */ - -/* Like `ASM_OUTPUT_COMMON' except takes the required alignment as a separate, - explicit argument. If you define this macro, it is used in place of - `ASM_OUTPUT_COMMON', and gives you more flexibility in handling the required - alignment of the variable. The alignment is specified as the number of - bits. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_ALIGNED_COMMON(STREAM, NAME, SIZE, ALIGNMENT) */ - -/* Like ASM_OUTPUT_ALIGNED_COMMON except that it takes an additional argument - - the DECL of the variable to be output, if there is one. This macro can be - called with DECL == NULL_TREE. If you define this macro, it is used in - place of both ASM_OUTPUT_COMMON and ASM_OUTPUT_ALIGNED_COMMON, and gives you - more flexibility in handling the destination of the variable. */ -/* #define ASM_OUTPUT_DECL_COMMON (STREAM, DECL, NAME, SIZE, ALIGNMENT) */ - -/* If defined, it is similar to `ASM_OUTPUT_COMMON', except that it is used - when NAME is shared. If not defined, `ASM_OUTPUT_COMMON' will be used. */ -/* #define ASM_OUTPUT_SHARED_COMMON(STREAM, NAME, SIZE, ROUNDED) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM the - assembler definition of uninitialized global DECL named NAME whose size is - SIZE bytes. The variable ROUNDED is the size rounded up to whatever - alignment the caller wants. - - Try to use function `asm_output_bss' defined in `varasm.c' when defining - this macro. If unable, use the expression `assemble_name (STREAM, NAME)' to - output the name itself; before and after that, output the additional - assembler syntax for defining the name, and a newline. - - This macro controls how the assembler definitions of uninitialized global - variables are output. This macro exists to properly support languages like - `c++' which do not have `common' data. However, this macro currently is not - defined for all targets. If this macro and `ASM_OUTPUT_ALIGNED_BSS' are not - defined then `ASM_OUTPUT_COMMON' or `ASM_OUTPUT_ALIGNED_COMMON' or - `ASM_OUTPUT_DECL_COMMON' is used. */ -/* #define ASM_OUTPUT_BSS(STREAM, DECL, NAME, SIZE, ROUNDED) */ - -/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a separate, - explicit argument. If you define this macro, it is used in place of - `ASM_OUTPUT_BSS', and gives you more flexibility in handling the required - alignment of the variable. The alignment is specified as the number of - bits. - - Try to use function `asm_output_aligned_bss' defined in file `varasm.c' when - defining this macro. */ -/* #define ASM_OUTPUT_ALIGNED_BSS(STREAM, DECL, NAME, SIZE, ALIGNMENT) */ - -/* If defined, it is similar to `ASM_OUTPUT_BSS', except that it is used when - NAME is shared. If not defined, `ASM_OUTPUT_BSS' will be used. */ -/* #define ASM_OUTPUT_SHARED_BSS(STREAM, DECL, NAME, SIZE, ROUNDED) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM the - assembler definition of a local-common-label named NAME whose size is SIZE - bytes. The variable ROUNDED is the size rounded up to whatever alignment - the caller wants. - - Use the expression `assemble_name (STREAM, NAME)' to output the name itself; - before and after that, output the additional assembler syntax for defining - the name, and a newline. - - This macro controls how the assembler definitions of uninitialized static - variables are output. */ -/* #define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) */ - -/* Like `ASM_OUTPUT_LOCAL' except takes the required alignment as a separate, - explicit argument. If you define this macro, it is used in place of - `ASM_OUTPUT_LOCAL', and gives you more flexibility in handling the required - alignment of the variable. The alignment is specified as the number of - bits. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGNMENT) */ - -/* Like `ASM_OUTPUT_ALIGNED_LOCAL' except that it takes an additional - parameter - the DECL of variable to be output, if there is one. - This macro can be called with DECL == NULL_TREE. If you define - this macro, it is used in place of `ASM_OUTPUT_LOCAL' and - `ASM_OUTPUT_ALIGNED_LOCAL', and gives you more flexibility in - handling the destination of the variable. */ -/* #define ASM_OUTPUT_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) */ - -/* If defined, it is similar to `ASM_OUTPUT_LOCAL', except that it is used when - NAME is shared. If not defined, `ASM_OUTPUT_LOCAL' will be used. */ -/* #define ASM_OUTPUT_SHARED_LOCAL (STREAM, NAME, SIZE, ROUNDED) */ - -/*}}}*/ -/*{{{ Output and Generation of Labels. */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM the - assembler definition of a label named NAME. Use the expression - `assemble_name (STREAM, NAME)' to output the name itself; before and after - that, output the additional assembler syntax for defining the name, and a - newline. */ -#define ASM_OUTPUT_LABEL(STREAM, NAME) \ -do { \ - assemble_name (STREAM, NAME); \ - fputs (":\n", STREAM); \ -} while (0) - -/* A C statement (sans semicolon) to output to the stdio stream STREAM any text - necessary for declaring the name NAME of a function which is being defined. - This macro is responsible for outputting the label definition (perhaps using - `ASM_OUTPUT_LABEL'). The argument DECL is the `FUNCTION_DECL' tree node - representing the function. - - If this macro is not defined, then the function name is defined in the usual - manner as a label (by means of `ASM_OUTPUT_LABEL'). - - Defined in svr4.h. */ -/* #define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM any text - necessary for declaring the size of a function which is being defined. The - argument NAME is the name of the function. The argument DECL is the - `FUNCTION_DECL' tree node representing the function. - - If this macro is not defined, then the function size is not defined. - - Defined in svr4.h. */ -/* #define ASM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM any text - necessary for declaring the name NAME of an initialized variable which is - being defined. This macro must output the label definition (perhaps using - `ASM_OUTPUT_LABEL'). The argument DECL is the `VAR_DECL' tree node - representing the variable. - - If this macro is not defined, then the variable name is defined in the usual - manner as a label (by means of `ASM_OUTPUT_LABEL'). - - Defined in svr4.h. */ -/* #define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) */ - -/* A C statement (sans semicolon) to finish up declaring a variable name once - the compiler has processed its initializer fully and thus has had a chance - to determine the size of an array when controlled by an initializer. This - is used on systems where it's necessary to declare something about the size - of the object. - - If you don't define this macro, that is equivalent to defining it to do - nothing. - - Defined in svr4.h. */ -/* #define ASM_FINISH_DECLARE_OBJECT(STREAM, DECL, TOPLEVEL, ATEND) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM some - commands that will make the label NAME global; that is, available for - reference from other files. Use the expression `assemble_name (STREAM, - NAME)' to output the name itself; before and after that, output the - additional assembler syntax for making that name global, and a newline. */ -#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \ -do { \ - fputs ("\t.globl ", STREAM); \ - assemble_name (STREAM, NAME); \ - fputs ("\n", STREAM); \ -} while (0) - -/* A C statement (sans semicolon) to output to the stdio stream STREAM some - commands that will make the label NAME weak; that is, available for - reference from other files but only used if no other definition is - available. Use the expression `assemble_name (STREAM, NAME)' to output the - name itself; before and after that, output the additional assembler syntax - for making that name weak, and a newline. - - If you don't define this macro, GNU CC will not support weak symbols and you - should not define the `SUPPORTS_WEAK' macro. - - Defined in svr4.h. */ -/* #define ASM_WEAKEN_LABEL */ - -/* A C expression which evaluates to true if the target supports weak symbols. - - If you don't define this macro, `defaults.h' provides a default definition. - If `ASM_WEAKEN_LABEL' is defined, the default definition is `1'; otherwise, - it is `0'. Define this macro if you want to control weak symbol support - with a compiler flag such as `-melf'. */ -/* #define SUPPORTS_WEAK */ - -/* A C statement (sans semicolon) to mark DECL to be emitted as a - public symbol such that extra copies in multiple translation units - will be discarded by the linker. Define this macro if your object - file format provides support for this concept, such as the `COMDAT' - section flags in the Microsoft Windows PE/COFF format, and this - support requires changes to DECL, such as putting it in a separate - section. - - Defined in svr4.h. */ -/* #define MAKE_DECL_ONE_ONLY */ - -/* A C expression which evaluates to true if the target supports one-only - semantics. - - If you don't define this macro, `varasm.c' provides a default definition. - If `MAKE_DECL_ONE_ONLY' is defined, the default definition is `1'; - otherwise, it is `0'. Define this macro if you want to control one-only - symbol support with a compiler flag, or if setting the `DECL_ONE_ONLY' flag - is enough to mark a declaration to be emitted as one-only. */ -/* #define SUPPORTS_ONE_ONLY */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM any text - necessary for declaring the name of an external symbol named NAME which is - referenced in this compilation but not defined. The value of DECL is the - tree node for the declaration. - - This macro need not be defined if it does not need to output anything. The - GNU assembler and most Unix assemblers don't require anything. */ -/* #define ASM_OUTPUT_EXTERNAL(STREAM, DECL, NAME) */ - -/* A C statement (sans semicolon) to output on STREAM an assembler pseudo-op to - declare a library function name external. The name of the library function - is given by SYMREF, which has type `rtx' and is a `symbol_ref'. - - This macro need not be defined if it does not need to output anything. The - GNU assembler and most Unix assemblers don't require anything. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM, SYMREF) */ - -/* A C statement (sans semicolon) to output to the stdio stream STREAM a - reference in assembler syntax to a label named NAME. This should add `_' to - the front of the name, if that is customary on your operating system, as it - is in most Berkeley Unix systems. This macro is used in `assemble_name'. */ -/* #define ASM_OUTPUT_LABELREF(STREAM, NAME) */ - -/* A C statement to output to the stdio stream STREAM a label whose name is - made from the string PREFIX and the number NUM. - - It is absolutely essential that these labels be distinct from the labels - used for user-level functions and variables. Otherwise, certain programs - will have name conflicts with internal labels. - - It is desirable to exclude internal labels from the symbol table of the - object file. Most assemblers have a naming convention for labels that - should be excluded; on many systems, the letter `L' at the beginning of a - label has this effect. You should find out what convention your system - uses, and follow it. - - The usual definition of this macro is as follows: - - fprintf (STREAM, "L%s%d:\n", PREFIX, NUM) - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) */ - -/* A C expression to assign to OUTVAR (which is a variable of type `char *') a - newly allocated string made from the string NAME and the number NUMBER, with - some suitable punctuation added. Use `alloca' to get space for the string. - - The string will be used as an argument to `ASM_OUTPUT_LABELREF' to produce - an assembler label for an internal static variable whose name is NAME. - Therefore, the string must be such as to result in valid assembler code. - The argument NUMBER is different each time this macro is executed; it - prevents conflicts between similarly-named internal static variables in - different scopes. - - Ideally this string should not be a valid C identifier, to prevent any - conflict with the user's own symbols. Most assemblers allow periods or - percent signs in assembler symbols; putting at least one of these between - the name and the number will suffice. */ -#define ASM_FORMAT_PRIVATE_NAME(OUTVAR, NAME, NUMBER) \ -do { \ - (OUTVAR) = (char *) alloca (strlen ((NAME)) + 12); \ - sprintf ((OUTVAR), "%s.%ld", (NAME), (long)(NUMBER)); \ -} while (0) - -/* A C statement to output to the stdio stream STREAM assembler code which - defines (equates) the symbol NAME to have the value VALUE. - - If SET_ASM_OP is defined, a default definition is provided which is correct - for most systems. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_DEF(STREAM, NAME, VALUE) */ - -/* A C statement to output to the stdio stream STREAM assembler code which - defines (equates) the weak symbol NAME to have the value VALUE. - - Define this macro if the target only supports weak aliases; define - ASM_OUTPUT_DEF instead if possible. */ -/* #define ASM_OUTPUT_WEAK_ALIAS (STREAM, NAME, VALUE) */ - -/* Define this macro to override the default assembler names used for Objective - C methods. - - The default name is a unique method number followed by the name of the class - (e.g. `_1_Foo'). For methods in categories, the name of the category is - also included in the assembler name (e.g. `_1_Foo_Bar'). - - These names are safe on most systems, but make debugging difficult since the - method's selector is not present in the name. Therefore, particular systems - define other ways of computing names. - - BUF is an expression of type `char *' which gives you a buffer in which to - store the name; its length is as long as CLASS_NAME, CAT_NAME and SEL_NAME - put together, plus 50 characters extra. - - The argument IS_INST specifies whether the method is an instance method or a - class method; CLASS_NAME is the name of the class; CAT_NAME is the name of - the category (or NULL if the method is not in a category); and SEL_NAME is - the name of the selector. - - On systems where the assembler can handle quoted names, you can use this - macro to provide more human-readable names. */ -/* #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME) */ - -/*}}}*/ -/*{{{ Macros Controlling Initialization Routines. */ - -/* If defined, a C string constant for the assembler operation to identify the - following data as initialization code. If not defined, GNU CC will assume - such a section does not exist. When you are using special sections for - initialization and termination functions, this macro also controls how - `crtstuff.c' and `libgcc2.c' arrange to run the initialization functions. - - Defined in svr4.h. */ -/* #define INIT_SECTION_ASM_OP */ - -/* If defined, `main' will not call `__main' as described above. This macro - should be defined for systems that control the contents of the init section - on a symbol-by-symbol basis, such as OSF/1, and should not be defined - explicitly for systems that support `INIT_SECTION_ASM_OP'. */ -/* #define HAS_INIT_SECTION */ - -/* If defined, a C string constant for a switch that tells the linker that the - following symbol is an initialization routine. */ -/* #define LD_INIT_SWITCH */ - -/* If defined, a C string constant for a switch that tells the linker that the - following symbol is a finalization routine. */ -/* #define LD_FINI_SWITCH */ - -/* If defined, `main' will call `__main' despite the presence of - `INIT_SECTION_ASM_OP'. This macro should be defined for systems where the - init section is not actually run automatically, but is still useful for - collecting the lists of constructors and destructors. */ -/* #define INVOKE__main */ - -/* Define this macro as a C statement to output on the stream STREAM the - assembler code to arrange to call the function named NAME at initialization - time. - - Assume that NAME is the name of a C function generated automatically by the - compiler. This function takes no arguments. Use the function - `assemble_name' to output the name NAME; this performs any system-specific - syntactic transformations such as adding an underscore. - - If you don't define this macro, nothing special is output to arrange to call - the function. This is correct when the function will be called in some - other manner--for example, by means of the `collect2' program, which looks - through the symbol table to find these functions by their names. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_CONSTRUCTOR(STREAM, NAME) */ - -/* This is like `ASM_OUTPUT_CONSTRUCTOR' but used for termination functions - rather than initialization functions. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_DESTRUCTOR(STREAM, NAME) */ - -/* If your system uses `collect2' as the means of processing constructors, then - that program normally uses `nm' to scan an object file for constructor - functions to be called. On certain kinds of systems, you can define these - macros to make `collect2' work faster (and, in some cases, make it work at - all): */ - -/* Define this macro if the system uses COFF (Common Object File Format) object - files, so that `collect2' can assume this format and scan object files - directly for dynamic constructor/destructor functions. */ -/* #define OBJECT_FORMAT_COFF */ - -/* Define this macro if the system uses ROSE format object files, so that - `collect2' can assume this format and scan object files directly for dynamic - constructor/destructor functions. - - These macros are effective only in a native compiler; `collect2' as - part of a cross compiler always uses `nm' for the target machine. */ -/* #define OBJECT_FORMAT_ROSE */ - -/* Define this macro if the system uses ELF format object files. - - Defined in svr4.h. */ -/* #define OBJECT_FORMAT_ELF */ - -/* Define this macro as a C string constant containing the file name to use to - execute `nm'. The default is to search the path normally for `nm'. - - If your system supports shared libraries and has a program to list the - dynamic dependencies of a given library or executable, you can define these - macros to enable support for running initialization and termination - functions in shared libraries: */ -/* #define REAL_NM_FILE_NAME */ - -/* Define this macro to a C string constant containing the name of the program - which lists dynamic dependencies, like `"ldd"' under SunOS 4. */ -/* #define LDD_SUFFIX */ - -/* Define this macro to be C code that extracts filenames from the output of - the program denoted by `LDD_SUFFIX'. PTR is a variable of type `char *' - that points to the beginning of a line of output from `LDD_SUFFIX'. If the - line lists a dynamic dependency, the code must advance PTR to the beginning - of the filename on that line. Otherwise, it must set PTR to `NULL'. */ -/* #define PARSE_LDD_OUTPUT (PTR) */ - -/*}}}*/ -/*{{{ Output of Assembler Instructions. */ - -/* Define this macro if you are using an unusual assembler that requires - different names for the machine instructions. - - The definition is a C statement or statements which output an assembler - instruction opcode to the stdio stream STREAM. The macro-operand PTR is a - variable of type `char *' which points to the opcode name in its "internal" - form--the form that is written in the machine description. The definition - should output the opcode name to STREAM, performing any translation you - desire, and increment the variable PTR to point at the end of the opcode so - that it will not be output twice. - - In fact, your macro definition may process less than the entire opcode name, - or more than the opcode name; but if you want to process text that includes - `%'-sequences to substitute operands, you must take care of the substitution - yourself. Just be sure to increment PTR over whatever text should not be - output normally. - - If you need to look at the operand values, they can be found as the elements - of `recog_operand'. - - If the macro definition does nothing, the instruction is output in the usual - way. */ -/* #define ASM_OUTPUT_OPCODE(STREAM, PTR) */ - -/* If defined, a C statement to be executed just prior to the output of - assembler code for INSN, to modify the extracted operands so they will be - output differently. - - Here the argument OPVEC is the vector containing the operands extracted from - INSN, and NOPERANDS is the number of elements of the vector which contain - meaningful data for this insn. The contents of this vector are what will be - used to convert the insn template into assembler code, so you can change the - assembler output by changing the contents of the vector. - - This macro is useful when various assembler syntaxes share a single file of - instruction patterns; by defining this macro differently, you can cause a - large class of instructions to be output differently (such as with - rearranged operands). Naturally, variations in assembler syntax affecting - individual insn patterns ought to be handled by writing conditional output - routines in those patterns. - - If this macro is not defined, it is equivalent to a null statement. */ -/* #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) */ - -/* If defined, `FINAL_PRESCAN_INSN' will be called on each - `CODE_LABEL'. In that case, OPVEC will be a null pointer and - NOPERANDS will be zero. */ -/* #define FINAL_PRESCAN_LABEL */ - -/* 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. */ -#define PRINT_OPERAND(STREAM, X, CODE) fr30_print_operand (STREAM, X, CODE) - -extern void fr30_print_operand STDIO_PROTO((FILE *, Rtx, int)); - -/* A C expression which evaluates to true if CODE is a valid punctuation - character for use in the `PRINT_OPERAND' macro. If - `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no punctuation - characters (except for the standard one, `%') are used in this way. */ -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) (CODE == '#') - -/* A C compound statement to output to stdio stream STREAM the assembler syntax - for an instruction operand that is a memory reference whose address is X. X - is an RTL expression. - - On some machines, the syntax for a symbolic address depends on the section - that the address refers to. On these machines, define the macro - `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and - then check for it here. *Note Assembler Format::. */ -#define PRINT_OPERAND_ADDRESS(STREAM, X) fr30_print_operand_address (STREAM, X) -extern void fr30_print_operand_address STDIO_PROTO((FILE *, Rtx)); - -/* 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(FILE) */ - -/* If defined, C string expressions to be used for the `%R', `%L', `%U', and - `%I' options of `asm_fprintf' (see `final.c'). These are useful when a - single `md' file must support multiple assembler formats. In that case, the - various `tm.h' files can define these macros differently. - - USER_LABEL_PREFIX is defined in svr4.h. */ -#define REGISTER_PREFIX "%" -#define LOCAL_LABEL_PREFIX "." -#define USER_LABEL_PREFIX "" -#define IMMEDIATE_PREFIX "" - -/* If your target supports multiple dialects of assembler language (such as - different opcodes), define this macro as a C expression that gives the - numeric index of the assembler language dialect to use, with zero as the - first variant. - - If this macro is defined, you may use `{option0|option1|option2...}' - constructs in the output templates of patterns or - in the first argument of `asm_fprintf'. This construct outputs `option0', - `option1' or `option2', etc., if the value of `ASSEMBLER_DIALECT' is zero, - one or two, etc. Any special characters within these strings retain their - usual meaning. - - If you do not define this macro, the characters `{', `|' and `}' do not have - any special meaning when used in templates or operands to `asm_fprintf'. - - Define the macros `REGISTER_PREFIX', `LOCAL_LABEL_PREFIX', - `USER_LABEL_PREFIX' and `IMMEDIATE_PREFIX' if you can express the variations - in assemble language syntax with that mechanism. Define `ASSEMBLER_DIALECT' - and use the `{option0|option1}' syntax if the syntax variant are larger and - involve such things as different opcodes or operand order. */ -/* #define ASSEMBLER_DIALECT */ - -/* A C expression to output to STREAM some assembler code which will push hard - register number REGNO onto the stack. The code need not be optimal, since - this macro is used only when profiling. */ -/* #define ASM_OUTPUT_REG_PUSH (STREAM, REGNO) */ - -/* A C expression to output to STREAM some assembler code which will pop hard - register number REGNO off of the stack. The code need not be optimal, since - this macro is used only when profiling. */ -/* #define ASM_OUTPUT_REG_POP (STREAM, REGNO) */ - -/*}}}*/ -/*{{{ Output of dispatch tables. */ - -/* This macro should be provided on machines where the addresses in a dispatch - table are relative to the table's own address. - - The definition should be a C statement to output to the stdio stream STREAM - an assembler pseudo-instruction to generate a difference between two labels. - VALUE and REL are the numbers of two internal labels. The definitions of - these labels are output using `ASM_OUTPUT_INTERNAL_LABEL', and they must be - printed in the same way here. For example, - - fprintf (STREAM, "\t.word L%d-L%d\n", VALUE, REL) */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ -fprintf (STREAM, "\t.word .L%d-.L%d\n", VALUE, REL) - -/* This macro should be provided on machines where the addresses in a dispatch - table are absolute. - - The definition should be a C statement to output to the stdio stream STREAM - an assembler pseudo-instruction to generate a reference to a label. VALUE - is the number of an internal label whose definition is output using - `ASM_OUTPUT_INTERNAL_LABEL'. For example, - - fprintf (STREAM, "\t.word L%d\n", VALUE) */ -#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ -fprintf (STREAM, "\t.word .L%d\n", VALUE) - -/* Define this if the label before a jump-table needs to be output specially. - The first three arguments are the same as for `ASM_OUTPUT_INTERNAL_LABEL'; - the fourth argument is the jump-table which follows (a `jump_insn' - containing an `addr_vec' or `addr_diff_vec'). - - This feature is used on system V to output a `swbeg' statement for the - table. - - If this macro is not defined, these labels are output with - `ASM_OUTPUT_INTERNAL_LABEL'. - - Defined in svr4.h. */ -/* #define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, TABLE) */ - -/* Define this if something special must be output at the end of a jump-table. - The definition should be a C statement to be executed after the assembler - code for the table is written. It should write the appropriate code to - stdio stream STREAM. The argument TABLE is the jump-table insn, and NUM is - the label-number of the preceding label. - - If this macro is not defined, nothing special is output at the end of the - jump-table. */ -/* #define ASM_OUTPUT_CASE_END(STREAM, NUM, TABLE) */ - -/*}}}*/ -/*{{{ Assembler Commands for Exception Regions. */ - -/* A C expression to output text to mark the start of an exception region. - - This macro need not be defined on most platforms. */ -/* #define ASM_OUTPUT_EH_REGION_BEG() */ - -/* A C expression to output text to mark the end of an exception region. - - This macro need not be defined on most platforms. */ -/* #define ASM_OUTPUT_EH_REGION_END() */ - -/* A C expression to switch to the section in which the main exception table is - to be placed. The default is a section named - `.gcc_except_table' on machines that support named sections via - `ASM_OUTPUT_SECTION_NAME', otherwise if `-fpic' or `-fPIC' is in effect, the - `data_section', otherwise the `readonly_data_section'. */ -/* #define EXCEPTION_SECTION() */ - -/* If defined, a C string constant for the assembler operation to switch to the - section for exception handling frame unwind information. If not defined, - GNU CC will provide a default definition if the target supports named - sections. `crtstuff.c' uses this macro to switch to the appropriate - section. - - You should define this symbol if your target supports DWARF 2 frame unwind - information and the default definition does not work. */ -/* #define EH_FRAME_SECTION_ASM_OP */ - -/* A C expression that is nonzero if the normal exception table output should - be omitted. - - This macro need not be defined on most platforms. */ -/* #define OMIT_EH_TABLE() */ - -/* Alternate runtime support for looking up an exception at runtime and finding - the associated handler, if the default method won't work. - - This macro need not be defined on most platforms. */ -/* #define EH_TABLE_LOOKUP() */ - -/* A C expression that decides whether or not the current function needs to - have a function unwinder generated for it. See the file `except.c' for - details on when to define this, and how. */ -/* #define DOESNT_NEED_UNWINDER */ - -/* An rtx used to mask the return address found via RETURN_ADDR_RTX, so that it - does not contain any extraneous set bits in it. */ -/* #define MASK_RETURN_ADDR */ - -/* Define this macro to 0 if your target supports DWARF 2 frame unwind - information, but it does not yet work with exception handling. Otherwise, - if your target supports this information (if it defines - `INCOMING_RETURN_ADDR_RTX' and either `UNALIGNED_INT_ASM_OP' or - `OBJECT_FORMAT_ELF'), GCC will provide a default definition of 1. - - If this macro is defined to 1, the DWARF 2 unwinder will be the default - exception handling mechanism; otherwise, setjmp/longjmp will be used by - default. - - If this macro is defined to anything, the DWARF 2 unwinder will be used - instead of inline unwinders and __unwind_function in the non-setjmp case. */ -/* #define DWARF2_UNWIND_INFO */ - -/*}}}*/ -/*{{{ Assembler Commands for Alignment. */ - -/* The alignment (log base 2) to put in front of LABEL, which follows - a BARRIER. - - This macro need not be defined if you don't want any special alignment to be - done at such a time. Most machine descriptions do not currently define the - macro. */ -/* #define LABEL_ALIGN_AFTER_BARRIER(LABEL) */ - -/* The desired alignment for the location counter at the beginning - of a loop. - - This macro need not be defined if you don't want any special alignment to be - done at such a time. Most machine descriptions do not currently define the - macro. */ -/* #define LOOP_ALIGN(LABEL) */ - -/* Define this macro if `ASM_OUTPUT_SKIP' should not be used in the text - section because it fails put zeros in the bytes that are skipped. This is - true on many Unix systems, where the pseudo-op to skip bytes produces no-op - instructions rather than zeros when used in the text section. */ -/* #define ASM_NO_SKIP_IN_TEXT */ - -/* A C statement to output to the stdio stream STREAM an assembler command to - advance the location counter to a multiple of 2 to the POWER bytes. POWER - will be a C expression of type `int'. */ -#define ASM_OUTPUT_ALIGN(STREAM, POWER) \ - fprintf ((STREAM), "\t.p2align %d\n", (POWER)) - -/*}}}*/ -/*{{{ Macros Affecting all Debug Formats. */ - -/* A C expression that returns the DBX register number for the compiler - register number REGNO. In simple cases, the value of this expression may be - REGNO itself. But sometimes there are some registers that the compiler - knows about and DBX does not, or vice versa. In such cases, some register - may need to have one number in the compiler and another for DBX. - - If two registers have consecutive numbers inside GNU CC, and they can be - used as a pair to hold a multiword value, then they *must* have consecutive - numbers after renumbering with `DBX_REGISTER_NUMBER'. Otherwise, debuggers - will be unable to access such a pair, because they expect register pairs to - be consecutive in their own numbering scheme. - - If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not - preserve register pairs, then what you must do instead is redefine the - actual register numbering scheme. */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* A C expression that returns the integer offset value for an automatic - variable having address X (an RTL expression). The default computation - assumes that X is based on the frame-pointer and gives the offset from the - frame-pointer. This is required for targets that produce debugging output - for DBX or COFF-style debugging output for SDB and allow the frame-pointer - to be eliminated when the `-g' options is used. */ -/* #define DEBUGGER_AUTO_OFFSET(X) */ - -/* A C expression that returns the integer offset value for an argument having - address X (an RTL expression). The nominal offset is OFFSET. */ -/* #define DEBUGGER_ARG_OFFSET(OFFSET, X) */ - -/* A C expression that returns the type of debugging output GNU CC produces - when the user specifies `-g' or `-ggdb'. Define this if you have arranged - for GNU CC to support more than one format of debugging output. Currently, - the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG', - `DWARF2_DEBUG', and `XCOFF_DEBUG'. - - The value of this macro only affects the default debugging output; the user - can always get a specific type of output by using `-gstabs', `-gcoff', - `-gdwarf-1', `-gdwarf-2', or `-gxcoff'. - - Defined in svr4.h. */ -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG - -/*}}}*/ -/*{{{ Macros for SDB and Dwarf Output. */ - -/* Define this macro if GNU CC should produce dwarf format debugging output in - response to the `-g' option. - - Defined in svr4.h. */ -#define DWARF_DEBUGGING_INFO - -/* Define this macro if GNU CC should produce dwarf version 2 format debugging - output in response to the `-g' option. - - To support optional call frame debugging information, you must also define - `INCOMING_RETURN_ADDR_RTX' and either set `RTX_FRAME_RELATED_P' on the - prologue insns if you use RTL for the prologue, or call `dwarf2out_def_cfa' - and `dwarf2out_reg_save' as appropriate from `FUNCTION_PROLOGUE' if you - don't. - - Defined in svr4.h. */ -#define DWARF2_DEBUGGING_INFO - -/* Define these macros to override the assembler syntax for the special SDB - assembler directives. See `sdbout.c' for a list of these macros and their - arguments. If the standard syntax is used, you need not define them - yourself. */ -/* #define PUT_SDB_... */ - -/* Some assemblers do not support a semicolon as a delimiter, even between SDB - assembler directives. In that case, define this macro to be the delimiter - to use (usually `\n'). It is not necessary to define a new set of - `PUT_SDB_OP' macros if this is the only change required. */ -/* #define SDB_DELIM */ - -/* Define this macro to override the usual method of constructing a dummy name - for anonymous structure and union types. See `sdbout.c' for more - information. */ -/* #define SDB_GENERATE_FAKE */ - -/* Define this macro to allow references to unknown structure, union, or - enumeration tags to be emitted. Standard COFF does not allow handling of - unknown references, MIPS ECOFF has support for it. */ -/* #define SDB_ALLOW_UNKNOWN_REFERENCES */ - -/* Define this macro to allow references to structure, union, or enumeration - tags that have not yet been seen to be handled. Some assemblers choke if - forward tags are used, while some require it. */ -/* #define SDB_ALLOW_FORWARD_REFERENCES */ - -#define DWARF_LINE_MIN_INSTR_LENGTH 2 - -/*}}}*/ -/*{{{ Cross Compilation and Floating Point. */ - -/* While all modern machines use 2's complement representation for integers, - there are a variety of representations for floating point numbers. This - means that in a cross-compiler the representation of floating point numbers - in the compiled program may be different from that used in the machine doing - the compilation. - - Because different representation systems may offer different amounts of - range and precision, the cross compiler cannot safely use the host machine's - floating point arithmetic. Therefore, floating point constants must be - represented in the target machine's format. This means that the cross - compiler cannot use `atof' to parse a floating point constant; it must have - its own special routine to use instead. Also, constant folding must emulate - the target machine's arithmetic (or must not be done at all). - - The macros in the following table should be defined only if you are cross - compiling between different floating point formats. - - Otherwise, don't define them. Then default definitions will be set up which - use `double' as the data type, `==' to test for equality, etc. - - You don't need to worry about how many times you use an operand of any of - these macros. The compiler never uses operands which have side effects. */ - -/* A macro for the C data type to be used to hold a floating point value in the - target machine's format. Typically this would be a `struct' containing an - array of `int'. */ -/* #define REAL_VALUE_TYPE */ - -/* A macro for a C expression which compares for equality the two values, X and - Y, both of type `REAL_VALUE_TYPE'. */ -/* #define REAL_VALUES_EQUAL(X, Y) */ - -/* A macro for a C expression which tests whether X is less than Y, both values - being of type `REAL_VALUE_TYPE' and interpreted as floating point numbers in - the target machine's representation. */ -/* #define REAL_VALUES_LESS(X, Y) */ - -/* A macro for a C expression which performs the standard library function - `ldexp', but using the target machine's floating point representation. Both - X and the value of the expression have type `REAL_VALUE_TYPE'. The second - argument, SCALE, is an integer. */ -/* #define REAL_VALUE_LDEXP(X, SCALE) */ - -/* A macro whose definition is a C expression to convert the target-machine - floating point value X to a signed integer. X has type `REAL_VALUE_TYPE'. */ -/* #define REAL_VALUE_FIX(X) */ - -/* A macro whose definition is a C expression to convert the target-machine - floating point value X to an unsigned integer. X has type - `REAL_VALUE_TYPE'. */ -/* #define REAL_VALUE_UNSIGNED_FIX(X) */ - -/* A macro whose definition is a C expression to round the target-machine - floating point value X towards zero to an integer value (but still as a - floating point number). X has type `REAL_VALUE_TYPE', and so does the - value. */ -/* #define REAL_VALUE_RNDZINT(X) */ - -/* A macro whose definition is a C expression to round the target-machine - floating point value X towards zero to an unsigned integer value (but still - represented as a floating point number). X has type `REAL_VALUE_TYPE', and - so does the value. */ -/* #define REAL_VALUE_UNSIGNED_RNDZINT(X) */ - -/* A macro for a C expression which converts STRING, an expression of type - `char *', into a floating point number in the target machine's - representation for mode MODE. The value has type `REAL_VALUE_TYPE'. */ -/* #define REAL_VALUE_ATOF(STRING, MODE) */ - -/* Define this macro if infinity is a possible floating point value, and - therefore division by 0 is legitimate. */ -/* #define REAL_INFINITY */ - -/* A macro for a C expression which determines whether X, a floating point - value, is infinity. The value has type `int'. By default, this is defined - to call `isinf'. */ -/* #define REAL_VALUE_ISINF(X) */ - -/* A macro for a C expression which determines whether X, a floating point - value, is a "nan" (not-a-number). The value has type `int'. By default, - this is defined to call `isnan'. */ -/* #define REAL_VALUE_ISNAN(X) */ - -/* Define the following additional macros if you want to make floating point - constant folding work while cross compiling. If you don't define them, - cross compilation is still possible, but constant folding will not happen - for floating point values. */ - -/* A macro for a C statement which calculates an arithmetic operation of the - two floating point values X and Y, both of type `REAL_VALUE_TYPE' in the - target machine's representation, to produce a result of the same type and - representation which is stored in OUTPUT (which will be a variable). - - The operation to be performed is specified by CODE, a tree code which will - always be one of the following: `PLUS_EXPR', `MINUS_EXPR', `MULT_EXPR', - `RDIV_EXPR', `MAX_EXPR', `MIN_EXPR'. - - The expansion of this macro is responsible for checking for overflow. If - overflow happens, the macro expansion should execute the statement `return - 0;', which indicates the inability to perform the arithmetic operation - requested. */ -/* #define REAL_ARITHMETIC(OUTPUT, CODE, X, Y) */ - -/* A macro for a C expression which returns the negative of the floating point - value X. Both X and the value of the expression have type `REAL_VALUE_TYPE' - and are in the target machine's floating point representation. - - There is no way for this macro to report overflow, since overflow can't - happen in the negation operation. */ -/* #define REAL_VALUE_NEGATE(X) */ - -/* A macro for a C expression which converts the floating point value X to mode - MODE. - - Both X and the value of the expression are in the target machine's floating - point representation and have type `REAL_VALUE_TYPE'. However, the value - should have an appropriate bit pattern to be output properly as a floating - constant whose precision accords with mode MODE. - - There is no way for this macro to report overflow. */ -/* #define REAL_VALUE_TRUNCATE(MODE, X) */ - -/* A macro for a C expression which converts a floating point value X into a - double-precision integer which is then stored into LOW and HIGH, two - variables of type INT. */ -/* #define REAL_VALUE_TO_INT(LOW, HIGH, X) */ - -/* A macro for a C expression which converts a double-precision integer found - in LOW and HIGH, two variables of type INT, into a floating point value - which is then stored into X. */ -/* #define REAL_VALUE_FROM_INT(X, LOW, HIGH) */ - -/*}}}*/ -/*{{{ Miscellaneous Parameters. */ - -/* An alias for a machine mode name. This is the machine mode that elements of - a jump-table should have. */ -#define CASE_VECTOR_MODE SImode - -/* Define 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 if control falls through a `case' insn when the index value is - out of range. This means the specified default-label is actually ignored by - the `case' insn proper. */ -/* #define CASE_DROPS_THROUGH */ - -/* Define this to be the smallest number of different values for which it is - best to use a jump-table instead of a tree of conditional branches. The - default is four for machines with a `casesi' instruction and five otherwise. - This is best for most machines. */ -/* #define CASE_VALUES_THRESHOLD */ - -/* Define this macro if operations between registers with integral mode smaller - than a word are always performed on the entire register. Most RISC machines - have this property and most CISC machines do not. */ -/* #define WORD_REGISTER_OPERATIONS */ - -/* Define this macro to be a C expression indicating when insns that read - memory in MODE, an integral mode narrower than a word, set the bits outside - of MODE to be either the sign-extension or the zero-extension of the data - read. Return `SIGN_EXTEND' for values of MODE for which the insn - sign-extends, `ZERO_EXTEND' for which it zero-extends, and `NIL' for other - modes. - - This macro is not called with MODE non-integral or with a width greater than - or equal to `BITS_PER_WORD', so you may return any value in this case. Do - not define this macro if it would always return `NIL'. On machines where - this macro is defined, you will normally define it as the constant - `SIGN_EXTEND' or `ZERO_EXTEND'. */ -/* #define LOAD_EXTEND_OP (MODE) */ - -/* Define if loading short immediate values into registers sign extends. */ -/* #define SHORT_IMMEDIATES_SIGN_EXTEND */ - -/* An alias for a tree code that should be used by default for conversion of - floating point values to fixed point. Normally, `FIX_ROUND_EXPR' is used. */ -/* #define IMPLICIT_FIX_EXPR */ - -/* Define this macro if the same instructions that convert a floating point - number to a signed fixed point number also convert validly to an unsigned - one. */ -/* #define FIXUNS_TRUNC_LIKE_FIX_TRUNC */ - -/* An alias for a tree code that is the easiest kind of division to compile - code for in the general case. It may be `TRUNC_DIV_EXPR', `FLOOR_DIV_EXPR', - `CEIL_DIV_EXPR' or `ROUND_DIV_EXPR'. These four division operators differ - in how they round the result to an integer. `EASY_DIV_EXPR' is used when it - is permissible to use any of those kinds of division and the choice should - be made on the basis of efficiency. */ -#define EASY_DIV_EXPR TRUNC_DIV_EXPR - -/* The maximum number of bytes that a single instruction can move quickly from - memory to memory. */ -#define MOVE_MAX 8 - -/* The maximum number of bytes that a single instruction can move quickly from - memory to memory. If this is undefined, the default is `MOVE_MAX'. - Otherwise, it is the constant value that is the largest value that - `MOVE_MAX' can have at run-time. */ -/* #define MAX_MOVE_MAX */ - -/* A C expression that is nonzero if on this machine the number of bits - actually used for the count of a shift operation is equal to the number of - bits needed to represent the size of the object being shifted. When this - macro is non-zero, the compiler will assume that it is safe to omit a - sign-extend, zero-extend, and certain bitwise `and' instructions that - truncates the count of a shift operation. On machines that have - instructions that act on bitfields at variable positions, which may include - `bit test' instructions, a nonzero `SHIFT_COUNT_TRUNCATED' also enables - deletion of truncations of the values that serve as arguments to bitfield - instructions. - - If both types of instructions truncate the count (for shifts) and position - (for bitfield operations), or if no variable-position bitfield instructions - exist, you should define this macro. - - However, on some machines, such as the 80386 and the 680x0, truncation only - applies to shift operations and not the (real or pretended) bitfield - operations. Define `SHIFT_COUNT_TRUNCATED' to be zero on such machines. - Instead, add patterns to the `md' file that include the implied truncation - of the shift instructions. - - You need not define this macro if it would always have the value of zero. */ -/* #define SHIFT_COUNT_TRUNCATED */ - -/* A C expression which is nonzero if on this machine it is safe to "convert" - an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller - than INPREC) by merely operating on it as if it had only OUTPREC bits. - - On many machines, this expression can be 1. - - When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for - which `MODES_TIEABLE_P' is 0, suboptimal code can result. If this is the - case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve - things. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* A C expression describing the value returned by a comparison operator with - an integral mode and stored by a store-flag instruction (`sCOND') when the - condition is true. This description must apply to *all* the `sCOND' - patterns and all the comparison operators whose results have a `MODE_INT' - mode. - - A value of 1 or -1 means that the instruction implementing the comparison - operator returns exactly 1 or -1 when the comparison is true and 0 when the - comparison is false. Otherwise, the value indicates which bits of the - result are guaranteed to be 1 when the comparison is true. This value is - interpreted in the mode of the comparison operation, which is given by the - mode of the first operand in the `sCOND' pattern. Either the low bit or the - sign bit of `STORE_FLAG_VALUE' be on. Presently, only those bits are used - by the compiler. - - If `STORE_FLAG_VALUE' is neither 1 or -1, the compiler will generate code - that depends only on the specified bits. It can also replace comparison - operators with equivalent operations if they cause the required bits to be - set, even if the remaining bits are undefined. For example, on a machine - whose comparison operators return an `SImode' value and where - `STORE_FLAG_VALUE' is defined as `0x80000000', saying that just the sign bit - is relevant, the expression - - (ne:SI (and:SI X (const_int POWER-OF-2)) (const_int 0)) - - can be converted to - - (ashift:SI X (const_int N)) - - where N is the appropriate shift count to move the bit being tested into the - sign bit. - - There is no way to describe a machine that always sets the low-order bit for - a true value, but does not guarantee the value of any other bits, but we do - not know of any machine that has such an instruction. If you are trying to - port GNU CC to such a machine, include an instruction to perform a - logical-and of the result with 1 in the pattern for the comparison operators - and let us know. - - Often, a machine will have multiple instructions that obtain a value from a - comparison (or the condition codes). Here are rules to guide the choice of - value for `STORE_FLAG_VALUE', and hence the instructions to be used: - - * Use the shortest sequence that yields a valid definition for - `STORE_FLAG_VALUE'. It is more efficient for the compiler to - "normalize" the value (convert it to, e.g., 1 or 0) than for - the comparison operators to do so because there may be - opportunities to combine the normalization with other - operations. - - * For equal-length sequences, use a value of 1 or -1, with -1 - being slightly preferred on machines with expensive jumps and - 1 preferred on other machines. - - * As a second choice, choose a value of `0x80000001' if - instructions exist that set both the sign and low-order bits - but do not define the others. - - * Otherwise, use a value of `0x80000000'. - - Many machines can produce both the value chosen for `STORE_FLAG_VALUE' and - its negation in the same number of instructions. On those machines, you - should also define a pattern for those cases, e.g., one matching - - (set A (neg:M (ne:M B C))) - - Some machines can also perform `and' or `plus' operations on condition code - values with less instructions than the corresponding `sCOND' insn followed - by `and' or `plus'. On those machines, define the appropriate patterns. - Use the names `incscc' and `decscc', respectively, for the the patterns - which perform `plus' or `minus' operations on condition code values. See - `rs6000.md' for some examples. The GNU Superoptizer can be used to find - such instruction sequences on other machines. - - You need not define `STORE_FLAG_VALUE' if the machine has no store-flag - instructions. */ -/* #define STORE_FLAG_VALUE */ - -/* A C expression that gives a non-zero floating point value that is returned - when comparison operators with floating-point results are true. Define this - macro on machine that have comparison operations that return floating-point - values. If there are no such operations, do not define this macro. */ -/* #define FLOAT_STORE_FLAG_VALUE */ - -/* An alias for the machine mode for pointers. On most machines, define this - to be the integer mode corresponding to the width of a hardware pointer; - `SImode' on 32-bit machine or `DImode' on 64-bit machines. On some machines - you must define this to be one of the partial integer modes, such as - `PSImode'. - - The width of `Pmode' must be at least as large as the value of - `POINTER_SIZE'. If it is not equal, you must define the macro - `POINTERS_EXTEND_UNSIGNED' to specify how pointers are extended to `Pmode'. */ -#define Pmode SImode - -/* An alias for the machine mode used for memory references to functions being - called, in `call' RTL expressions. On most machines this should be - `QImode'. */ -#define FUNCTION_MODE QImode - -/* A C expression for the maximum number of instructions above which the - function DECL should not be inlined. DECL is a `FUNCTION_DECL' node. - - The default definition of this macro is 64 plus 8 times the number of - arguments that the function accepts. Some people think a larger threshold - should be used on RISC machines. */ -/* #define INTEGRATE_THRESHOLD(DECL) */ - -/* Define this if the preprocessor should ignore `#sccs' directives and print - no error message. - - Defined in svr4.h. */ -/* #define SCCS_DIRECTIVE */ - -/* Define this macro if the system header files support C++ as well as C. This - macro inhibits the usual method of using system header files in C++, which - is to pretend that the file's contents are enclosed in `extern "C" {...}'. */ -/* #define NO_IMPLICIT_EXTERN_C */ - -/* Define this macro if you want to implement any pragmas. If defined, it - should be a C expression to be executed when #pragma is seen. The - argument GETC is a function which will return the next character in the - input stream, or EOF if no characters are left. The argument UNGETC is - a function which will push a character back into the input stream. The - argument NAME is the word following #pragma in the input stream. The input - stream pointer will be pointing just beyond the end of this word. The - expression should return true if it handled the pragma, false otherwise. - The input stream should be left undistrubed if false is returned, otherwise - it should be pointing at the next character after the end of the pragma. - Any characters left between the end of the pragma and the end of the line will - be ignored. - - It is generally a bad idea to implement new uses of `#pragma'. The only - reason to define this macro is for compatibility with other compilers that - do support `#pragma' for the sake of any user programs which already use it. */ -/* #define HANDLE_PRAGMA(GETC, UNGETC, NAME) handle_pragma (GETC, UNGETC, NAME) */ - -/* Define this macro to handle System V style pragmas: #pragma pack and - #pragma weak. Note, #pragma weak will only be supported if SUPPORT_WEAK is - defined. - - Defined in svr4.h. */ -#define HANDLE_SYSV_PRAGMA - -/* Define this macro to control use of the character `$' in identifier names. - The value should be 0, 1, or 2. 0 means `$' is not allowed by default; 1 - means it is allowed by default if `-traditional' is used; 2 means it is - allowed by default provided `-ansi' is not used. 1 is the default; there is - no need to define this macro in that case. */ -/* #define DOLLARS_IN_IDENTIFIERS */ - -/* Define this macro if the assembler does not accept the character `$' in - label names. By default constructors and destructors in G++ have `$' in the - identifiers. If this macro is defined, `.' is used instead. - - Defined in svr4.h. */ -/* #define NO_DOLLAR_IN_LABEL */ - -/* Define this macro if the assembler does not accept the character `.' in - label names. By default constructors and destructors in G++ have names that - use `.'. If this macro is defined, these names are rewritten to avoid `.'. */ -/* #define NO_DOT_IN_LABEL */ - -/* Define this macro if the target system expects every program's `main' - function to return a standard "success" value by default (if no other value - is explicitly returned). - - The definition should be a C statement (sans semicolon) to generate the - appropriate rtl instructions. It is used only when compiling the end of - `main'. */ -/* #define DEFAULT_MAIN_RETURN */ - -/* Define this if the target system supports the function `atexit' from the - ANSI C standard. If this is not defined, and `INIT_SECTION_ASM_OP' is not - defined, a default `exit' function will be provided to support C++. - - Defined by svr4.h */ -/* #define HAVE_ATEXIT */ - -/* Define this if your `exit' function needs to do something besides calling an - external function `_cleanup' before terminating with `_exit'. The - `EXIT_BODY' macro is only needed if netiher `HAVE_ATEXIT' nor - `INIT_SECTION_ASM_OP' are defined. */ -/* #define EXIT_BODY */ - -/* Define this macro as a C expression that is nonzero if it is safe for the - delay slot scheduler to place instructions in the delay slot of INSN, even - if they appear to use a resource set or clobbered in INSN. INSN is always a - `jump_insn' or an `insn'; GNU CC knows that every `call_insn' has this - behavior. On machines where some `insn' or `jump_insn' is really a function - call and hence has this behavior, you should define this macro. - - You need not define this macro if it would always return zero. */ -/* #define INSN_SETS_ARE_DELAYED(INSN) */ - -/* Define this macro as a C expression that is nonzero if it is safe for the - delay slot scheduler to place instructions in the delay slot of INSN, even - if they appear to set or clobber a resource referenced in INSN. INSN is - always a `jump_insn' or an `insn'. On machines where some `insn' or - `jump_insn' is really a function call and its operands are registers whose - use is actually in the subroutine it calls, you should define this macro. - Doing so allows the delay slot scheduler to move instructions which copy - arguments into the argument registers into the delay slot of INSN. - - You need not define this macro if it would always return zero. */ -/* #define INSN_REFERENCES_ARE_DELAYED(INSN) */ - -/* #define MACHINE_DEPENDENT_REORG(INSN) fr30_reorg (INSN) */ - -/* 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 */ - -/* A C expression for the maximum number of instructions to execute via - conditional execution instructions instead of a branch. A value of - BRANCH_COST+1 is the default if the machine does not use - cc0, and 1 if it does use cc0. */ -/* #define MAX_CONDITIONAL_EXECUTE */ - -/* Indicate how many instructions can be issued at the same time. */ -/* #define ISSUE_RATE */ - -/* If cross-compiling, don't require stdio.h etc to build libgcc.a. */ -#if defined CROSS_COMPILE && ! defined inhibit_libc -#define inhibit_libc -#endif - -/*}}}*/ -/*{{{ Exported variables */ - -/* 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 * fr30_compare_op0; -extern struct rtx_def * fr30_compare_op1; - -/*}}}*/ -/*{{{ PERDICATE_CODES */ - -#define PREDICATE_CODES \ - { "stack_add_operand", { CONST_INT }}, \ - { "high_register_operand", { REG }}, \ - { "low_register_operand", { REG }}, \ - { "call_operand", { REG, MEM }}, \ - { "fp_displacement_operand", { CONST_INT }}, \ - { "sp_displacement_operand", { CONST_INT }}, \ - { "add_immediate_operand", { REG, CONST_INT }}, - -/*}}}*/ -/*{{{ Functions defined in fr30.c */ - -extern void fr30_expand_prologue PROTO ((void)); -extern void fr30_expand_epilogue PROTO ((void)); -extern unsigned int fr30_compute_frame_size PROTO ((int, int)); -extern int stack_add_operand PROTO ((Rtx, int)); -extern int add_immediate_operand PROTO ((Rtx, int)); -extern int high_register_operand PROTO ((Rtx, int)); -extern int low_register_operand PROTO ((Rtx, int)); -extern int call_operand PROTO ((Rtx, int)); -extern int fp_displacement_operand PROTO ((Rtx, int)); -extern int sp_displacement_operand PROTO ((Rtx, int)); -extern int fr30_check_multiple_regs PROTO ((Rtx *, int, int)); - -/*}}}*/ - -/* Local Variables: */ -/* folded-file: t */ -/* End: */ - -/* END CYGNUS LOCAL -- nickc/fr30 */ diff --git a/gcc/config/fr30/fr30.md b/gcc/config/fr30/fr30.md deleted file mode 100755 index 6970c16..0000000 --- a/gcc/config/fr30/fr30.md +++ /dev/null @@ -1,1404 +0,0 @@ -;; CYGNUS LOCAL -- nickc/fr30 - -;;{{{ Comment - -;; FR30 machine description. -;; Copyright (C) 1998, 1999 Free Software Foundation, Inc. -;; Contributed by Cygnus Solutions. - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;;}}} -;;{{{ Attributes - -(define_attr "length" "" (const_int 2)) - -;; Used to distinguish between small memory model targets and big mode targets. - -(define_attr "size" "small,big" - (const (if_then_else (symbol_ref "TARGET_SMALL_MODEL") - (const_string "small") - (const_string "big")))) - - -;; Define an attribute to be used by the delay slot code. -;; An instruction by default is considered to be 'delyabable' -;; that is, it can be placed into a delay slot, but it is not -;; itself an delyaed branch type instruction. An instruction -;; whoes type is 'delayed' is one which has a delay slot, and -;; an instruction whoes delay_type is 'other' is one which does -;; not have a delay slot, nor can it be placed into a delay slot. - -(define_attr "delay_type" "delayable,delayed,other" (const_string "delayable")) - -;;}}} -;;{{{ Delay Slot Specifications - -(define_delay (eq_attr "delay_type" "delayed") - [(and (eq_attr "delay_type" "delayable") - (eq_attr "length" "2")) - (nil) - (nil)] -) - -;;}}} -;;{{{ Moves - -;;{{{ Comment - -;; Wrap moves in define_expand to prevent memory->memory moves from being -;; generated at the RTL level, which generates better code for most machines -;; which can't do mem->mem moves. - -;; If operand 0 is a `subreg' with mode M of a register whose own mode is wider -;; than M, the effect of this instruction is to store the specified value in -;; the part of the register that corresponds to mode M. The effect on the rest -;; of the register is undefined. - -;; This class of patterns is special in several ways. First of all, each of -;; these names *must* be defined, because there is no other way to copy a datum -;; from one place to another. - -;; Second, these patterns are not used solely in the RTL generation pass. Even -;; the reload pass can generate move insns to copy values from stack slots into -;; temporary registers. When it does so, one of the operands is a hard -;; register and the other is an operand that can need to be reloaded into a -;; register. - -;; Therefore, when given such a pair of operands, the pattern must -;; generate RTL which needs no reloading and needs no temporary -;; registers--no registers other than the operands. For example, if -;; you support the pattern with a `define_expand', then in such a -;; case the `define_expand' mustn't call `force_reg' or any other such -;; function which might generate new pseudo registers. - -;; This requirement exists even for subword modes on a RISC machine -;; where fetching those modes from memory normally requires several -;; insns and some temporary registers. Look in `spur.md' to see how -;; the requirement can be satisfied. - -;; During reload a memory reference with an invalid address may be passed as an -;; operand. Such an address will be replaced with a valid address later in the -;; reload pass. In this case, nothing may be done with the address except to -;; use it as it stands. If it is copied, it will not be replaced with a valid -;; address. No attempt should be made to make such an address into a valid -;; address and no routine (such as `change_address') that will do so may be -;; called. Note that `general_operand' will fail when applied to such an -;; address. -;; -;; The global variable `reload_in_progress' (which must be explicitly declared -;; if required) can be used to determine whether such special handling is -;; required. -;; -;; The variety of operands that have reloads depends on the rest of -;; the machine description, but typically on a RISC machine these can -;; only be pseudo registers that did not get hard registers, while on -;; other machines explicit memory references will get optional -;; reloads. -;; -;; If a scratch register is required to move an object to or from memory, it -;; can be allocated using `gen_reg_rtx' prior to reload. But this is -;; impossible during and after reload. If there are cases needing scratch -;; registers after reload, you must define `SECONDARY_INPUT_RELOAD_CLASS' and -;; perhaps also `SECONDARY_OUTPUT_RELOAD_CLASS' to detect them, and provide -;; patterns `reload_inM' or `reload_outM' to handle them. - -;; The constraints on a `moveM' must permit moving any hard register to any -;; other hard register provided that `HARD_REGNO_MODE_OK' permits mode M in -;; both registers and `REGISTER_MOVE_COST' applied to their classes returns a -;; value of 2. - -;; It is obligatory to support floating point `moveM' instructions -;; into and out of any registers that can hold fixed point values, -;; because unions and structures (which have modes `SImode' or -;; `DImode') can be in those registers and they may have floating -;; point members. - -;; There may also be a need to support fixed point `moveM' instructions in and -;; out of floating point registers. Unfortunately, I have forgotten why this -;; was so, and I don't know whether it is still true. If `HARD_REGNO_MODE_OK' -;; rejects fixed point values in floating point registers, then the constraints -;; of the fixed point `moveM' instructions must be designed to avoid ever -;; trying to reload into a floating point register. - -;;}}} -;;{{{ Push and Pop - -;; Push a register onto the stack -(define_insn "movsi_push" - [(set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 0 "register_operand" "a"))] - "" - "st %0, @-r15" -) - -;; Pop a register off the stack -(define_insn "movsi_pop" - [(set:SI (match_operand:SI 0 "register_operand" "a") - (mem:SI (post_inc:SI (reg:SI 15))))] - "" - "ld @r15+, %0" -) - -;;}}} -;;{{{ 1 Byte Moves - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress - && !reload_completed - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM - || immediate_operand (operands[1], QImode))) - operands[1] = copy_to_mode_reg (QImode, operands[1]); -}") - -(define_insn "movqi_unsigned_register_load" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] - "" - "ldub %1, %0" -) - -(define_expand "movqi_signed_register_load" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))] - "" - " - emit_insn (gen_movqi_unsigned_register_load (operands[0], operands[1])); - emit_insn (gen_extendqisi2 (operands[0], operands[0])); - DONE; - " -) - -(define_insn "*movqi_internal" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r,red,m,r") - (match_operand:QI 1 "general_operand" "i,red,r,rm"))] - "" - "@ - ldi:8\\t#%A1, %0 - mov \\t%1, %0 - stb \\t%1, %0 - ldub \\t%1, %0" -) - -;;}}} -;;{{{ 2 Byte Moves - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress - && !reload_completed - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM - || immediate_operand (operands[1], HImode))) - operands[1] = copy_to_mode_reg (HImode, operands[1]); -}") - -(define_insn "movhi_unsigned_register_load" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] - "" - "lduh %1, %0" -) - -(define_expand "movhi_signed_register_load" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:HI 1 "memory_operand" "")))] - "" - " - emit_insn (gen_movhi_unsigned_register_load (operands[0], operands[1])); - emit_insn (gen_extendhisi2 (operands[0], operands[0])); - DONE; - " -) - -(define_insn "*movhi_internal" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,red,m,r") - (match_operand:HI 1 "general_operand" "L,M,n,red,r,rm"))] - "" - "@ - ldi:8 \\t#%1, %0 - ldi:20\\t#%1, %0 - ldi:32\\t#%1, %0 - mov \\t%1, %0 - sth \\t%1, %0 - lduh \\t%1, %0" - [(set_attr "length" "*,4,6,*,*,*")] -) - -;;}}} -;;{{{ 4 Byte Moves - -;; If the destination is a MEM and the source is a -;; MEM or an CONST_INT move the source into a register. -(define_expand "movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - "{ - if (!reload_in_progress - && !reload_completed - && GET_CODE(operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM - || immediate_operand (operands[1], SImode))) - operands[1] = copy_to_mode_reg (SImode, operands[1]); - }" -) - -;; We can do some clever tricks when loading certain immediate -;; values. We implement these tricks as define_splits, rather -;; than putting the code into the define_expand "movsi" above, -;; because if we put them there, they will be evaluated at RTL -;; generation time and then the combiner pass will come along -;; and replace the multiple insns that have been generated with -;; the original, slower, load insns. (The combiner pass only -;; cares about reducing the number of instructions, it does not -;; care about instruction lengths or speeds). Splits are -;; evaluated after the combine pass and before the scheduling -;; passes, so that they are the perfect place to put this -;; intelligence. -;; -;; XXX we probably ought to implement these for QI and HI mode -;; loads as well. - -;; If we are loading a small negative constant we can save space -;; and time by loading the positive value and then sign extending it. -(define_split - [(set (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "immediate_operand" "i"))] - "INTVAL (operands[1]) <= -1 && INTVAL (operands[1]) >= -128" - [(set:SI (match_dup 0) (match_dup 2)) - (set:SI (match_dup 0) (sign_extend:SI (subreg:QI (match_dup 0) 0)))] - "{ - operands[2] = GEN_INT (INTVAL (operands[1]) & 0xff); - }" -) - -;; If we are loading a large negative constant, one which does -;; not have any of its bottom 24 bit set, then we can save time -;; and space by loading the byte value and shifting it into place. -(define_split - [(set (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "immediate_operand" "i"))] - "(INTVAL (operands[1]) < 0) && (INTVAL (operands[1]) & 0x00ffffff == 0)" - [(set:SI (match_dup 0) (match_dup 2)) - (parallel [(set:SI (match_dup 0) (ashift:SI (match_dup 0) (const_int 24))) - (clobber (reg:CC 16))])] - "{ - HOST_WIDE_INT val = INTVAL (operands[1]); - operands[2] = GEN_INT (val >> 24); - }" -) - -;; If we are loading a large positive constant, one which has bits -;; in the top byte set, but whoes set bits all lie within an 8 bit -;; range, then we can save time and space by loading the byte value -;; and shifting it into place. -(define_split - [(set (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "immediate_operand" "i"))] - "(INTVAL (operands[1]) > 0x00ffffff) - && ((INTVAL (operands[1]) >> exact_log2 (INTVAL (operands[1]) & (- INTVAL (operands[1])))) < 0x100)" - [(set:SI (match_dup 0) (match_dup 2)) - (parallel [(set:SI (match_dup 0) (ashift:SI (match_dup 0) (match_dup 3))) - (clobber (reg:CC 16))])] - "{ - HOST_WIDE_INT val = INTVAL (operands[1]); - int shift = exact_log2 (val & ( - val)); - operands[2] = GEN_INT (val >> shift); - operands[3] = GEN_INT (shift); - }" -) - -;; When TARGET_SMALL_MODEL is defined we assume that all symbolic -;; values are addresses which will fit in 20 bits. - -(define_insn "movsi_internal" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,red,m,r") - (match_operand:SI 1 "general_operand" "L,M,n,i,rde,r,rm"))] - "" - "* - { - switch (which_alternative) - { - case 0: return \"ldi:8 \\t#%1, %0\"; - case 1: return \"ldi:20\\t#%1, %0\"; - case 2: return \"ldi:32\\t#%1, %0\"; - case 3: if (TARGET_SMALL_MODEL) - return \"ldi:20\\t%1, %0\"; - else - return \"ldi:32\\t%1, %0\"; - case 4: return \"mov \\t%1, %0\"; - case 5: return \"st \\t%1, %0\"; - case 6: return \"ld \\t%1, %0\"; - default: abort (); - } - }" - [(set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 4) - (eq_attr "alternative" "2") (const_int 6) - (eq_attr "alternative" "3") - (if_then_else (eq_attr "size" "small") - (const_int 4) - (const_int 6))] - (const_int 2)))] -) - -;;}}} -;;{{{ Load & Store Multiple Registers - -;; The load multiple and store multiple patterns are implemented -;; as peepholes because the only time they are expected to occur -;; is during function prologues and epilogues. - -(define_peephole - [(set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 0 "high_register_operand" "h")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 1 "high_register_operand" "h")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 2 "high_register_operand" "h")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 3 "high_register_operand" "h"))] - "fr30_check_multiple_regs (operands, 4, 1)" - "stm1 (%0, %1, %2, %3)" - [(set_attr "delay_type" "other")] -) - -(define_peephole - [(set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 0 "high_register_operand" "h")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 1 "high_register_operand" "h")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 2 "high_register_operand" "h"))] - "fr30_check_multiple_regs (operands, 3, 1)" - "stm1 (%0, %1, %2)" - [(set_attr "delay_type" "other")] -) - -(define_peephole - [(set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 0 "high_register_operand" "h")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 1 "high_register_operand" "h"))] - "fr30_check_multiple_regs (operands, 2, 1)" - "stm1 (%0, %1)" - [(set_attr "delay_type" "other")] -) - -(define_peephole - [(set:SI (match_operand:SI 0 "high_register_operand" "h") - (mem:SI (post_inc:SI (reg:SI 15)))) - (set:SI (match_operand:SI 1 "high_register_operand" "h") - (mem:SI (post_inc:SI (reg:SI 15)))) - (set:SI (match_operand:SI 2 "high_register_operand" "h") - (mem:SI (post_inc:SI (reg:SI 15)))) - (set:SI (match_operand:SI 3 "high_register_operand" "h") - (mem:SI (post_inc:SI (reg:SI 15))))] - "fr30_check_multiple_regs (operands, 4, 0)" - "ldm1 (%0, %1, %2, %3)" - [(set_attr "delay_type" "other")] -) - -(define_peephole - [(set:SI (match_operand:SI 0 "high_register_operand" "h") - (mem:SI (post_inc:SI (reg:SI 15)))) - (set:SI (match_operand:SI 1 "high_register_operand" "h") - (mem:SI (post_inc:SI (reg:SI 15)))) - (set:SI (match_operand:SI 2 "high_register_operand" "h") - (mem:SI (post_inc:SI (reg:SI 15))))] - "fr30_check_multiple_regs (operands, 3, 0)" - "ldm1 (%0, %1, %2)" - [(set_attr "delay_type" "other")] -) - -(define_peephole - [(set:SI (match_operand:SI 0 "high_register_operand" "h") - (mem:SI (post_inc:SI (reg:SI 15)))) - (set:SI (match_operand:SI 1 "high_register_operand" "h") - (mem:SI (post_inc:SI (reg:SI 15))))] - "fr30_check_multiple_regs (operands, 2, 0)" - "ldm1 (%0, %1)" - [(set_attr "delay_type" "other")] -) - -(define_peephole - [(set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 0 "low_register_operand" "l")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 1 "low_register_operand" "l")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 2 "low_register_operand" "l")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 3 "low_register_operand" "l"))] - "fr30_check_multiple_regs (operands, 4, 1)" - "stm0 (%0, %1, %2, %3)" - [(set_attr "delay_type" "other")] -) - -(define_peephole - [(set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 0 "low_register_operand" "l")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 1 "low_register_operand" "l")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 2 "low_register_operand" "l"))] - "fr30_check_multiple_regs (operands, 3, 1)" - "stm0 (%0, %1, %2)" - [(set_attr "delay_type" "other")] -) - -(define_peephole - [(set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 0 "low_register_operand" "l")) - (set:SI (mem:SI (pre_dec:SI (reg:SI 15))) - (match_operand:SI 1 "low_register_operand" "l"))] - "fr30_check_multiple_regs (operands, 2, 1)" - "stm0 (%0, %1)" - [(set_attr "delay_type" "other")] -) - -;;}}} -;;{{{ Floating Point Moves - -;; Note - Patterns for SF mode moves are compulsory, but -;; patterns for DF are optional, as GCC can synthesise them. - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - "{ - if (!reload_in_progress && !reload_completed - && memory_operand (operands[0], SFmode) - && memory_operand (operands[1], SFmode)) - operands[1] = copy_to_mode_reg (SFmode, operands[1]); - }" -) - -(define_insn "*movsf_internal" - [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,red,m,r") - (match_operand:SF 1 "general_operand" "Fn,i,rde,r,rm"))] - "" - "* - { - switch (which_alternative) - { - case 0: return \"ldi:32\\t%1, %0\"; - case 1: if (TARGET_SMALL_MODEL) - return \"ldi:20\\t%1, %0\"; - else - return \"ldi:32\\t%1, %0\"; - case 2: return \"mov \\t%1, %0\"; - case 3: return \"st \\t%1, %0\"; - case 4: return \"ld \\t%1, %0\"; - default: abort (); - } - }" - [(set (attr "length") (cond [(eq_attr "alternative" "0") (const_int 6) - (eq_attr "alternative" "1") - (if_then_else (eq_attr "size" "small") - (const_int 4) - (const_int 6))] - (const_int 2)))] -) - -(define_insn "*movsf_constant_store" - [(set (match_operand:SF 0 "memory_operand" "m") - (match_operand:SF 1 "immediate_operand" "F"))] - "" - "* - { - char * ldi_instr; - char * tmp_reg; - static char buffer[100]; - REAL_VALUE_TYPE d; - - REAL_VALUE_FROM_CONST_DOUBLE (d, operands[1]); - - if (REAL_VALUES_EQUAL (d, dconst0)) - ldi_instr = \"ldi:8\"; - else - ldi_instr = \"ldi:32\"; - - tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER]; - - sprintf (buffer, \"%s\\t#%%1, %s\\t;\\n\\tst\\t%s, %%0\\t; Created by movsf_constant_store\", - ldi_instr, tmp_reg, tmp_reg); - - return buffer; - }" - [(set_attr "length" "8")] -) - -;;}}} - -;;}}} -;;{{{ Conversions - -;; Signed conversions from a smaller integer to a larger integer - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:QI 1 "register_operand" "0")))] - "" - "extsb %0" -) - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:HI 1 "register_operand" "0")))] - "" - "extsh %0" -) - -;; Unsigned conversions from a smaller integer to a larger integer - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))] - "" - "extub %0" -) - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))] - "" - "extuh %0" -) - -;;}}} -;;{{{ Arithmetic - -;;{{{ Addition - -;; This is a special pattern just for adjusting the stack size. -(define_insn "add_to_stack" - [(set (reg:SI 15) - (plus:SI (reg:SI 15) - (match_operand:SI 0 "stack_add_operand" "i")))] - "" - "addsp %0" -) - -;; We need some trickery to be able to handle the addition of -;; large (ie outside +/- 16) constants. We need to be able to -;; handle this because reload assumes that it can generate add -;; instructions with arbitary sized constants. -(define_expand "addsi3" - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - "{ - if ( GET_CODE (operands[2]) == REG - || GET_CODE (operands[2]) == SUBREG) - emit_insn (gen_addsi_regs (operands[0], operands[1], operands[2])); - else if (GET_CODE (operands[2]) != CONST_INT) - emit_insn (gen_addsi_big_int (operands[0], operands[1], operands[2])); - else if ((INTVAL (operands[2]) >= -16) && (INTVAL (operands[2]) <= 15)) - emit_insn (gen_addsi_small_int (operands[0], operands[1], operands[2])); - else - emit_insn (gen_addsi_big_int (operands[0], operands[1], operands[2])); - DONE; - }" -) - -(define_insn "addsi_regs" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "register_operand" "r")))] - "" - "addn %2, %0" -) - -(define_insn "addsi_small_int" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "add_immediate_operand" "I,J")))] - "" - "@ - addn %2, %0 - addn2 %2, %0" -) - -(define_expand "addsi_big_int" - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "immediate_operand" "")))] - "" - "{ - /* Cope with the possibility that ops 0 and 1 are the same register. */ - if (REGNO (operands[0]) == REGNO (operands[1])) - { - if (reload_in_progress || reload_completed) - { - rtx reg = gen_rtx_REG (SImode, 0/*COMPILER_SCRATCH_REGISTER*/); - - emit_insn (gen_movsi (reg, operands[2])); - emit_insn (gen_addsi_regs (operands[0], operands[0], reg)); - } - else - { - operands[2] = force_reg (SImode, operands[2]); - emit_insn (gen_addsi_regs (operands[0], operands[0], operands[2])); - } - } - else - { - emit_insn (gen_movsi (operands[0], operands[2])); - emit_insn (gen_addsi_regs (operands[0], operands[0], operands[1])); - } - DONE; - }" -) - -(define_insn "*addsi_for_reload" - [(set (match_operand:SI 0 "register_operand" "=&r,r,r") - (plus:SI (match_operand:SI 1 "register_operand" "r,r,r") - (match_operand:SI 2 "immediate_operand" "L,M,n")))] - "reload_in_progress || reload_completed" - "@ - ldi:8\\t#%2, %0 \\n\\taddn\\t%1, %0 - ldi:20\\t#%2, %0 \\n\\taddn\\t%1, %0 - ldi:32\\t#%2, %0 \\n\\taddn\\t%1, %0" - [(set_attr "length" "4,6,8")] -) - -;;}}} -;;{{{ Subtraction - -(define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "register_operand" "r")))] - "" - "subn %2, %0" -) - -;;}}} -;;{{{ Multiplication - -;; Signed multiplication producing 64 bit results from 32 bit inputs -(define_insn "mulsidi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%r")) - (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))) - (clobber (reg:CC 16))] - "" - "mul %2, %1\\n\\tmov\\tmdh, %0\\n\\tmov\\tmdl, %p0" - [(set_attr "length" "6")] -) - -;; Unsigned multiplication producing 64 bit results from 32 bit inputs -(define_insn "umulsidi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%r")) - (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))) - (clobber (reg:CC 16))] - "" - "mulu %2, %1\\n\\tmov\\tmdh, %0\\n\\tmov\\tmdl, %p0" - [(set_attr "length" "6")] -) - -;; Signed multiplication producing 32 bit result from 16 bit inputs -(define_insn "mulhisi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r")) - (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))) - (clobber (reg:CC 16))] - "" - "mulh %2, %1\\n\\tmov\\tmdl, %0" - [(set_attr "length" "4")] -) - -;; Unsigned multiplication producing 32 bit result from 16 bit inputs -(define_insn "umulhisi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%r")) - (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))) - (clobber (reg:CC 16))] - "" - "muluh %2, %1\\n\\tmov\\tmdl, %0" - [(set_attr "length" "4")] -) - -;; Signed multiplication producing 32 bit result from 32 bit inputs -(define_insn "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (mult:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "register_operand" "r"))) - (clobber (reg:CC 16))] - "" - "mul %2, %1\\n\\tmov\\tmdl, %0" - [(set_attr "length" "4")] -) - -;;}}} -;;{{{ Negation - -(define_expand "negsi2" - [(set (match_operand:SI 0 "register_operand" "") - (neg:SI (match_operand:SI 1 "register_operand" "")))] - "" - "{ - if (REGNO (operands[0]) == REGNO (operands[1])) - { - if (reload_in_progress || reload_completed) - { - rtx reg = gen_rtx_REG (SImode, 0/*COMPILER_SCRATCH_REGISTER*/); - - emit_insn (gen_movsi (reg, GEN_INT (0))); - emit_insn (gen_subsi3 (reg, reg, operands[0])); - emit_insn (gen_movsi (operands[0], reg)); - } - else - { - rtx reg = gen_reg_rtx (SImode); - - emit_insn (gen_movsi (reg, GEN_INT (0))); - emit_insn (gen_subsi3 (reg, reg, operands[0])); - emit_insn (gen_movsi (operands[0], reg)); - } - } - else - { - emit_insn (gen_movsi_internal (operands[0], GEN_INT (0))); - emit_insn (gen_subsi3 (operands[0], operands[0], operands[1])); - } - DONE; - }" -) - -;;}}} - -;;}}} -;;{{{ Shifts - -;; Arithmetic Shift Left -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (ashift:SI (match_operand:SI 1 "register_operand" "0,0,0") - (match_operand:SI 2 "nonmemory_operand" "r,I,K"))) - (clobber (reg:CC 16))] - "" - "@ - lsl %2, %0 - lsl %2, %0 - lsl2 %x2, %0" -) - -;; Arithmetic Shift Right -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0") - (match_operand:SI 2 "nonmemory_operand" "r,I,K"))) - (clobber (reg:CC 16))] - "" - "@ - asr %2, %0 - asr %2, %0 - asr2 %x2, %0" -) - -;; Logical Shift Right -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0") - (match_operand:SI 2 "nonmemory_operand" "r,I,K"))) - (clobber (reg:CC 16))] - "" - "@ - lsr %2, %0 - lsr %2, %0 - lsr2 %x2, %0" -) - -;;}}} -;;{{{ Logical Operations - -;; Logical AND, 32 bit integers -(define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "register_operand" "0"))) - (clobber (reg:CC 16))] - "" - "and %1, %0" -) - -;; Inclusive OR, 32 bit integers -(define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "register_operand" "0"))) - (clobber (reg:CC 16))] - "" - "or %1, %0" -) - -;; Exclusive OR, 32 bit integers -(define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (xor:SI (match_operand:SI 1 "register_operand" "%r") - (match_operand:SI 2 "register_operand" "0"))) - (clobber (reg:CC 16))] - "" - "eor %1, %0" -) - -;; One's complement, 32 bit integers -(define_expand "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "") - (not:SI (match_operand:SI 1 "register_operand" "")))] - "" - "{ - if (REGNO (operands[0]) == REGNO (operands[1])) - { - if (reload_in_progress || reload_completed) - { - rtx reg = gen_rtx_REG (SImode, 0/*COMPILER_SCRATCH_REGISTER*/); - - emit_insn (gen_movsi (reg, GEN_INT (-1))); - emit_insn (gen_xorsi3 (operands[0], operands[0], reg)); - } - else - { - rtx reg = gen_reg_rtx (SImode); - - emit_insn (gen_movsi (reg, GEN_INT (-1))); - emit_insn (gen_xorsi3 (operands[0], operands[0], reg)); - } - } - else - { - emit_insn (gen_movsi_internal (operands[0], GEN_INT (-1))); - emit_insn (gen_xorsi3 (operands[0], operands[1], operands[0])); - } - DONE; - }" -) - -;;}}} -;;{{{ Comparisons - -;; Note, we store the operands in the comparison insns, and use them later -;; when generating the branch or scc operation. - -;; First the routines called by the machine independent part of the compiler -(define_expand "cmpsi" - [(set (reg:CC 16) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "nonmemory_operand" "")))] - "" - "{ - fr30_compare_op0 = operands[0]; - fr30_compare_op1 = operands[1]; - DONE; - }" -) - -;; Now, the actual comparisons, generated by the branch and/or scc operations - -(define_insn "*cmpsi_internal" - [(set (reg:CC 16) - (compare:CC (match_operand:SI 0 "register_operand" "r,r,r") - (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] - "" - "@ - cmp %1, %0 - cmp %1, %0 - cmp2 %1, %0" -) - -;;}}} -;;{{{ Branches - -;; Define_expands called by the machine independent part of the compiler -;; to allocate a new comparison register - -(define_expand "beq" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (eq:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bne" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (ne:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "blt" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (lt:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "ble" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (le:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bgt" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (gt:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bge" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (ge:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bltu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (ltu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bleu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (leu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bgtu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (gtu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -(define_expand "bgeu" - [(set (reg:CC 16) - (compare:CC (match_dup 1) - (match_dup 2))) - (set (pc) - (if_then_else (geu:CC (reg:CC 16) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "{ - operands[1] = fr30_compare_op0; - operands[2] = fr30_compare_op1; - }" -) - -;; Actual branches. We must allow for the (label_ref) and the (pc) to be -;; swapped. If they are swapped, it reverses the sense of the branch. - -;; This pattern matches the (branch-if-true) branches generated above. -;; It generates two different instruction sequences depending upon how -;; far away the destination is. - -;; The calculation for the instruction length is derived as follows: -;; The branch instruction has a 9 bit signed displacement so we have -;; this inequality for the displacement: -;; -;; -256 <= pc < 256 -;; or -;; -256 + 256 <= pc + 256 < 256 + 256 -;; ie -;; 0 <= pc + 256 < 512 -;; -;; if we consider the displacement as an unsigned value, then negative -;; displacements become very large positive displacements, and the -;; inequality becomes: -;; -;; pc + 256 < 512 -;; -;; In order to allow for the fact that the real branch instruction works -;; from pc + 2, we increase the offset to 258. -;; -;; Note - we do not have to worry about whether the branch is delayed or -;; not, as branch shortening happens after delay slot reorganisation. - -(define_insn "*branch_true" - [(set (pc) - (if_then_else (match_operator:CC 0 "comparison_operator" - [(reg:CC 16) - (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "* - { - if (get_attr_length (insn) == 2) - return \"b%b0%#\\t%l1\"; - else - { - static char buffer [100]; - char * tmp_reg; - char * ldi_insn; - - tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER]; - - ldi_insn = TARGET_SMALL_MODEL ? \"ldi:20\" : \"ldi:32\"; - - /* The code produced here is, for say the EQ case: - - Bne 1f - LDI