From 61f78c36f4b8d5cbb9fc01b5d89d0e91e4acb510 Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Thu, 12 Sep 2002 14:00:21 +0000 Subject: This commit was manufactured by cvs2svn to create tag 'itanium-sched-branchpoint'. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/tags/itanium-sched-branchpoint@57065 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/config/frv/cmovd.c | 47 - gcc/config/frv/cmovh.c | 43 - gcc/config/frv/cmovw.c | 47 - gcc/config/frv/frv-abi.h | 181 - gcc/config/frv/frv-asm.h | 49 - gcc/config/frv/frv-modes.def | 30 - gcc/config/frv/frv-protos.h | 253 - gcc/config/frv/frv.c | 9776 -------------------- gcc/config/frv/frv.h | 3660 -------- gcc/config/frv/frv.md | 7441 --------------- gcc/config/frv/frvbegin.c | 150 - gcc/config/frv/frvend.c | 63 - gcc/config/frv/lib1funcs.asm | 275 - gcc/config/frv/modi.c | 4 - gcc/config/frv/t-frv | 93 - gcc/config/frv/uitod.c | 4 - gcc/config/frv/uitof.c | 4 - gcc/config/frv/ulltod.c | 4 - gcc/config/frv/ulltof.c | 4 - gcc/config/frv/umodi.c | 4 - gcc/config/frv/xm-frv.h | 38 - gcc/config/i386/scodbx.h | 84 - gcc/config/i386/xm-dgux.h | 4 - gcc/config/i386/xm-sun.h | 21 - gcc/config/i386/xm-sysv3.h | 3 - gcc/config/ip2k/crt0.S | 53 - gcc/config/ip2k/ip2k-protos.h | 99 - gcc/config/ip2k/ip2k.c | 6255 ------------- gcc/config/ip2k/ip2k.h | 2523 ----- gcc/config/ip2k/ip2k.md | 6902 -------------- gcc/config/ip2k/libgcc.S | 1532 --- gcc/config/ip2k/t-ip2k | 50 - .../g++.dg/expr/member-of-incomplete-type-1.C | 12 - gcc/testsuite/g++.dg/expr/pmf-1.C | 19 - gcc/testsuite/g++.dg/tls/diag-1.C | 30 - gcc/testsuite/g++.dg/tls/diag-2.C | 25 - gcc/testsuite/g++.dg/tls/init-1.C | 13 - gcc/testsuite/g++.dg/tls/init-2.C | 13 - gcc/testsuite/g++.dg/tls/tls.exp | 44 - gcc/testsuite/g++.dg/tls/trivial.C | 1 - gcc/testsuite/g++.old-deja/g++.robertl/eb42.C | 19 - gcc/testsuite/gcc.dg/cpp/trad/Wunused.c | 37 - gcc/testsuite/gcc.dg/cpp/trad/Wunused.h | 1 - gcc/testsuite/gcc.dg/cpp/trad/__STDC__.c | 7 - gcc/testsuite/gcc.dg/cpp/trad/argcount.c | 21 - gcc/testsuite/gcc.dg/cpp/trad/assembler.S | 25 - gcc/testsuite/gcc.dg/cpp/trad/assert1.c | 46 - gcc/testsuite/gcc.dg/cpp/trad/assert2.c | 23 - gcc/testsuite/gcc.dg/cpp/trad/assert3.c | 10 - gcc/testsuite/gcc.dg/cpp/trad/builtins.c | 52 - gcc/testsuite/gcc.dg/cpp/trad/builtins.h | 1 - gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C.c | 37 - gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C2.c | 15 - gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dD.c | 9 - gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dM.c | 9 - gcc/testsuite/gcc.dg/cpp/trad/comment-2.c | 11 - gcc/testsuite/gcc.dg/cpp/trad/comment.c | 5 - gcc/testsuite/gcc.dg/cpp/trad/define.c | 2 - gcc/testsuite/gcc.dg/cpp/trad/defined.c | 78 - gcc/testsuite/gcc.dg/cpp/trad/directive.c | 20 - gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c | 6 - gcc/testsuite/gcc.dg/cpp/trad/escaped-nl.c | 10 - gcc/testsuite/gcc.dg/cpp/trad/funlike-2.c | 23 - gcc/testsuite/gcc.dg/cpp/trad/funlike-3.c | 12 - gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c | 26 - gcc/testsuite/gcc.dg/cpp/trad/funlike.c | 25 - gcc/testsuite/gcc.dg/cpp/trad/hash.c | 14 - gcc/testsuite/gcc.dg/cpp/trad/include.c | 9 - gcc/testsuite/gcc.dg/cpp/trad/literals-1.c | 28 - gcc/testsuite/gcc.dg/cpp/trad/literals-2.c | 8 - gcc/testsuite/gcc.dg/cpp/trad/maccom1.c | 17 - gcc/testsuite/gcc.dg/cpp/trad/maccom2.c | 18 - gcc/testsuite/gcc.dg/cpp/trad/maccom3.c | 17 - gcc/testsuite/gcc.dg/cpp/trad/maccom4.c | 19 - gcc/testsuite/gcc.dg/cpp/trad/maccom6.c | 24 - gcc/testsuite/gcc.dg/cpp/trad/macroargs.c | 30 - gcc/testsuite/gcc.dg/cpp/trad/mi1.c | 36 - gcc/testsuite/gcc.dg/cpp/trad/mi1c.h | 12 - gcc/testsuite/gcc.dg/cpp/trad/mi1nd.h | 8 - gcc/testsuite/gcc.dg/cpp/trad/mi1ndp.h | 7 - gcc/testsuite/gcc.dg/cpp/trad/mi1x.h | 9 - gcc/testsuite/gcc.dg/cpp/trad/mi2.c | 12 - gcc/testsuite/gcc.dg/cpp/trad/mi2a.h | 5 - gcc/testsuite/gcc.dg/cpp/trad/mi2b.h | 6 - gcc/testsuite/gcc.dg/cpp/trad/mi2c.h | 15 - gcc/testsuite/gcc.dg/cpp/trad/mi3.c | 20 - gcc/testsuite/gcc.dg/cpp/trad/mi3.def | 10 - gcc/testsuite/gcc.dg/cpp/trad/mi3.h | 7 - gcc/testsuite/gcc.dg/cpp/trad/mi4.c | 10 - gcc/testsuite/gcc.dg/cpp/trad/mi5.c | 13 - gcc/testsuite/gcc.dg/cpp/trad/mi6.c | 59 - gcc/testsuite/gcc.dg/cpp/trad/mi6a.h | 5 - gcc/testsuite/gcc.dg/cpp/trad/mi6b.h | 5 - gcc/testsuite/gcc.dg/cpp/trad/mi6c.h | 5 - gcc/testsuite/gcc.dg/cpp/trad/mi6d.h | 5 - gcc/testsuite/gcc.dg/cpp/trad/mi6e.h | 5 - gcc/testsuite/gcc.dg/cpp/trad/mi7.c | 19 - gcc/testsuite/gcc.dg/cpp/trad/mi7a.h | 4 - gcc/testsuite/gcc.dg/cpp/trad/mi7b.h | 4 - gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c | 6 - gcc/testsuite/gcc.dg/cpp/trad/num-sign.c | 16 - gcc/testsuite/gcc.dg/cpp/trad/paste.c | 16 - gcc/testsuite/gcc.dg/cpp/trad/quote.c | 6 - gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c | 10 - gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c | 16 - gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c | 25 - gcc/testsuite/gcc.dg/cpp/trad/redef1.c | 36 - gcc/testsuite/gcc.dg/cpp/trad/redef2.c | 32 - gcc/testsuite/gcc.dg/cpp/trad/strify.c | 17 - gcc/testsuite/gcc.dg/cpp/trad/trad.exp | 43 - gcc/testsuite/gcc.dg/cpp/trad/uchar.c | 8 - gcc/testsuite/gcc.dg/tls/diag-1.c | 11 - gcc/testsuite/gcc.dg/tls/diag-2.c | 21 - gcc/testsuite/gcc.dg/tls/diag-3.c | 10 - gcc/testsuite/gcc.dg/tls/init-1.c | 4 - gcc/testsuite/gcc.dg/tls/opt-2.c | 53 - gcc/testsuite/gcc.dg/tls/section-1.c | 11 - gcc/testsuite/gcc.dg/tls/tls.exp | 45 - gcc/testsuite/gcc.dg/tls/trivial.c | 1 - gcc/testsuite/gcc.dg/weak/typeof-2.c | 29 - gcc/testsuite/gcc.dg/weak/weak-1.c | 50 - gcc/testsuite/gcc.dg/weak/weak-2.c | 46 - gcc/testsuite/gcc.dg/weak/weak-3.c | 71 - gcc/testsuite/gcc.dg/weak/weak-4.c | 104 - gcc/testsuite/gcc.dg/weak/weak-5.c | 107 - gcc/testsuite/gcc.dg/weak/weak-6.c | 6 - gcc/testsuite/gcc.dg/weak/weak-7.c | 6 - gcc/testsuite/gcc.dg/weak/weak-8.c | 7 - gcc/testsuite/gcc.dg/weak/weak-9.c | 20 - gcc/testsuite/gcc.dg/weak/weak.exp | 41 - gcc/testsuite/treelang/ChangeLog | 49 - gcc/testsuite/treelang/Makefile.in | 29 - gcc/testsuite/treelang/a01gcci01.c | 43 - gcc/testsuite/treelang/a01gcci01.tree | 60 - gcc/testsuite/treelang/a01gcco01runpgm | 8 - gcc/testsuite/treelang/treetests.exp | 307 - gcc/treelang/.cvsignore | 5 - gcc/treelang/ChangeLog | 164 - gcc/treelang/Make-lang.in | 308 - gcc/treelang/README | 19 - gcc/treelang/config-lang.in | 39 - gcc/treelang/lang-options.h | 29 - gcc/treelang/lang-specs.h | 63 - gcc/treelang/lex.l | 291 - gcc/treelang/parse.y | 1005 -- gcc/treelang/tree1.c | 319 - gcc/treelang/treelang.h | 152 - gcc/treelang/treelang.texi | 1317 --- gcc/treelang/treetree.c | 1299 --- gcc/treelang/treetree.h | 73 - 150 files changed, 47301 deletions(-) delete mode 100644 gcc/config/frv/cmovd.c delete mode 100644 gcc/config/frv/cmovh.c delete mode 100644 gcc/config/frv/cmovw.c delete mode 100644 gcc/config/frv/frv-abi.h delete mode 100644 gcc/config/frv/frv-asm.h delete mode 100644 gcc/config/frv/frv-modes.def delete mode 100644 gcc/config/frv/frv-protos.h delete mode 100644 gcc/config/frv/frv.c delete mode 100644 gcc/config/frv/frv.h delete mode 100644 gcc/config/frv/frv.md delete mode 100644 gcc/config/frv/frvbegin.c delete mode 100644 gcc/config/frv/frvend.c delete mode 100644 gcc/config/frv/lib1funcs.asm delete mode 100644 gcc/config/frv/modi.c delete mode 100644 gcc/config/frv/t-frv delete mode 100644 gcc/config/frv/uitod.c delete mode 100644 gcc/config/frv/uitof.c delete mode 100644 gcc/config/frv/ulltod.c delete mode 100644 gcc/config/frv/ulltof.c delete mode 100644 gcc/config/frv/umodi.c delete mode 100644 gcc/config/frv/xm-frv.h delete mode 100644 gcc/config/i386/scodbx.h delete mode 100644 gcc/config/i386/xm-dgux.h delete mode 100644 gcc/config/i386/xm-sun.h delete mode 100644 gcc/config/i386/xm-sysv3.h delete mode 100644 gcc/config/ip2k/crt0.S delete mode 100644 gcc/config/ip2k/ip2k-protos.h delete mode 100644 gcc/config/ip2k/ip2k.c delete mode 100644 gcc/config/ip2k/ip2k.h delete mode 100644 gcc/config/ip2k/ip2k.md delete mode 100644 gcc/config/ip2k/libgcc.S delete mode 100644 gcc/config/ip2k/t-ip2k delete mode 100644 gcc/testsuite/g++.dg/expr/member-of-incomplete-type-1.C delete mode 100644 gcc/testsuite/g++.dg/expr/pmf-1.C delete mode 100644 gcc/testsuite/g++.dg/tls/diag-1.C delete mode 100644 gcc/testsuite/g++.dg/tls/diag-2.C delete mode 100644 gcc/testsuite/g++.dg/tls/init-1.C delete mode 100644 gcc/testsuite/g++.dg/tls/init-2.C delete mode 100644 gcc/testsuite/g++.dg/tls/tls.exp delete mode 100644 gcc/testsuite/g++.dg/tls/trivial.C delete mode 100644 gcc/testsuite/g++.old-deja/g++.robertl/eb42.C delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/Wunused.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/Wunused.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/__STDC__.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/argcount.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/assembler.S delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/assert1.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/assert2.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/assert3.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/builtins.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/builtins.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C2.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dD.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dM.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/comment-2.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/comment.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/define.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/defined.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/directive.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/escaped-nl.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/funlike-2.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/funlike-3.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/funlike.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/hash.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/include.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/literals-1.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/literals-2.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/maccom1.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/maccom2.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/maccom3.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/maccom4.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/maccom6.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/macroargs.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi1.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi1c.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi1nd.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi1ndp.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi1x.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi2.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi2a.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi2b.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi2c.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi3.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi3.def delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi3.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi4.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi5.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi6.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi6a.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi6b.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi6c.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi6d.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi6e.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi7.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi7a.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/mi7b.h delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/num-sign.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/paste.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/quote.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/redef1.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/redef2.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/strify.c delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/trad.exp delete mode 100644 gcc/testsuite/gcc.dg/cpp/trad/uchar.c delete mode 100644 gcc/testsuite/gcc.dg/tls/diag-1.c delete mode 100644 gcc/testsuite/gcc.dg/tls/diag-2.c delete mode 100644 gcc/testsuite/gcc.dg/tls/diag-3.c delete mode 100644 gcc/testsuite/gcc.dg/tls/init-1.c delete mode 100644 gcc/testsuite/gcc.dg/tls/opt-2.c delete mode 100644 gcc/testsuite/gcc.dg/tls/section-1.c delete mode 100644 gcc/testsuite/gcc.dg/tls/tls.exp delete mode 100644 gcc/testsuite/gcc.dg/tls/trivial.c delete mode 100644 gcc/testsuite/gcc.dg/weak/typeof-2.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak-1.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak-2.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak-3.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak-4.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak-5.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak-6.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak-7.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak-8.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak-9.c delete mode 100644 gcc/testsuite/gcc.dg/weak/weak.exp delete mode 100644 gcc/testsuite/treelang/ChangeLog delete mode 100644 gcc/testsuite/treelang/Makefile.in delete mode 100644 gcc/testsuite/treelang/a01gcci01.c delete mode 100644 gcc/testsuite/treelang/a01gcci01.tree delete mode 100644 gcc/testsuite/treelang/a01gcco01runpgm delete mode 100644 gcc/testsuite/treelang/treetests.exp delete mode 100644 gcc/treelang/.cvsignore delete mode 100644 gcc/treelang/ChangeLog delete mode 100644 gcc/treelang/Make-lang.in delete mode 100644 gcc/treelang/README delete mode 100644 gcc/treelang/config-lang.in delete mode 100644 gcc/treelang/lang-options.h delete mode 100644 gcc/treelang/lang-specs.h delete mode 100644 gcc/treelang/lex.l delete mode 100644 gcc/treelang/parse.y delete mode 100644 gcc/treelang/tree1.c delete mode 100644 gcc/treelang/treelang.h delete mode 100644 gcc/treelang/treelang.texi delete mode 100644 gcc/treelang/treetree.c delete mode 100644 gcc/treelang/treetree.h (limited to 'gcc') diff --git a/gcc/config/frv/cmovd.c b/gcc/config/frv/cmovd.c deleted file mode 100644 index 11b50ba0dcc..00000000000 --- a/gcc/config/frv/cmovd.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Move double-word library function. - Copyright (C) 2000 Free Software Foundation, Inc. - Contributed by Red Hat, 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. */ - -void -__cmovd (long long *dest, const long long *src, unsigned len) -{ - unsigned i; - unsigned num = len >> 3; - unsigned xlen = len & ~7; - char *dest_byte = (char *)dest; - const char *src_byte = (const char *)src; - - if (dest_byte < src_byte || dest_byte > src_byte+len) - { - for (i = 0; i < num; i++) - dest[i] = src[i]; - - while (len > xlen) - { - dest_byte[xlen] = src_byte[xlen]; - xlen++; - } - } - else - { - while (len-- > 0) - dest_byte[len] = src_byte[len]; - } -} diff --git a/gcc/config/frv/cmovh.c b/gcc/config/frv/cmovh.c deleted file mode 100644 index 018a0b448ac..00000000000 --- a/gcc/config/frv/cmovh.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Move half-word library function. - Copyright (C) 2000 Free Software Foundation, Inc. - Contributed by Red Hat, 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. */ - -void -__cmovh (short *dest, const short *src, unsigned len) -{ - unsigned i; - unsigned num = len >> 1; - char *dest_byte = (char *)dest; - const char *src_byte = (const char *)src; - - if (dest_byte < src_byte || dest_byte > src_byte+len) - { - for (i = 0; i < num; i++) - dest[i] = src[i]; - - if ((len & 1) != 0) - dest_byte[len-1] = src_byte[len-1]; - } - else - { - while (len-- > 0) - dest_byte[len] = src_byte[len]; - } -} diff --git a/gcc/config/frv/cmovw.c b/gcc/config/frv/cmovw.c deleted file mode 100644 index 5509e068e41..00000000000 --- a/gcc/config/frv/cmovw.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Move word library function. - Copyright (C) 2000 Free Software Foundation, Inc. - Contributed by Red Hat, 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. */ - -void -__cmovw (int *dest, const int *src, unsigned len) -{ - unsigned i; - unsigned num = len >> 2; - unsigned xlen = len & ~3; - char *dest_byte = (char *)dest; - const char *src_byte = (const char *)src; - - if (dest_byte < src_byte || dest_byte > src_byte+len) - { - for (i = 0; i < num; i++) - dest[i] = src[i]; - - while (len > xlen) - { - dest_byte[xlen] = src_byte[xlen]; - xlen++; - } - } - else - { - while (len-- > 0) - dest_byte[len] = src_byte[len]; - } -} diff --git a/gcc/config/frv/frv-abi.h b/gcc/config/frv/frv-abi.h deleted file mode 100644 index 68fd32fb128..00000000000 --- a/gcc/config/frv/frv-abi.h +++ /dev/null @@ -1,181 +0,0 @@ -/* Frv map GCC names to FR-V ABI. - Copyright (C) 2000 Free Software Foundation, Inc. - Contributed by Red Hat, 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. */ - -/* For each of the functions in the library that has a corresponding name in - the ABI, add an equivalence between the GCC name and the ABI name. This is - in a separate file from frv.h so that fp-bit.c can be made to include it. */ - -#ifdef __GNUC__ -#ifdef __FRV_UNDERSCORE__ -#define RENAME_LIBRARY(OLD,NEW) \ -__asm__ (".globl\t_" #NEW "\n" \ - "_" #NEW "=_" #OLD "\n" \ - "\t.type\t_" #NEW ",@function\n"); - -#else -#define RENAME_LIBRARY(OLD,NEW) \ -__asm__ (".globl\t" #NEW "\n" \ - #NEW "=" #OLD "\n" \ - "\t.type\t" #NEW ",@function\n"); -#endif - -#define CREATE_DOUBLE_SHIFT(OLD,NEW) \ -__asm__ (".text\n" \ - "\t.globl\t" #NEW "\n" \ - "\t.type\t" #NEW ",@function\n" \ - #NEW ":\n" \ - "\tor\tgr11, gr0, gr10\n" \ - "\tbra\t" #OLD "\n"); - -#ifdef L_sf_to_df -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__extendsfdf2,__ftod) -#endif - -#ifdef L_sf_to_si -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixsfsi,__ftoi) -#endif - -#ifdef L_sf_to_usi -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunssfsi,__ftoui) -#endif - -#ifdef L_df_to_si -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixdfsi,__dtoi) -#endif - -#ifdef L_fixunssfsi -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunssfsi,__ftoui) -#endif - -#ifdef L_fixunsdfsi -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunsdfsi,__dtoui) -#endif - -#ifdef L_fixsfdi -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixsfdi,__ftoll) -#endif - -#ifdef L_fixdfdi -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixdfdi,__dtoll) -#endif - -#ifdef L_fixunssfdi -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunssfdi,__ftoull) -#endif - -#ifdef L_fixunsdfdi -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunsdfdi,__dtoull) -#endif - -#ifdef L_si_to_sf -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatsisf,__itof) -#endif - -#ifdef L_di_to_sf -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatdisf,__lltof) -#endif - -#ifdef L_df_to_sf -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__truncdfsf2,__dtof) -#endif - -#ifdef L_si_to_df -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatsidf,__itod) -#endif - -#ifdef L_floatdisf -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatdisf,__lltof) -#endif - -#ifdef L_floatdidf -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatdidf,__lltod) -#endif - -#ifdef L_addsub_df -#define DECLARE_LIBRARY_RENAMES \ - RENAME_LIBRARY(__adddf3,__addd) - RENAME_LIBRARY(__subdf3,__subd) -#endif - -#ifdef L_mul_df -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__muldf3,__muld) -#endif - -#ifdef L_div_df -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__divdf3,__divd) -#endif - -#ifdef L_addsub_sf -#define DECLARE_LIBRARY_RENAMES \ - RENAME_LIBRARY(__addsf3,__addf) \ - RENAME_LIBRARY(__subsf3,__subf) -#endif - -#ifdef L_mul_sf -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__mulsf3,__mulf) -#endif - -#ifdef L_div_sf -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__divsf3,__divf) -#endif - -#ifdef L_ashldi3 -#define DECLARE_LIBRARY_RENAMES CREATE_DOUBLE_SHIFT (__ashldi3,__sllll) -#endif - -#ifdef L_lshrdi3 -#define DECLARE_LIBRARY_RENAMES CREATE_DOUBLE_SHIFT (__lshrdi3,__srlll) -#endif - -#ifdef L_ashrdi3 -#define DECLARE_LIBRARY_RENAMES CREATE_DOUBLE_SHIFT (__ashrdi3,__srall) -#endif - -#ifdef L_adddi3 -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__adddi3,__addll) -#endif - -#ifdef L_subdi3 -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__subdi3,__subll) -#endif - -#ifdef L_muldi3 -#define DECLARE_LIBRARY_RENAMES \ - RENAME_LIBRARY(__muldi3,__mulll) - RENAME_LIBRARY(__muldi3,__umulll) -#endif - -#ifdef L_divdi3 -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__divdi3,__divll) -#endif - -#ifdef L_udivdi3 -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__udivdi3,__udivll) -#endif - -#ifdef L_moddi3 -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__moddi3,__modll) -#endif - -#ifdef L_umoddi3 -#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__umoddi3,__umodll) -#endif -#endif /* __GNUC__ */ diff --git a/gcc/config/frv/frv-asm.h b/gcc/config/frv/frv-asm.h deleted file mode 100644 index e8447a6093d..00000000000 --- a/gcc/config/frv/frv-asm.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Assembler Support. - Copyright (C) 2000 Free Software Foundation, Inc. - Contributed by Red Hat, 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. */ - -/* P(INSN): Emit INSN.P for VLIW machines, otherwise emit plain INSN. - P2(INSN): Emit INSN.P on the FR500 and above, otherwise emit plain INSN. */ -#ifdef __FRV_VLIW__ -#ifdef __STDC__ -#define P(A) A##.p -#else -#define P(A) A/**/.p -#endif -#if __FRV_VLIW__ > 2 -#define P2(A) P(A) -#else -#define P2(A) A -#endif -#else -#define P(A) A -#define P2(A) A -#endif - -/* Add underscore if necessary to external name. */ -#ifdef __FRV_UNDERSCORE__ -#ifdef __STDC__ -#define EXT(NAME) _##NAME -#else -#define EXT(NAME) _/**/NAME -#endif -#else -#define EXT(NAME) NAME -#endif diff --git a/gcc/config/frv/frv-modes.def b/gcc/config/frv/frv-modes.def deleted file mode 100644 index ca7818c1d60..00000000000 --- a/gcc/config/frv/frv-modes.def +++ /dev/null @@ -1,30 +0,0 @@ -/* Definitions of target machine for GNU compiler for FRV. - Copyright (C) 2002 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. */ - -/* On the FRV, the CC modes used are: - - CCmode set ICC's from comparing signed integers - CC_UNSmode set ICC's from comparing unsigned integers - CC_FPmode set FCC's from comparing floating point - CC_CCRmode set CCR's to do conditional execution */ - -CC (CC_UNS) -CC (CC_FP) -CC (CC_CCR) diff --git a/gcc/config/frv/frv-protos.h b/gcc/config/frv/frv-protos.h deleted file mode 100644 index c3f13f5772d..00000000000 --- a/gcc/config/frv/frv-protos.h +++ /dev/null @@ -1,253 +0,0 @@ -/* Frv prototypes. - Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. - Contributed by Red Hat, 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 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! */ - -/* Define global data defined in frv.c */ -extern const char *frv_branch_cost_string; /* -mbranch-cost option */ -extern int frv_branch_cost_int; /* value of -mbranch_cost */ - -extern const char *frv_cpu_string; /* -mcpu= option */ - -extern const char *frv_condexec_insns_str; /* -mcond-exec-insns= option */ -extern int frv_condexec_insns; /* value of -mcond-exec-insns */ - -extern const char *frv_condexec_temps_str; /* -mcond-exec-temps= option */ -extern int frv_condexec_temps; /* value of -mcond-exec-temps */ - -extern const char *frv_sched_lookahead_str; /* -msched-lookahead= option */ -extern int frv_sched_lookahead; /* value -msched-lookahead= */ - -/* CPU type. This must be identical to the cpu enumeration in frv.md. */ -typedef enum frv_cpu -{ - FRV_CPU_GENERIC, - FRV_CPU_FR500, - FRV_CPU_FR400, - FRV_CPU_FR300, - FRV_CPU_SIMPLE, - FRV_CPU_TOMCAT -} frv_cpu_t; - -extern frv_cpu_t frv_cpu_type; /* value of -mcpu= */ - -/* Define functions defined in frv.c */ -extern void frv_expand_prologue PARAMS ((void)); -extern void frv_expand_epilogue PARAMS ((int)); -extern void frv_override_options PARAMS ((void)); -extern void frv_optimization_options PARAMS ((int, int)); -extern void frv_conditional_register_usage PARAMS ((void)); -extern frv_stack_t *frv_stack_info PARAMS ((void)); -extern void frv_debug_stack PARAMS ((frv_stack_t *)); -extern int frv_frame_pointer_required PARAMS ((void)); -extern int frv_initial_elimination_offset PARAMS ((int, int)); - -#ifdef RTX_CODE -extern int frv_legitimate_address_p PARAMS ((enum machine_mode, rtx, - int, int)); -extern rtx frv_legitimize_address PARAMS ((rtx, rtx, - enum machine_mode)); - -#ifdef TREE_CODE -extern void frv_init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, - rtx, int, int)); - -extern int frv_function_arg_boundary PARAMS ((enum machine_mode, tree)); -extern rtx frv_function_arg PARAMS ((CUMULATIVE_ARGS *, - enum machine_mode, - tree, int, int)); - -extern void frv_function_arg_advance PARAMS ((CUMULATIVE_ARGS *, - enum machine_mode, - tree, int)); - -extern int frv_function_arg_partial_nregs PARAMS ((CUMULATIVE_ARGS *, - enum machine_mode, - tree, int)); - -extern int frv_function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *, - enum machine_mode, - tree, int)); - -extern int frv_function_arg_callee_copies PARAMS ((CUMULATIVE_ARGS *, - enum machine_mode, - tree, int)); - -extern int frv_function_arg_keep_as_reference PARAMS ((CUMULATIVE_ARGS *, - enum machine_mode, - tree, int)); - -extern rtx frv_expand_builtin_saveregs PARAMS ((void)); -extern void frv_setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *, - enum machine_mode, - tree, int *, int)); - -extern void frv_expand_builtin_va_start PARAMS ((tree, rtx)); -extern rtx frv_expand_builtin_va_arg PARAMS ((tree, tree)); -#endif /* TREE_CODE */ - -extern int frv_expand_block_move PARAMS ((rtx *)); -extern int frv_expand_block_clear PARAMS ((rtx *)); -extern rtx frv_dynamic_chain_address PARAMS ((rtx)); -extern rtx frv_return_addr_rtx PARAMS ((int, rtx)); -extern rtx frv_index_memory PARAMS ((rtx, - enum machine_mode, - int)); - -#ifdef TREE_CODE -extern void frv_asm_output_mi_thunk PARAMS ((FILE *, tree, long, - tree)); -#endif /* TREE_CODE */ - -extern const char *frv_asm_output_opcode - PARAMS ((FILE *, const char *)); -extern void frv_final_prescan_insn PARAMS ((rtx, rtx *, int)); -extern void frv_print_operand PARAMS ((FILE *, rtx, int)); -extern void frv_print_operand_address PARAMS ((FILE *, rtx)); -extern int frv_emit_movsi PARAMS ((rtx, rtx)); -extern const char *output_move_single PARAMS ((rtx *, rtx)); -extern const char *output_move_double PARAMS ((rtx *, rtx)); -extern const char *output_condmove_single - PARAMS ((rtx *, rtx)); -extern int frv_emit_cond_branch PARAMS ((enum rtx_code, rtx)); -extern int frv_emit_scc PARAMS ((enum rtx_code, rtx)); -extern rtx frv_split_scc PARAMS ((rtx, rtx, rtx, rtx, - HOST_WIDE_INT)); -extern int frv_emit_cond_move PARAMS ((rtx, rtx, rtx, rtx)); -extern rtx frv_split_cond_move PARAMS ((rtx *)); -extern rtx frv_split_minmax PARAMS ((rtx *)); -extern rtx frv_split_abs PARAMS ((rtx *)); -extern void frv_split_double_load PARAMS ((rtx, rtx)); -extern void frv_split_double_store PARAMS ((rtx, rtx)); -#ifdef BLOCK_HEAD -extern void frv_ifcvt_init_extra_fields PARAMS ((ce_if_block_t *)); -extern void frv_ifcvt_modify_tests PARAMS ((ce_if_block_t *, - rtx *, rtx *)); -extern void frv_ifcvt_modify_multiple_tests - PARAMS ((ce_if_block_t *, - basic_block, - rtx *, rtx *)); -extern rtx frv_ifcvt_modify_insn PARAMS ((ce_if_block_t *, - rtx, rtx)); -extern void frv_ifcvt_modify_final PARAMS ((ce_if_block_t *)); -extern void frv_ifcvt_modify_cancel PARAMS ((ce_if_block_t *)); -#endif -extern int frv_trampoline_size PARAMS ((void)); -extern void frv_initialize_trampoline PARAMS ((rtx, rtx, rtx)); -extern enum reg_class frv_secondary_reload_class - PARAMS ((enum reg_class class, - enum machine_mode mode, - rtx x, int)); -extern int frv_class_likely_spilled_p PARAMS ((enum reg_class class)); -extern int frv_hard_regno_mode_ok PARAMS ((int, enum machine_mode)); -extern int frv_hard_regno_nregs PARAMS ((int, enum machine_mode)); -extern int frv_class_max_nregs PARAMS ((enum reg_class class, - enum machine_mode mode)); -extern int frv_legitimate_constant_p PARAMS ((rtx)); -#endif /* RTX_CODE */ - -extern int direct_return_p PARAMS ((void)); -extern int frv_register_move_cost PARAMS ((enum reg_class, enum reg_class)); - -#ifdef TREE_CODE -extern int frv_adjust_field_align PARAMS ((tree, int)); -#endif - -extern void fixup_section PARAMS ((void)); -extern void sdata_section PARAMS ((void)); -extern void sbss_section PARAMS ((void)); -extern void const_section PARAMS ((void)); -extern void data_section PARAMS ((void)); - -#ifdef RTX_CODE -extern int integer_register_operand PARAMS ((rtx, enum machine_mode)); -extern int frv_load_operand PARAMS ((rtx, enum machine_mode)); -extern int gpr_or_fpr_operand PARAMS ((rtx, enum machine_mode)); -extern int gpr_no_subreg_operand PARAMS ((rtx, enum machine_mode)); -extern int gpr_or_int6_operand PARAMS ((rtx, enum machine_mode)); -extern int fpr_or_int6_operand PARAMS ((rtx, enum machine_mode)); -extern int gpr_or_int_operand PARAMS ((rtx, enum machine_mode)); -extern int gpr_or_int12_operand PARAMS ((rtx, enum machine_mode)); -extern int gpr_fpr_or_int12_operand PARAMS ((rtx, enum machine_mode)); -extern int gpr_or_int10_operand PARAMS ((rtx, enum machine_mode)); -extern int move_source_operand PARAMS ((rtx, enum machine_mode)); -extern int move_destination_operand PARAMS ((rtx, enum machine_mode)); -extern int condexec_source_operand PARAMS ((rtx, enum machine_mode)); -extern int condexec_dest_operand PARAMS ((rtx, enum machine_mode)); -extern int lr_operand PARAMS ((rtx, enum machine_mode)); -extern int gpr_or_memory_operand PARAMS ((rtx, enum machine_mode)); -extern int fpr_or_memory_operand PARAMS ((rtx, enum machine_mode)); -extern int reg_or_0_operand PARAMS ((rtx, enum machine_mode)); -extern int fcc_operand PARAMS ((rtx, enum machine_mode)); -extern int icc_operand PARAMS ((rtx, enum machine_mode)); -extern int cc_operand PARAMS ((rtx, enum machine_mode)); -extern int fcr_operand PARAMS ((rtx, enum machine_mode)); -extern int icr_operand PARAMS ((rtx, enum machine_mode)); -extern int cr_operand PARAMS ((rtx, enum machine_mode)); -extern int call_operand PARAMS ((rtx, enum machine_mode)); -extern int fpr_operand PARAMS ((rtx, enum machine_mode)); -extern int even_reg_operand PARAMS ((rtx, enum machine_mode)); -extern int odd_reg_operand PARAMS ((rtx, enum machine_mode)); -extern int even_gpr_operand PARAMS ((rtx, enum machine_mode)); -extern int odd_gpr_operand PARAMS ((rtx, enum machine_mode)); -extern int quad_fpr_operand PARAMS ((rtx, enum machine_mode)); -extern int even_fpr_operand PARAMS ((rtx, enum machine_mode)); -extern int odd_fpr_operand PARAMS ((rtx, enum machine_mode)); -extern int dbl_memory_one_insn_operand PARAMS ((rtx, enum machine_mode)); -extern int dbl_memory_two_insn_operand PARAMS ((rtx, enum machine_mode)); -extern int int12_operand PARAMS ((rtx, enum machine_mode)); -extern int int6_operand PARAMS ((rtx, enum machine_mode)); -extern int int5_operand PARAMS ((rtx, enum machine_mode)); -extern int uint5_operand PARAMS ((rtx, enum machine_mode)); -extern int uint4_operand PARAMS ((rtx, enum machine_mode)); -extern int uint1_operand PARAMS ((rtx, enum machine_mode)); -extern int int_2word_operand PARAMS ((rtx, enum machine_mode)); -extern int pic_register_operand PARAMS ((rtx, enum machine_mode)); -extern int pic_symbolic_operand PARAMS ((rtx, enum machine_mode)); -extern int small_data_register_operand PARAMS ((rtx, enum machine_mode)); -extern int small_data_symbolic_operand PARAMS ((rtx, enum machine_mode)); -extern int upper_int16_operand PARAMS ((rtx, enum machine_mode)); -extern int uint16_operand PARAMS ((rtx, enum machine_mode)); -extern int relational_operator PARAMS ((rtx, enum machine_mode)); -extern int signed_relational_operator PARAMS ((rtx, enum machine_mode)); -extern int unsigned_relational_operator PARAMS ((rtx, enum machine_mode)); -extern int float_relational_operator PARAMS ((rtx, enum machine_mode)); -extern int ccr_eqne_operator PARAMS ((rtx, enum machine_mode)); -extern int minmax_operator PARAMS ((rtx, enum machine_mode)); -extern int condexec_si_binary_operator PARAMS ((rtx, enum machine_mode)); -extern int condexec_si_media_operator PARAMS ((rtx, enum machine_mode)); -extern int condexec_si_divide_operator PARAMS ((rtx, enum machine_mode)); -extern int condexec_si_unary_operator PARAMS ((rtx, enum machine_mode)); -extern int condexec_sf_conv_operator PARAMS ((rtx, enum machine_mode)); -extern int condexec_sf_add_operator PARAMS ((rtx, enum machine_mode)); -extern int condexec_memory_operand PARAMS ((rtx, enum machine_mode)); -extern int intop_compare_operator PARAMS ((rtx, enum machine_mode)); -extern int condexec_intop_cmp_operator PARAMS ((rtx, enum machine_mode)); -extern int acc_operand PARAMS ((rtx, enum machine_mode)); -extern int even_acc_operand PARAMS ((rtx, enum machine_mode)); -extern int quad_acc_operand PARAMS ((rtx, enum machine_mode)); -extern int accg_operand PARAMS ((rtx, enum machine_mode)); -extern rtx frv_matching_accg_for_acc PARAMS ((rtx)); -extern void frv_machine_dependent_reorg PARAMS ((rtx)); -#endif - diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c deleted file mode 100644 index 4ef94e4ab50..00000000000 --- a/gcc/config/frv/frv.c +++ /dev/null @@ -1,9776 +0,0 @@ -/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - Contributed by Red Hat, 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. */ - -#include "config.h" -#include "system.h" -#include "rtl.h" -#include "tree.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "insn-flags.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "recog.h" -#include "reload.h" -#include "expr.h" -#include "obstack.h" -#include "except.h" -#include "function.h" -#include "optabs.h" -#include "toplev.h" -#include "basic-block.h" -#include "tm_p.h" -#include "ggc.h" -#include -#include "target.h" -#include "target-def.h" - -#ifndef FRV_INLINE -#define FRV_INLINE inline -#endif - -/* Temporary register allocation support structure. */ -typedef struct frv_tmp_reg_struct - { - HARD_REG_SET regs; /* possible registers to allocate */ - int next_reg[N_REG_CLASSES]; /* next register to allocate per class */ - } -frv_tmp_reg_t; - -/* Register state information for VLIW re-packing phase. These values must fit - within an unsigned char. */ -#define REGSTATE_DEAD 0x00 /* register is currently dead */ -#define REGSTATE_CC_MASK 0x07 /* Mask to isolate CCn for cond exec */ -#define REGSTATE_LIVE 0x08 /* register is live */ -#define REGSTATE_MODIFIED 0x10 /* reg modified in current VLIW insn */ -#define REGSTATE_IF_TRUE 0x20 /* reg modified in cond exec true */ -#define REGSTATE_IF_FALSE 0x40 /* reg modified in cond exec false */ -#define REGSTATE_UNUSED 0x80 /* bit for hire */ -#define REGSTATE_MASK 0xff /* mask for the bits to set */ - - /* conditional expression used */ -#define REGSTATE_IF_EITHER (REGSTATE_IF_TRUE | REGSTATE_IF_FALSE) - -/* the following is not sure in the reg_state bytes, so can have a larger value - than 0xff. */ -#define REGSTATE_CONDJUMP 0x100 /* conditional jump done in VLIW insn */ - -/* Used in frv_frame_accessor_t to indicate the direction of a register-to- - memory move. */ -enum frv_stack_op -{ - FRV_LOAD, - FRV_STORE -}; - -/* Information required by frv_frame_access. */ -typedef struct -{ - /* This field is FRV_LOAD if registers are to be loaded from the stack and - FRV_STORE if they should be stored onto the stack. FRV_STORE implies - the move is being done by the prologue code while FRV_LOAD implies it - is being done by the epilogue. */ - enum frv_stack_op op; - - /* The base register to use when accessing the stack. This may be the - frame pointer, stack pointer, or a temporary. The choice of register - depends on which part of the frame is being accessed and how big the - frame is. */ - rtx base; - - /* The offset of BASE from the bottom of the current frame, in bytes. */ - int base_offset; -} frv_frame_accessor_t; - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ -rtx frv_compare_op0; -rtx frv_compare_op1; - -/* Conditional execution support gathered together in one structure */ -typedef struct - { - /* Linked list of insns to add if the conditional execution conversion was - successful. Each link points to an EXPR_LIST which points to the pattern - of the insn to add, and the insn to be inserted before. */ - rtx added_insns_list; - - /* Identify which registers are safe to allocate for if conversions to - conditional execution. We keep the last allocated register in the - register classes between COND_EXEC statements. This will mean we allocate - different registers for each different COND_EXEC group if we can. This - might allow the scheduler to intermix two different COND_EXEC sections. */ - frv_tmp_reg_t tmp_reg; - - /* For nested IFs, identify which CC registers are used outside of setting - via a compare isnsn, and using via a check insn. This will allow us to - know if we can rewrite the register to use a different register that will - be paired with the CR register controlling the nested IF-THEN blocks. */ - HARD_REG_SET nested_cc_ok_rewrite; - - /* Temporary registers allocated to hold constants during conditional - execution. */ - rtx scratch_regs[FIRST_PSEUDO_REGISTER]; - - /* Current number of temp registers available. */ - int cur_scratch_regs; - - /* Number of nested conditional execution blocks */ - int num_nested_cond_exec; - - /* Map of insns that set up constants in scratch registers. */ - bitmap scratch_insns_bitmap; - - /* Conditional execution test register (CC0..CC7) */ - rtx cr_reg; - - /* Conditional execution compare register that is paired with cr_reg, so that - nested compares can be done. The csubcc and caddcc instructions don't - have enough bits to specify both a CC register to be set and a CR register - to do the test on, so the same bit number is used for both. Needless to - say, this is rather inconvient for GCC. */ - rtx nested_cc_reg; - - /* Extra CR registers used for &&, ||. */ - rtx extra_int_cr; - rtx extra_fp_cr; - - /* Previous CR used in nested if, to make sure we are dealing with the same - nested if as the previous statement. */ - rtx last_nested_if_cr; - } -frv_ifcvt_t; - -static /* GTY(()) */ frv_ifcvt_t frv_ifcvt; - -/* 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]; - -/* Cached value of frv_stack_info */ -static frv_stack_t *frv_stack_cache = (frv_stack_t *)0; - -/* -mbranch-cost= support */ -const char *frv_branch_cost_string; -int frv_branch_cost_int = DEFAULT_BRANCH_COST; - -/* -mcpu= support */ -const char *frv_cpu_string; /* -mcpu= option */ -frv_cpu_t frv_cpu_type = CPU_TYPE; /* value of -mcpu= */ - -/* -mcond-exec-insns= support */ -const char *frv_condexec_insns_str; /* -mcond-exec-insns= option */ -int frv_condexec_insns = DEFAULT_CONDEXEC_INSNS; /* value of -mcond-exec-insns*/ - -/* -mcond-exec-temps= support */ -const char *frv_condexec_temps_str; /* -mcond-exec-temps= option */ -int frv_condexec_temps = DEFAULT_CONDEXEC_TEMPS; /* value of -mcond-exec-temps*/ - -/* -msched-lookahead=n */ -const char *frv_sched_lookahead_str; /* -msched-lookahead=n */ -int frv_sched_lookahead = 4; /* -msched-lookahead=n */ - -/* Forward references */ -static int frv_default_flags_for_cpu PARAMS ((void)); -static int frv_string_begins_with PARAMS ((tree, const char *)); -static FRV_INLINE int symbol_ref_small_data_p PARAMS ((rtx)); -static FRV_INLINE int const_small_data_p PARAMS ((rtx)); -static FRV_INLINE int plus_small_data_p PARAMS ((rtx, rtx)); -static void frv_print_operand_memory_reference_reg - PARAMS ((FILE *, rtx)); -static void frv_print_operand_memory_reference PARAMS ((FILE *, rtx, int)); -static int frv_print_operand_jump_hint PARAMS ((rtx)); -static FRV_INLINE int frv_regno_ok_for_base_p PARAMS ((int, int)); -static rtx single_set_pattern PARAMS ((rtx)); -static int frv_function_contains_far_jump PARAMS ((void)); -static rtx frv_alloc_temp_reg PARAMS ((frv_tmp_reg_t *, - enum reg_class, - enum machine_mode, - int, int)); -static rtx frv_frame_offset_rtx PARAMS ((int)); -static rtx frv_frame_mem PARAMS ((enum machine_mode, - rtx, int)); -static rtx frv_dwarf_store PARAMS ((rtx, int)); -static void frv_frame_insn PARAMS ((rtx, rtx)); -static void frv_frame_access PARAMS ((frv_frame_accessor_t*, - rtx, int)); -static void frv_frame_access_multi PARAMS ((frv_frame_accessor_t*, - frv_stack_t *, int)); -static void frv_frame_access_standard_regs PARAMS ((enum frv_stack_op, - frv_stack_t *)); -static struct machine_function *frv_init_machine_status PARAMS ((void)); -static int frv_legitimate_memory_operand PARAMS ((rtx, - enum machine_mode, - int)); -static rtx frv_int_to_acc PARAMS ((enum insn_code, - int, rtx)); -static enum machine_mode frv_matching_accg_mode PARAMS ((enum machine_mode)); -static rtx frv_read_argument PARAMS ((tree *)); -static int frv_check_constant_argument PARAMS ((enum insn_code, - int, rtx)); -static rtx frv_legitimize_target PARAMS ((enum insn_code, rtx)); -static rtx frv_legitimize_argument PARAMS ((enum insn_code, - int, rtx)); -static rtx frv_expand_set_builtin PARAMS ((enum insn_code, - tree, rtx)); -static rtx frv_expand_unop_builtin PARAMS ((enum insn_code, - tree, rtx)); -static rtx frv_expand_binop_builtin PARAMS ((enum insn_code, - tree, rtx)); -static rtx frv_expand_cut_builtin PARAMS ((enum insn_code, - tree, rtx)); -static rtx frv_expand_binopimm_builtin PARAMS ((enum insn_code, - tree, rtx)); -static rtx frv_expand_voidbinop_builtin PARAMS ((enum insn_code, - tree)); -static rtx frv_expand_voidtriop_builtin PARAMS ((enum insn_code, - tree)); -static rtx frv_expand_voidaccop_builtin PARAMS ((enum insn_code, - tree)); -static rtx frv_expand_mclracc_builtin PARAMS ((tree)); -static rtx frv_expand_mrdacc_builtin PARAMS ((enum insn_code, - tree)); -static rtx frv_expand_mwtacc_builtin PARAMS ((enum insn_code, - tree)); -static rtx frv_expand_noargs_builtin PARAMS ((enum insn_code)); -static rtx frv_emit_comparison PARAMS ((enum rtx_code, rtx, - rtx)); -static int frv_clear_registers_used PARAMS ((rtx *, void *)); -static void frv_ifcvt_add_insn PARAMS ((rtx, rtx, int)); -static rtx frv_ifcvt_rewrite_mem PARAMS ((rtx, - enum machine_mode, - rtx)); -static rtx frv_ifcvt_load_value PARAMS ((rtx, rtx)); -static void frv_registers_update PARAMS ((rtx, unsigned char [], - int [], int *, int)); -static int frv_registers_used_p PARAMS ((rtx, unsigned char [], - int)); -static int frv_registers_set_p PARAMS ((rtx, unsigned char [], - int)); -static void frv_pack_insns PARAMS ((void)); -static void frv_function_prologue PARAMS ((FILE *, HOST_WIDE_INT)); -static void frv_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT)); -static bool frv_assemble_integer PARAMS ((rtx, unsigned, int)); -static const char * frv_strip_name_encoding PARAMS ((const char *)); -static void frv_encode_section_info PARAMS ((tree, int)); -static void frv_init_builtins PARAMS ((void)); -static rtx frv_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int)); -static bool frv_in_small_data_p PARAMS ((tree)); - -/* Initialize the GCC target structure. */ -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE frv_function_prologue -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE frv_function_epilogue -#undef TARGET_ASM_INTEGER -#define TARGET_ASM_INTEGER frv_assemble_integer -#undef TARGET_STRIP_NAME_ENCODING -#define TARGET_STRIP_NAME_ENCODING frv_strip_name_encoding -#undef TARGET_ENCODE_SECTION_INFO -#define TARGET_ENCODE_SECTION_INFO frv_encode_section_info -#undef TARGET_INIT_BUILTINS -#define TARGET_INIT_BUILTINS frv_init_builtins -#undef TARGET_EXPAND_BUILTIN -#define TARGET_EXPAND_BUILTIN frv_expand_builtin -#undef TARGET_IN_SMALL_DATA_P -#define TARGET_IN_SMALL_DATA_P frv_in_small_data_p - -struct gcc_target targetm = TARGET_INITIALIZER; - -/* Given a SYMBOL_REF, return true if it points to small data. */ - -static FRV_INLINE int -symbol_ref_small_data_p (x) - rtx x; -{ - return SDATA_NAME_P (XSTR (x, 0)); -} - -/* Given a CONST, return true if the symbol_ref points to small data. */ - -static FRV_INLINE int -const_small_data_p (x) - rtx x; -{ - rtx x0, x1; - - if (GET_CODE (XEXP (x, 0)) != PLUS) - return FALSE; - - x0 = XEXP (XEXP (x, 0), 0); - if (GET_CODE (x0) != SYMBOL_REF || !SDATA_NAME_P (XSTR (x0, 0))) - return FALSE; - - x1 = XEXP (XEXP (x, 0), 1); - if (GET_CODE (x1) != CONST_INT - || !IN_RANGE_P (INTVAL (x1), -2048, 2047)) - return FALSE; - - return TRUE; -} - -/* Given a PLUS, return true if this is a small data reference. */ - -static FRV_INLINE int -plus_small_data_p (op0, op1) - rtx op0; - rtx op1; -{ - if (GET_MODE (op0) == SImode - && GET_CODE (op0) == REG - && REGNO (op0) == SDA_BASE_REG) - { - if (GET_CODE (op1) == SYMBOL_REF) - return symbol_ref_small_data_p (op1); - - if (GET_CODE (op1) == CONST) - return const_small_data_p (op1); - } - - return FALSE; -} - - -static int -frv_default_flags_for_cpu () -{ - switch (frv_cpu_type) - { - case FRV_CPU_GENERIC: - return MASK_DEFAULT_FRV; - - case FRV_CPU_FR500: - case FRV_CPU_TOMCAT: - return MASK_DEFAULT_FR500; - - case FRV_CPU_FR400: - return MASK_DEFAULT_FR400; - - case FRV_CPU_FR300: - case FRV_CPU_SIMPLE: - return MASK_DEFAULT_SIMPLE; - } - abort (); -} - -/* 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 -frv_override_options () -{ - int regno, i; - - /* Set the cpu type */ - if (frv_cpu_string) - { - if (strcmp (frv_cpu_string, "simple") == 0) - frv_cpu_type = FRV_CPU_SIMPLE; - - else if (strcmp (frv_cpu_string, "tomcat") == 0) - frv_cpu_type = FRV_CPU_TOMCAT; - - else if (strncmp (frv_cpu_string, "fr", sizeof ("fr")-1) != 0) - error ("Unknown cpu: -mcpu=%s", frv_cpu_string); - - else - { - const char *p = frv_cpu_string + sizeof ("fr") - 1; - if (strcmp (p, "500") == 0) - frv_cpu_type = FRV_CPU_FR500; - - else if (strcmp (p, "400") == 0) - frv_cpu_type = FRV_CPU_FR400; - - else if (strcmp (p, "300") == 0) - frv_cpu_type = FRV_CPU_FR300; - - else if (strcmp (p, "v") == 0) - frv_cpu_type = FRV_CPU_GENERIC; - - else - error ("Unknown cpu: -mcpu=%s", frv_cpu_string); - } - } - - target_flags |= (frv_default_flags_for_cpu () & ~target_flags_explicit); - - /* -mlibrary-pic sets -fPIC and -G0 and also suppresses warnings from the - linker about linking pic and non-pic code. */ - if (TARGET_LIBPIC) - { - if (!flag_pic) /* -fPIC */ - flag_pic = 2; - - if (! g_switch_set) /* -G0 */ - { - g_switch_set = 1; - g_switch_value = 0; - } - } - - /* Both -fpic and -gdwarf want to use .previous and the assembler only keeps - one level. */ - if (write_symbols == DWARF_DEBUG && flag_pic) - error ("-fpic and -gdwarf are incompatible (-fpic and -g/-gdwarf-2 are fine)"); - - /* Change the branch cost value */ - if (frv_branch_cost_string) - frv_branch_cost_int = atoi (frv_branch_cost_string); - - /* Change the # of insns to be converted to conditional execution */ - if (frv_condexec_insns_str) - frv_condexec_insns = atoi (frv_condexec_insns_str); - - /* Change # of temporary registers used to hold integer constants */ - if (frv_condexec_temps_str) - frv_condexec_temps = atoi (frv_condexec_temps_str); - - /* Change scheduling look ahead. */ - if (frv_sched_lookahead_str) - frv_sched_lookahead = atoi (frv_sched_lookahead_str); - - /* 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)) - { - int gpr_reg = regno - GPR_FIRST; - if ((gpr_reg & 3) == 0) - class = QUAD_REGS; - - else if ((gpr_reg & 1) == 0) - class = EVEN_REGS; - - else - class = GPR_REGS; - } - - else if (FPR_P (regno)) - { - int fpr_reg = regno - GPR_FIRST; - if ((fpr_reg & 3) == 0) - class = QUAD_FPR_REGS; - - else if ((fpr_reg & 1) == 0) - class = FEVEN_REGS; - - else - class = FPR_REGS; - } - - else if (regno == LR_REGNO) - class = LR_REG; - - else if (regno == LCR_REGNO) - class = LCR_REG; - - else if (ICC_P (regno)) - class = ICC_REGS; - - else if (FCC_P (regno)) - class = FCC_REGS; - - else if (ICR_P (regno)) - class = ICR_REGS; - - else if (FCR_P (regno)) - class = FCR_REGS; - - else if (ACC_P (regno)) - { - int r = regno - ACC_FIRST; - if ((r & 3) == 0) - class = QUAD_ACC_REGS; - else if ((r & 1) == 0) - class = EVEN_ACC_REGS; - else - class = ACC_REGS; - } - - else if (ACCG_P (regno)) - class = ACCG_REGS; - - else - class = NO_REGS; - - regno_reg_class[regno] = class; - } - - /* Check for small data option */ - if (!g_switch_set) - g_switch_value = SDATA_DEFAULT_SIZE; - - /* 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'] = ACC_REGS; - reg_class_from_letter['b'] = EVEN_ACC_REGS; - reg_class_from_letter['c'] = CC_REGS; - reg_class_from_letter['d'] = GPR_REGS; - reg_class_from_letter['e'] = EVEN_REGS; - reg_class_from_letter['f'] = FPR_REGS; - reg_class_from_letter['h'] = FEVEN_REGS; - reg_class_from_letter['l'] = LR_REG; - reg_class_from_letter['q'] = QUAD_REGS; - reg_class_from_letter['t'] = ICC_REGS; - reg_class_from_letter['u'] = FCC_REGS; - reg_class_from_letter['v'] = ICR_REGS; - reg_class_from_letter['w'] = FCR_REGS; - reg_class_from_letter['x'] = QUAD_FPR_REGS; - reg_class_from_letter['y'] = LCR_REG; - reg_class_from_letter['z'] = SPR_REGS; - reg_class_from_letter['A'] = QUAD_ACC_REGS; - reg_class_from_letter['B'] = ACCG_REGS; - reg_class_from_letter['C'] = CR_REGS; - - /* There is no single unaligned SI op for PIC code. Sometimes we - need to use ".4byte" and sometimes we need to use ".picptr". - See frv_assemble_integer for details. */ - if (flag_pic) - targetm.asm_out.unaligned_op.si = 0; - - init_machine_status = frv_init_machine_status; -} - - -/* 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. */ - -/* On the FRV, possibly disable VLIW packing which is done by the 2nd - scheduling pass at the current time. */ -void -frv_optimization_options (level, size) - int level; - int size ATTRIBUTE_UNUSED; -{ - if (level >= 2) - { -#ifdef DISABLE_SCHED2 - flag_schedule_insns_after_reload = 0; -#endif -#ifdef ENABLE_RCSP - flag_rcsp = 1; -#endif - } -} - - -/* Return true if NAME (a STRING_CST node) begins with PREFIX. */ - -static int -frv_string_begins_with (name, prefix) - tree name; - const char *prefix; -{ - int prefix_len = strlen (prefix); - - /* Remember: NAME's length includes the null terminator. */ - return (TREE_STRING_LENGTH (name) > prefix_len - && strncmp (TREE_STRING_POINTER (name), prefix, prefix_len) == 0); -} - -/* Encode section information of DECL, which is either a VAR_DECL, - FUNCTION_DECL, STRING_CST, CONSTRUCTOR, or ???. - - For the FRV we want to record: - - - whether the object lives in .sdata/.sbss. - objects living in .sdata/.sbss are prefixed with SDATA_FLAG_CHAR - -*/ - -static void -frv_encode_section_info (decl, first) - tree decl; - int first; -{ - if (! first) - return; - if (TREE_CODE (decl) == VAR_DECL) - { - int size = int_size_in_bytes (TREE_TYPE (decl)); - tree section_name = DECL_SECTION_NAME (decl); - int is_small = 0; - - /* Don't apply the -G flag to internal compiler structures. We - should leave such structures in the main data section, partly - for efficiency and partly because the size of some of them - (such as C++ typeinfos) is not known until later. */ - if (!DECL_ARTIFICIAL (decl) && size > 0 && size <= g_switch_value) - is_small = 1; - - /* If we already know which section the decl should be in, see if - it's a small data section. */ - if (section_name) - { - if (TREE_CODE (section_name) == STRING_CST) - { - if (frv_string_begins_with (section_name, ".sdata")) - is_small = 1; - if (frv_string_begins_with (section_name, ".sbss")) - is_small = 1; - } - else - abort (); - } - - if (is_small) - { - rtx sym_ref = XEXP (DECL_RTL (decl), 0); - char * str = xmalloc (2 + strlen (XSTR (sym_ref, 0))); - - str[0] = SDATA_FLAG_CHAR; - strcpy (&str[1], XSTR (sym_ref, 0)); - XSTR (sym_ref, 0) = str; - } - } -} - - -/* 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.) */ - -void -frv_conditional_register_usage () -{ - int i; - - for (i = GPR_FIRST + NUM_GPRS; i <= GPR_LAST; i++) - fixed_regs[i] = call_used_regs[i] = 1; - - for (i = FPR_FIRST + NUM_FPRS; i <= FPR_LAST; i++) - fixed_regs[i] = call_used_regs[i] = 1; - - for (i = ACC_FIRST + NUM_ACCS; i <= ACC_LAST; i++) - fixed_regs[i] = call_used_regs[i] = 1; - - for (i = ACCG_FIRST + NUM_ACCS; i <= ACCG_LAST; i++) - fixed_regs[i] = call_used_regs[i] = 1; - - /* Reserve the registers used for conditional execution. At present, we need - 1 ICC and 1 ICR register. */ - fixed_regs[ICC_TEMP] = call_used_regs[ICC_TEMP] = 1; - fixed_regs[ICR_TEMP] = call_used_regs[ICR_TEMP] = 1; - - if (TARGET_FIXED_CC) - { - fixed_regs[ICC_FIRST] = call_used_regs[ICC_FIRST] = 1; - fixed_regs[FCC_FIRST] = call_used_regs[FCC_FIRST] = 1; - fixed_regs[ICR_FIRST] = call_used_regs[ICR_FIRST] = 1; - fixed_regs[FCR_FIRST] = call_used_regs[FCR_FIRST] = 1; - } - -#if 0 - /* If -fpic, SDA_BASE_REG is the PIC register. */ - if (g_switch_value == 0 && !flag_pic) - fixed_regs[SDA_BASE_REG] = call_used_regs[SDA_BASE_REG] = 0; - - if (!flag_pic) - fixed_regs[PIC_REGNO] = call_used_regs[PIC_REGNO] = 0; -#endif -} - - -/* - * Compute the stack frame layout - * - * Register setup: - * +---------------+-----------------------+-----------------------+ - * |Register |type |caller-save/callee-save| - * +---------------+-----------------------+-----------------------+ - * |GR0 |Zero register | - | - * |GR1 |Stack pointer(SP) | - | - * |GR2 |Frame pointer(FP) | - | - * |GR3 |Hidden parameter | caller save | - * |GR4-GR7 | - | caller save | - * |GR8-GR13 |Argument register | caller save | - * |GR14-GR15 | - | caller save | - * |GR16-GR31 | - | callee save | - * |GR32-GR47 | - | caller save | - * |GR48-GR63 | - | callee save | - * |FR0-FR15 | - | caller save | - * |FR16-FR31 | - | callee save | - * |FR32-FR47 | - | caller save | - * |FR48-FR63 | - | callee save | - * +---------------+-----------------------+-----------------------+ - * - * Stack frame setup: - * Low - * SP-> |-----------------------------------| - * | Argument area | - * |-----------------------------------| - * | Register save area | - * |-----------------------------------| - * | Local variable save area | - * FP-> |-----------------------------------| - * | Old FP | - * |-----------------------------------| - * | Hidden parameter save area | - * |-----------------------------------| - * | Return address(LR) storage area | - * |-----------------------------------| - * | Padding for alignment | - * |-----------------------------------| - * | Register argument area | - * OLD SP-> |-----------------------------------| - * | Parameter area | - * |-----------------------------------| - * High - * - * Argument area/Parameter area: - * - * When a function is called, this area is used for argument transfer. When - * the argument is set up by the caller function, this area is referred to as - * the argument area. When the argument is referenced by the callee function, - * this area is referred to as the parameter area. The area is allocated when - * all arguments cannot be placed on the argument register at the time of - * argument transfer. - * - * Register save area: - * - * This is a register save area that must be guaranteed for the caller - * function. This area is not secured when the register save operation is not - * needed. - * - * Local variable save area: - * - * This is the area for local variables and temporary variables. - * - * Old FP: - * - * This area stores the FP value of the caller function. - * - * Hidden parameter save area: - * - * This area stores the start address of the return value storage - * area for a struct/union return function. - * When a struct/union is used as the return value, the caller - * function stores the return value storage area start address in - * register GR3 and passes it to the caller function. - * The callee function interprets the address stored in the GR3 - * as the return value storage area start address. - * When register GR3 needs to be saved into memory, the callee - * function saves it in the hidden parameter save area. This - * area is not secured when the save operation is not needed. - * - * Return address(LR) storage area: - * - * This area saves the LR. The LR stores the address of a return to the caller - * function for the purpose of function calling. - * - * Argument register area: - * - * This area saves the argument register. This area is not secured when the - * save operation is not needed. - * - * Argument: - * - * Arguments, the count of which equals the count of argument registers (6 - * words), are positioned in registers GR8 to GR13 and delivered to the callee - * function. When a struct/union return function is called, the return value - * area address is stored in register GR3. Arguments not placed in the - * argument registers will be stored in the stack argument area for transfer - * purposes. When an 8-byte type argument is to be delivered using registers, - * it is divided into two and placed in two registers for transfer. When - * argument registers must be saved to memory, the callee function secures an - * argument register save area in the stack. In this case, a continuous - * argument register save area must be established in the parameter area. The - * argument register save area must be allocated as needed to cover the size of - * the argument register to be saved. If the function has a variable count of - * arguments, it saves all argument registers in the argument register save - * area. - * - * Argument Extension Format: - * - * When an argument is to be stored in the stack, its type is converted to an - * extended type in accordance with the individual argument type. The argument - * is freed by the caller function after the return from the callee function is - * made. - * - * +-----------------------+---------------+------------------------+ - * | Argument Type |Extended Type |Stack Storage Size(byte)| - * +-----------------------+---------------+------------------------+ - * |char |int | 4 | - * |signed char |int | 4 | - * |unsigned char |int | 4 | - * |[signed] short int |int | 4 | - * |unsigned short int |int | 4 | - * |[signed] int |No extension | 4 | - * |unsigned int |No extension | 4 | - * |[signed] long int |No extension | 4 | - * |unsigned long int |No extension | 4 | - * |[signed] long long int |No extension | 8 | - * |unsigned long long int |No extension | 8 | - * |float |double | 8 | - * |double |No extension | 8 | - * |long double |No extension | 8 | - * |pointer |No extension | 4 | - * |struct/union |- | 4 (*1) | - * +-----------------------+---------------+------------------------+ - * - * When a struct/union is to be delivered as an argument, the caller copies it - * to the local variable area and delivers the address of that area. - * - * Return Value: - * - * +-------------------------------+----------------------+ - * |Return Value Type |Return Value Interface| - * +-------------------------------+----------------------+ - * |void |None | - * |[signed|unsigned] char |GR8 | - * |[signed|unsigned] short int |GR8 | - * |[signed|unsigned] int |GR8 | - * |[signed|unsigned] long int |GR8 | - * |pointer |GR8 | - * |[signed|unsigned] long long int|GR8 & GR9 | - * |float |GR8 | - * |double |GR8 & GR9 | - * |long double |GR8 & GR9 | - * |struct/union |(*1) | - * +-------------------------------+----------------------+ - * - * When a struct/union is used as the return value, the caller function stores - * the start address of the return value storage area into GR3 and then passes - * it to the callee function. The callee function interprets GR3 as the start - * address of the return value storage area. When this address needs to be - * saved in memory, the callee function secures the hidden parameter save area - * and saves the address in that area. - */ - -frv_stack_t * -frv_stack_info () -{ - static frv_stack_t info, zero_info; - frv_stack_t *info_ptr = &info; - tree fndecl = current_function_decl; - int varargs_p = 0; - tree cur_arg; - tree next_arg; - int range; - int alignment; - int offset; - - /* If we've already calculated the values and reload is complete, just return now */ - if (frv_stack_cache) - return frv_stack_cache; - - /* Zero all fields */ - info = zero_info; - - /* Set up the register range information */ - info_ptr->regs[STACK_REGS_GPR].name = "gpr"; - info_ptr->regs[STACK_REGS_GPR].first = LAST_ARG_REGNUM + 1; - info_ptr->regs[STACK_REGS_GPR].last = GPR_LAST; - info_ptr->regs[STACK_REGS_GPR].dword_p = TRUE; - - info_ptr->regs[STACK_REGS_FPR].name = "fpr"; - info_ptr->regs[STACK_REGS_FPR].first = FPR_FIRST; - info_ptr->regs[STACK_REGS_FPR].last = FPR_LAST; - info_ptr->regs[STACK_REGS_FPR].dword_p = TRUE; - - info_ptr->regs[STACK_REGS_LR].name = "lr"; - info_ptr->regs[STACK_REGS_LR].first = LR_REGNO; - info_ptr->regs[STACK_REGS_LR].last = LR_REGNO; - info_ptr->regs[STACK_REGS_LR].special_p = 1; - - info_ptr->regs[STACK_REGS_CC].name = "cc"; - info_ptr->regs[STACK_REGS_CC].first = CC_FIRST; - info_ptr->regs[STACK_REGS_CC].last = CC_LAST; - info_ptr->regs[STACK_REGS_CC].field_p = TRUE; - - info_ptr->regs[STACK_REGS_LCR].name = "lcr"; - info_ptr->regs[STACK_REGS_LCR].first = LCR_REGNO; - info_ptr->regs[STACK_REGS_LCR].last = LCR_REGNO; - - info_ptr->regs[STACK_REGS_STDARG].name = "stdarg"; - info_ptr->regs[STACK_REGS_STDARG].first = FIRST_ARG_REGNUM; - info_ptr->regs[STACK_REGS_STDARG].last = LAST_ARG_REGNUM; - info_ptr->regs[STACK_REGS_STDARG].dword_p = 1; - info_ptr->regs[STACK_REGS_STDARG].special_p = 1; - - info_ptr->regs[STACK_REGS_STRUCT].name = "struct"; - info_ptr->regs[STACK_REGS_STRUCT].first = STRUCT_VALUE_REGNUM; - info_ptr->regs[STACK_REGS_STRUCT].last = STRUCT_VALUE_REGNUM; - info_ptr->regs[STACK_REGS_STRUCT].special_p = 1; - - info_ptr->regs[STACK_REGS_FP].name = "fp"; - info_ptr->regs[STACK_REGS_FP].first = FRAME_POINTER_REGNUM; - info_ptr->regs[STACK_REGS_FP].last = FRAME_POINTER_REGNUM; - info_ptr->regs[STACK_REGS_FP].special_p = 1; - - /* Determine if this is a stdarg function. If so, allocate space to store - the 6 arguments. */ - if (cfun->stdarg) - 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; - } - } - } - - /* Iterate over all of the register ranges */ - for (range = 0; range < STACK_REGS_MAX; range++) - { - frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]); - int first = reg_ptr->first; - int last = reg_ptr->last; - int size_1word = 0; - int size_2words = 0; - int regno; - - /* Calculate which registers need to be saved & save area size */ - switch (range) - { - default: - for (regno = first; regno <= last; regno++) - { - if ((regs_ever_live[regno] && !call_used_regs[regno]) - || (current_function_calls_eh_return - && (regno >= FIRST_EH_REGNUM && regno <= LAST_EH_REGNUM)) - || (flag_pic && cfun->uses_pic_offset_table && regno == PIC_REGNO)) - { - info_ptr->save_p[regno] = REG_SAVE_1WORD; - size_1word += UNITS_PER_WORD; - } - } - break; - - /* Calculate whether we need to create a frame after everything else - has been processed. */ - case STACK_REGS_FP: - break; - - case STACK_REGS_LR: - if (regs_ever_live[LR_REGNO] - || profile_flag - || frame_pointer_needed - || (flag_pic && cfun->uses_pic_offset_table)) - { - info_ptr->save_p[LR_REGNO] = REG_SAVE_1WORD; - size_1word += UNITS_PER_WORD; - } - break; - - case STACK_REGS_STDARG: - if (varargs_p) - { - /* If this is a stdarg function with an non varardic argument split - between registers and the stack, adjust the saved registers - downward */ - last -= (ADDR_ALIGN (cfun->pretend_args_size, UNITS_PER_WORD) - / UNITS_PER_WORD); - - for (regno = first; regno <= last; regno++) - { - info_ptr->save_p[regno] = REG_SAVE_1WORD; - size_1word += UNITS_PER_WORD; - } - - info_ptr->stdarg_size = size_1word; - } - break; - - case STACK_REGS_STRUCT: - if (cfun->returns_struct) - { - info_ptr->save_p[STRUCT_VALUE_REGNUM] = REG_SAVE_1WORD; - size_1word += UNITS_PER_WORD; - } - break; - } - - - if (size_1word) - { - /* If this is a field, it only takes one word */ - if (reg_ptr->field_p) - size_1word = UNITS_PER_WORD; - - /* Determine which register pairs can be saved together */ - else if (reg_ptr->dword_p && TARGET_DWORD) - { - for (regno = first; regno < last; regno += 2) - { - if (info_ptr->save_p[regno] && info_ptr->save_p[regno+1]) - { - size_2words += 2 * UNITS_PER_WORD; - size_1word -= 2 * UNITS_PER_WORD; - info_ptr->save_p[regno] = REG_SAVE_2WORDS; - info_ptr->save_p[regno+1] = REG_SAVE_NO_SAVE; - } - } - } - - reg_ptr->size_1word = size_1word; - reg_ptr->size_2words = size_2words; - - if (! reg_ptr->special_p) - { - info_ptr->regs_size_1word += size_1word; - info_ptr->regs_size_2words += size_2words; - } - } - } - - /* Set up the sizes of each each field in the frame body, making the sizes - of each be divisible by the size of a dword if dword operations might - be used, or the size of a word otherwise. */ - alignment = (TARGET_DWORD? 2 * UNITS_PER_WORD : UNITS_PER_WORD); - - info_ptr->parameter_size = ADDR_ALIGN (cfun->outgoing_args_size, alignment); - info_ptr->regs_size = ADDR_ALIGN (info_ptr->regs_size_2words - + info_ptr->regs_size_1word, - alignment); - info_ptr->vars_size = ADDR_ALIGN (get_frame_size (), alignment); - - info_ptr->pretend_size = cfun->pretend_args_size; - - /* Work out the size of the frame, excluding the header. Both the frame - body and register parameter area will be dword-aligned. */ - info_ptr->total_size - = (ADDR_ALIGN (info_ptr->parameter_size - + info_ptr->regs_size - + info_ptr->vars_size, - 2 * UNITS_PER_WORD) - + ADDR_ALIGN (info_ptr->pretend_size - + info_ptr->stdarg_size, - 2 * UNITS_PER_WORD)); - - /* See if we need to create a frame at all, if so add header area. */ - if (info_ptr->total_size > 0 - || info_ptr->regs[STACK_REGS_LR].size_1word > 0 - || info_ptr->regs[STACK_REGS_STRUCT].size_1word > 0) - { - offset = info_ptr->parameter_size; - info_ptr->header_size = 4 * UNITS_PER_WORD; - info_ptr->total_size += 4 * UNITS_PER_WORD; - - /* Calculate the offsets to save normal register pairs */ - for (range = 0; range < STACK_REGS_MAX; range++) - { - frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]); - if (! reg_ptr->special_p) - { - int first = reg_ptr->first; - int last = reg_ptr->last; - int regno; - - for (regno = first; regno <= last; regno++) - if (info_ptr->save_p[regno] == REG_SAVE_2WORDS - && regno != FRAME_POINTER_REGNUM - && (regno < FIRST_ARG_REGNUM - || regno > LAST_ARG_REGNUM)) - { - info_ptr->reg_offset[regno] = offset; - offset += 2 * UNITS_PER_WORD; - } - } - } - - /* Calculate the offsets to save normal single registers */ - for (range = 0; range < STACK_REGS_MAX; range++) - { - frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]); - if (! reg_ptr->special_p) - { - int first = reg_ptr->first; - int last = reg_ptr->last; - int regno; - - for (regno = first; regno <= last; regno++) - if (info_ptr->save_p[regno] == REG_SAVE_1WORD - && regno != FRAME_POINTER_REGNUM - && (regno < FIRST_ARG_REGNUM - || regno > LAST_ARG_REGNUM)) - { - info_ptr->reg_offset[regno] = offset; - offset += UNITS_PER_WORD; - } - } - } - - /* Calculate the offset to save the local variables at. */ - offset = ADDR_ALIGN (offset, alignment); - if (info_ptr->vars_size) - { - info_ptr->vars_offset = offset; - offset += info_ptr->vars_size; - } - - /* Align header to a dword-boundary. */ - offset = ADDR_ALIGN (offset, 2 * UNITS_PER_WORD); - - /* Calculate the offsets in the fixed frame. */ - info_ptr->save_p[FRAME_POINTER_REGNUM] = REG_SAVE_1WORD; - info_ptr->reg_offset[FRAME_POINTER_REGNUM] = offset; - info_ptr->regs[STACK_REGS_FP].size_1word = UNITS_PER_WORD; - - info_ptr->save_p[LR_REGNO] = REG_SAVE_1WORD; - info_ptr->reg_offset[LR_REGNO] = offset + 2*UNITS_PER_WORD; - info_ptr->regs[STACK_REGS_LR].size_1word = UNITS_PER_WORD; - - if (cfun->returns_struct) - { - info_ptr->save_p[STRUCT_VALUE_REGNUM] = REG_SAVE_1WORD; - info_ptr->reg_offset[STRUCT_VALUE_REGNUM] = offset + UNITS_PER_WORD; - info_ptr->regs[STACK_REGS_STRUCT].size_1word = UNITS_PER_WORD; - } - - /* Calculate the offsets to store the arguments passed in registers - for stdarg functions. The register pairs are first and the single - register if any is last. The register save area starts on a - dword-boundary. */ - if (info_ptr->stdarg_size) - { - int first = info_ptr->regs[STACK_REGS_STDARG].first; - int last = info_ptr->regs[STACK_REGS_STDARG].last; - int regno; - - /* Skip the header. */ - offset += 4 * UNITS_PER_WORD; - for (regno = first; regno <= last; regno++) - { - if (info_ptr->save_p[regno] == REG_SAVE_2WORDS) - { - info_ptr->reg_offset[regno] = offset; - offset += 2 * UNITS_PER_WORD; - } - else if (info_ptr->save_p[regno] == REG_SAVE_1WORD) - { - info_ptr->reg_offset[regno] = offset; - offset += UNITS_PER_WORD; - } - } - } - } - - if (reload_completed) - frv_stack_cache = info_ptr; - - return info_ptr; -} - - -/* Print the information about the frv stack offsets, etc. when debugging. */ - -void -frv_debug_stack (info) - frv_stack_t *info; -{ - int range; - - if (!info) - info = frv_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, "\ttotal_size\t= %6d\n", info->total_size); - fprintf (stderr, "\tvars_size\t= %6d\n", info->vars_size); - fprintf (stderr, "\tparam_size\t= %6d\n", info->parameter_size); - fprintf (stderr, "\tregs_size\t= %6d, 1w = %3d, 2w = %3d\n", - info->regs_size, info->regs_size_1word, info->regs_size_2words); - - fprintf (stderr, "\theader_size\t= %6d\n", info->header_size); - fprintf (stderr, "\tpretend_size\t= %6d\n", info->pretend_size); - fprintf (stderr, "\tvars_offset\t= %6d\n", info->vars_offset); - fprintf (stderr, "\tregs_offset\t= %6d\n", info->regs_offset); - - for (range = 0; range < STACK_REGS_MAX; range++) - { - frv_stack_regs_t *regs = &(info->regs[range]); - if ((regs->size_1word + regs->size_2words) > 0) - { - int first = regs->first; - int last = regs->last; - int regno; - - fprintf (stderr, "\t%s\tsize\t= %6d, 1w = %3d, 2w = %3d, save =", - regs->name, regs->size_1word + regs->size_2words, - regs->size_1word, regs->size_2words); - - for (regno = first; regno <= last; regno++) - { - if (info->save_p[regno] == REG_SAVE_1WORD) - fprintf (stderr, " %s (%d)", reg_names[regno], - info->reg_offset[regno]); - - else if (info->save_p[regno] == REG_SAVE_2WORDS) - fprintf (stderr, " %s-%s (%d)", reg_names[regno], - reg_names[regno+1], info->reg_offset[regno]); - } - - fputc ('\n', stderr); - } - } - - fflush (stderr); -} - - - - -/* The following variable value is TRUE if the next output insn should - finish cpu cycle. In order words the insn will have packing bit - (which means absence of asm code suffix `.p' on assembler. */ - -static int frv_insn_packing_flag; - -/* True if the current function contains a far jump. */ - -static int -frv_function_contains_far_jump () -{ - rtx insn = get_insns (); - while (insn != NULL - && !(GET_CODE (insn) == JUMP_INSN - /* Ignore tablejump patterns. */ - && GET_CODE (PATTERN (insn)) != ADDR_VEC - && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC - && get_attr_far_jump (insn) == FAR_JUMP_YES)) - insn = NEXT_INSN (insn); - return (insn != NULL); -} - -/* For the FRV, this function makes sure that a function with far jumps - will return correctly. It also does the VLIW packing. */ - -static void -frv_function_prologue (file, size) - FILE *file; - HOST_WIDE_INT size ATTRIBUTE_UNUSED; -{ - /* If no frame was created, check whether the function uses a call - instruction to implement a far jump. If so, save the link in gr3 and - replace all returns to LR with returns to GR3. GR3 is used because it - is call-clobbered, because is not available to the register allocator, - and because all functions that take a hidden argument pointer will have - a stack frame. */ - if (frv_stack_info ()->total_size == 0 && frv_function_contains_far_jump ()) - { - rtx insn; - - /* Just to check that the above comment is true. */ - if (regs_ever_live[GPR_FIRST + 3]) - abort (); - - /* Generate the instruction that saves the link register. */ - fprintf (file, "\tmovsg lr,gr3\n"); - - /* Replace the LR with GR3 in *return_internal patterns. The insn - will now return using jmpl @(gr3,0) rather than bralr. We cannot - simply emit a different assembly directive because bralr and jmpl - execute in different units. */ - for (insn = get_insns(); insn != NULL; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == JUMP_INSN) - { - rtx pattern = PATTERN (insn); - if (GET_CODE (pattern) == PARALLEL - && XVECLEN (pattern, 0) >= 2 - && GET_CODE (XVECEXP (pattern, 0, 0)) == RETURN - && GET_CODE (XVECEXP (pattern, 0, 1)) == USE) - { - rtx address = XEXP (XVECEXP (pattern, 0, 1), 0); - if (GET_CODE (address) == REG && REGNO (address) == LR_REGNO) - REGNO (address) = GPR_FIRST + 3; - } - } - } - - frv_pack_insns (); - frv_insn_packing_flag = TRUE; -} - - -/* Return the next available temporary register in a given class. */ - -static rtx -frv_alloc_temp_reg (info, class, mode, mark_as_used, no_abort) - frv_tmp_reg_t *info; /* which registers are available */ - enum reg_class class; /* register class desired */ - enum machine_mode mode; /* mode to allocate register with */ - int mark_as_used; /* register not available after allocation */ - int no_abort; /* return NULL instead of aborting */ -{ - int regno = info->next_reg[ (int)class ]; - int orig_regno = regno; - HARD_REG_SET *reg_in_class = ®_class_contents[ (int)class ]; - int i, nr; - - for (;;) - { - if (TEST_HARD_REG_BIT (*reg_in_class, regno) - && TEST_HARD_REG_BIT (info->regs, regno)) - break; - - if (++regno >= FIRST_PSEUDO_REGISTER) - regno = 0; - if (regno == orig_regno) - { - if (no_abort) - return NULL_RTX; - else - abort (); - } - } - - nr = HARD_REGNO_NREGS (regno, mode); - info->next_reg[ (int)class ] = regno + nr; - - if (mark_as_used) - for (i = 0; i < nr; i++) - CLEAR_HARD_REG_BIT (info->regs, regno+i); - - return gen_rtx_REG (mode, regno); -} - - -/* Return an rtx with the value OFFSET, which will either be a register or a - signed 12-bit integer. It can be used as the second operand in an "add" - instruction, or as the index in a load or store. - - The function returns a constant rtx if OFFSET is small enough, otherwise - it loads the constant into register OFFSET_REGNO and returns that. */ -static rtx -frv_frame_offset_rtx (offset) - int offset; -{ - rtx offset_rtx = GEN_INT (offset); - if (IN_RANGE_P (offset, -2048, 2047)) - return offset_rtx; - else - { - rtx reg_rtx = gen_rtx_REG (SImode, OFFSET_REGNO); - if (IN_RANGE_P (offset, -32768, 32767)) - emit_insn (gen_movsi (reg_rtx, offset_rtx)); - else - { - emit_insn (gen_movsi_high (reg_rtx, offset_rtx)); - emit_insn (gen_movsi_lo_sum (reg_rtx, offset_rtx)); - } - return reg_rtx; - } -} - -/* Generate (mem:MODE (plus:Pmode BASE (frv_frame_offset OFFSET)))). The - prologue and epilogue uses such expressions to access the stack. */ -static rtx -frv_frame_mem (mode, base, offset) - enum machine_mode mode; - rtx base; - int offset; -{ - return gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode, - base, - frv_frame_offset_rtx (offset))); -} - -/* Generate a frame-related expression: - - (set REG (mem (plus (sp) (const_int OFFSET)))). - - Such expressions are used in FRAME_RELATED_EXPR notes for more complex - instructions. Marking the expressions as frame-related is superfluous if - the note contains just a single set. But if the note contains a PARALLEL - or SEQUENCE that has several sets, each set must be individually marked - as frame-related. */ -static rtx -frv_dwarf_store (reg, offset) - rtx reg; - int offset; -{ - rtx set = gen_rtx_SET (VOIDmode, - gen_rtx_MEM (GET_MODE (reg), - plus_constant (stack_pointer_rtx, - offset)), - reg); - RTX_FRAME_RELATED_P (set) = 1; - return set; -} - -/* Emit a frame-related instruction whose pattern is PATTERN. The - instruction is the last in a sequence that cumulatively performs the - operation described by DWARF_PATTERN. The instruction is marked as - frame-related and has a REG_FRAME_RELATED_EXPR note containing - DWARF_PATTERN. */ -static void -frv_frame_insn (pattern, dwarf_pattern) - rtx pattern; - rtx dwarf_pattern; -{ - rtx insn = emit_insn (pattern); - RTX_FRAME_RELATED_P (insn) = 1; - REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, - dwarf_pattern, - REG_NOTES (insn)); -} - -/* Emit instructions that transfer REG to or from the memory location (sp + - STACK_OFFSET). The register is stored in memory if ACCESSOR->OP is - FRV_STORE and loaded if it is FRV_LOAD. Only the prologue uses this - function to store registers and only the epilogue uses it to load them. - - The caller sets up ACCESSOR so that BASE is equal to (sp + BASE_OFFSET). - The generated instruction will use BASE as its base register. BASE may - simply be the stack pointer, but if several accesses are being made to a - region far away from the stack pointer, it may be more efficient to set - up a temporary instead. - - Store instructions will be frame-related and will be annotated with the - overall effect of the store. Load instructions will be followed by a - (use) to prevent later optimizations from zapping them. - - The function takes care of the moves to and from SPRs, using TEMP_REGNO - as a temporary in such cases. */ -static void -frv_frame_access (accessor, reg, stack_offset) - frv_frame_accessor_t *accessor; - rtx reg; - int stack_offset; -{ - enum machine_mode mode = GET_MODE (reg); - rtx mem = frv_frame_mem (mode, - accessor->base, - stack_offset - accessor->base_offset); - - if (accessor->op == FRV_LOAD) - { - if (SPR_P (REGNO (reg))) - { - rtx temp = gen_rtx_REG (mode, TEMP_REGNO); - emit_insn (gen_rtx_SET (VOIDmode, temp, mem)); - emit_insn (gen_rtx_SET (VOIDmode, reg, temp)); - } - else - emit_insn (gen_rtx_SET (VOIDmode, reg, mem)); - emit_insn (gen_rtx_USE (VOIDmode, reg)); - } - else - { - if (SPR_P (REGNO (reg))) - { - rtx temp = gen_rtx_REG (mode, TEMP_REGNO); - emit_insn (gen_rtx_SET (VOIDmode, temp, reg)); - frv_frame_insn (gen_rtx_SET (Pmode, mem, temp), - frv_dwarf_store (reg, stack_offset)); - } - else if (GET_MODE (reg) == DImode) - { - /* For DImode saves, the dwarf2 version needs to be a SEQUENCE - with a separate save for each register. */ - rtx reg1 = gen_rtx_REG (SImode, REGNO (reg)); - rtx reg2 = gen_rtx_REG (SImode, REGNO (reg) + 1); - rtx set1 = frv_dwarf_store (reg1, stack_offset); - rtx set2 = frv_dwarf_store (reg2, stack_offset + 4); - frv_frame_insn (gen_rtx_SET (Pmode, mem, reg), - gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (2, set1, set2))); - } - else - frv_frame_insn (gen_rtx_SET (Pmode, mem, reg), - frv_dwarf_store (reg, stack_offset)); - } -} - -/* A function that uses frv_frame_access to transfer a group of registers to - or from the stack. ACCESSOR is passed directly to frv_frame_access, INFO - is the stack information generated by frv_stack_info, and REG_SET is the - number of the register set to transfer. */ -static void -frv_frame_access_multi (accessor, info, reg_set) - frv_frame_accessor_t *accessor; - frv_stack_t *info; - int reg_set; -{ - frv_stack_regs_t *regs_info; - int regno; - - regs_info = &info->regs[reg_set]; - for (regno = regs_info->first; regno <= regs_info->last; regno++) - if (info->save_p[regno]) - frv_frame_access (accessor, - info->save_p[regno] == REG_SAVE_2WORDS - ? gen_rtx_REG (DImode, regno) - : gen_rtx_REG (SImode, regno), - info->reg_offset[regno]); -} - -/* Save or restore callee-saved registers that are kept outside the frame - header. The function saves the registers if OP is FRV_STORE and restores - them if OP is FRV_LOAD. INFO is the stack information generated by - frv_stack_info. */ -static void -frv_frame_access_standard_regs (op, info) - enum frv_stack_op op; - frv_stack_t *info; -{ - frv_frame_accessor_t accessor; - - accessor.op = op; - accessor.base = stack_pointer_rtx; - accessor.base_offset = 0; - frv_frame_access_multi (&accessor, info, STACK_REGS_GPR); - frv_frame_access_multi (&accessor, info, STACK_REGS_FPR); - frv_frame_access_multi (&accessor, info, STACK_REGS_LCR); -} - - -/* 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. - - Also any insns generated here should have RTX_FRAME_RELATED_P(insn) = 1 - so that the debug info generation code can handle them properly. */ -void -frv_expand_prologue () -{ - frv_stack_t *info = frv_stack_info (); - rtx sp = stack_pointer_rtx; - rtx fp = frame_pointer_rtx; - frv_frame_accessor_t accessor; - - if (TARGET_DEBUG_STACK) - frv_debug_stack (info); - - if (info->total_size == 0) - return; - - /* We're interested in three areas of the frame here: - - A: the register save area - B: the old FP - C: the header after B - - If the frame pointer isn't used, we'll have to set up A, B and C - using the stack pointer. If the frame pointer is used, we'll access - them as follows: - - A: set up using sp - B: set up using sp or a temporary (see below) - C: set up using fp - - We set up B using the stack pointer if the frame is small enough. - Otherwise, it's more efficient to copy the old stack pointer into a - temporary and use that. - - Note that it's important to make sure the prologue and epilogue use the - same registers to access A and C, since doing otherwise will confuse - the aliasing code. */ - - /* Set up ACCESSOR for accessing region B above. If the frame pointer - isn't used, the same method will serve for C. */ - accessor.op = FRV_STORE; - if (frame_pointer_needed && info->total_size > 2048) - { - rtx insn; - - accessor.base = gen_rtx_REG (Pmode, OLD_SP_REGNO); - accessor.base_offset = info->total_size; - insn = emit_insn (gen_movsi (accessor.base, sp)); - } - else - { - accessor.base = stack_pointer_rtx; - accessor.base_offset = 0; - } - - /* Allocate the stack space. */ - { - rtx asm_offset = frv_frame_offset_rtx (-info->total_size); - rtx dwarf_offset = GEN_INT (-info->total_size); - - frv_frame_insn (gen_stack_adjust (sp, sp, asm_offset), - gen_rtx_SET (Pmode, - sp, - gen_rtx_PLUS (Pmode, sp, dwarf_offset))); - } - - /* If the frame pointer is needed, store the old one at (sp + FP_OFFSET) - and point the new one to that location. */ - if (frame_pointer_needed) - { - int fp_offset = info->reg_offset[FRAME_POINTER_REGNUM]; - - /* ASM_SRC and DWARF_SRC both point to the frame header. ASM_SRC is - based on ACCESSOR.BASE but DWARF_SRC is always based on the stack - pointer. */ - rtx asm_src = plus_constant (accessor.base, - fp_offset - accessor.base_offset); - rtx dwarf_src = plus_constant (sp, fp_offset); - - /* Store the old frame pointer at (sp + FP_OFFSET). */ - frv_frame_access (&accessor, fp, fp_offset); - - /* Set up the new frame pointer. */ - frv_frame_insn (gen_rtx_SET (VOIDmode, fp, asm_src), - gen_rtx_SET (VOIDmode, fp, dwarf_src)); - - /* Access region C from the frame pointer. */ - accessor.base = fp; - accessor.base_offset = fp_offset; - } - - /* Set up region C. */ - frv_frame_access_multi (&accessor, info, STACK_REGS_STRUCT); - frv_frame_access_multi (&accessor, info, STACK_REGS_LR); - frv_frame_access_multi (&accessor, info, STACK_REGS_STDARG); - - /* Set up region A. */ - frv_frame_access_standard_regs (FRV_STORE, info); - - /* If this is a varargs/stdarg function, issue a blockage to prevent the - scheduler from moving loads before the stores saving the registers. */ - if (info->stdarg_size > 0) - emit_insn (gen_blockage ()); - - /* Set up pic register/small data register for this function. */ - if (flag_pic && cfun->uses_pic_offset_table) - emit_insn (gen_pic_prologue (gen_rtx_REG (Pmode, PIC_REGNO), - gen_rtx_REG (Pmode, LR_REGNO), - gen_rtx_REG (SImode, OFFSET_REGNO))); -} - - -/* Under frv, all of the work is done via frv_expand_epilogue, but - this function provides a convient place to do cleanup. */ - -static void -frv_function_epilogue (file, size) - FILE *file ATTRIBUTE_UNUSED; - HOST_WIDE_INT size ATTRIBUTE_UNUSED; -{ - frv_stack_cache = (frv_stack_t *)0; - - /* zap last used registers for conditional execution. */ - memset ((PTR) &frv_ifcvt.tmp_reg, 0, sizeof (frv_ifcvt.tmp_reg)); - - /* release the bitmap of created insns. */ - BITMAP_XFREE (frv_ifcvt.scratch_insns_bitmap); -} - - -/* 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. - - If SIBCALL_P is true, the final branch back to the calling function is - omitted, and is used for sibling call (aka tail call) sites. For sibcalls, - we must not clobber any arguments used for parameter passing or any stack - slots for arguments passed to the current function. */ - -void -frv_expand_epilogue (sibcall_p) - int sibcall_p; -{ - frv_stack_t *info = frv_stack_info (); - rtx fp = frame_pointer_rtx; - rtx sp = stack_pointer_rtx; - rtx return_addr; - int fp_offset; - - fp_offset = info->reg_offset[FRAME_POINTER_REGNUM]; - - /* Restore the stack pointer to its original value if alloca or the like - is used. */ - if (! current_function_sp_is_unchanging) - emit_insn (gen_addsi3 (sp, fp, frv_frame_offset_rtx (-fp_offset))); - - /* Restore the callee-saved registers that were used in this function. */ - frv_frame_access_standard_regs (FRV_LOAD, info); - - /* Set RETURN_ADDR to the address we should return to. Set it to NULL if - no return instruction should be emitted. */ - if (sibcall_p) - return_addr = 0; - else if (info->save_p[LR_REGNO]) - { - int lr_offset; - rtx mem; - - /* Use the same method to access the link register's slot as we did in - the prologue. In other words, use the frame pointer if available, - otherwise use the stack pointer. - - LR_OFFSET is the offset of the link register's slot from the start - of the frame and MEM is a memory rtx for it. */ - lr_offset = info->reg_offset[LR_REGNO]; - if (frame_pointer_needed) - mem = frv_frame_mem (Pmode, fp, lr_offset - fp_offset); - else - mem = frv_frame_mem (Pmode, sp, lr_offset); - - /* Load the old link register into a GPR. */ - return_addr = gen_rtx_REG (Pmode, TEMP_REGNO); - emit_insn (gen_rtx_SET (VOIDmode, return_addr, mem)); - } - else - return_addr = gen_rtx_REG (Pmode, LR_REGNO); - - /* Restore the old frame pointer. Emit a USE afterwards to make sure - the load is preserved. */ - if (frame_pointer_needed) - { - emit_insn (gen_rtx_SET (VOIDmode, fp, gen_rtx_MEM (Pmode, fp))); - emit_insn (gen_rtx_USE (VOIDmode, fp)); - } - - /* Deallocate the stack frame. */ - if (info->total_size != 0) - { - rtx offset = frv_frame_offset_rtx (info->total_size); - emit_insn (gen_stack_adjust (sp, sp, offset)); - } - - /* If this function uses eh_return, add the final stack adjustment now. */ - if (current_function_calls_eh_return) - emit_insn (gen_stack_adjust (sp, sp, EH_RETURN_STACKADJ_RTX)); - - if (return_addr) - emit_jump_insn (gen_epilogue_return (return_addr)); -} - - -/* 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. */ - -void -frv_asm_output_mi_thunk (file, thunk_fndecl, delta, function) - FILE *file; - tree thunk_fndecl ATTRIBUTE_UNUSED; - long delta; - tree function; -{ - const char *name_func = XSTR (XEXP (DECL_RTL (function), 0), 0); - const char *name_arg0 = reg_names[FIRST_ARG_REGNUM]; - const char *name_jmp = reg_names[JUMP_REGNO]; - const char *parallel = ((PACKING_FLAG_USED_P ()) ? ".p" : ""); - - /* Do the add using an addi if possible */ - if (IN_RANGE_P (delta, -2048, 2047)) - fprintf (file, "\taddi %s,#%ld,%s\n", name_arg0, delta, name_arg0); - else - { - const char *name_add = reg_names[TEMP_REGNO]; - fprintf (file, "\tsethi%s #hi(%ld),%s\n", parallel, delta, name_add); - fprintf (file, "\tsetlo #lo(%ld),%s\n", delta, name_add); - fprintf (file, "\tadd %s,%s,%s\n", name_add, name_arg0, name_arg0); - } - - if (!flag_pic) - { - fprintf (file, "\tsethi%s #hi(", parallel); - assemble_name (file, name_func); - fprintf (file, "),%s\n", name_jmp); - - fprintf (file, "\tsetlo #lo("); - assemble_name (file, name_func); - fprintf (file, "),%s\n", name_jmp); - } - else - { - /* Use JUMP_REGNO as a temporary PIC register. */ - const char *name_lr = reg_names[LR_REGNO]; - const char *name_gppic = name_jmp; - const char *name_tmp = reg_names[TEMP_REGNO]; - - fprintf (file, "\tmovsg %s,%s\n", name_lr, name_tmp); - fprintf (file, "\tcall 1f\n"); - fprintf (file, "1:\tmovsg %s,%s\n", name_lr, name_gppic); - fprintf (file, "\tmovgs %s,%s\n", name_tmp, name_lr); - fprintf (file, "\tsethi%s #gprelhi(1b),%s\n", parallel, name_tmp); - fprintf (file, "\tsetlo #gprello(1b),%s\n", name_tmp); - fprintf (file, "\tsub %s,%s,%s\n", name_gppic, name_tmp, name_gppic); - - fprintf (file, "\tsethi%s #gprelhi(", parallel); - assemble_name (file, name_func); - fprintf (file, "),%s\n", name_tmp); - - fprintf (file, "\tsetlo #gprello("); - assemble_name (file, name_func); - fprintf (file, "),%s\n", name_tmp); - - fprintf (file, "\tadd %s,%s,%s\n", name_gppic, name_tmp, name_jmp); - } - - /* Jump to the function address */ - fprintf (file, "\tjmpl @(%s,%s)\n", name_jmp, reg_names[GPR_FIRST+0]); -} - - -/* 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. */ - -/* On frv, create a frame whenever we need to create stack */ - -int -frv_frame_pointer_required () -{ - if (! current_function_is_leaf) - return TRUE; - - if (get_frame_size () != 0) - return TRUE; - - if (cfun->stdarg) - return TRUE; - - if (!current_function_sp_is_unchanging) - return TRUE; - - if (flag_pic && cfun->uses_pic_offset_table) - return TRUE; - - if (profile_flag) - return TRUE; - - if (cfun->machine->frame_needed) - return TRUE; - - return FALSE; -} - - -/* 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. */ - -/* See frv_stack_info for more details on the frv stack frame. */ - -int -frv_initial_elimination_offset (from, to) - int from; - int to; -{ - frv_stack_t *info = frv_stack_info (); - int ret = 0; - - if (to == STACK_POINTER_REGNUM && from == ARG_POINTER_REGNUM) - ret = info->total_size - info->pretend_size; - - else if (to == STACK_POINTER_REGNUM && from == FRAME_POINTER_REGNUM) - ret = - info->reg_offset[FRAME_POINTER_REGNUM]; - - else if (to == FRAME_POINTER_REGNUM && from == ARG_POINTER_REGNUM) - ret = (info->total_size - - info->reg_offset[FRAME_POINTER_REGNUM] - - info->pretend_size); - - else - abort (); - - if (TARGET_DEBUG_STACK) - fprintf (stderr, "Eliminate %s to %s by adding %d\n", - reg_names [from], reg_names[to], ret); - - return ret; -} - - -/* 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 -frv_setup_incoming_varargs (cum, mode, type, pretend_size, second_time) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type ATTRIBUTE_UNUSED; - int *pretend_size; - int second_time; -{ - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "setup_vararg: words = %2d, mode = %4s, pretend_size = %d, second_time = %d\n", - *cum, GET_MODE_NAME (mode), *pretend_size, second_time); -} - - -/* If defined, is a C expression that produces the machine-specific code for a - call to `__builtin_saveregs'. This code will be moved to the very beginning - of the function, before any parameter access are made. The return value of - this function should be an RTX that contains the value to use as the return - of `__builtin_saveregs'. - - If this macro is not defined, the compiler will output an ordinary call to - the library function `__builtin_saveregs'. */ - -rtx -frv_expand_builtin_saveregs () -{ - int offset = UNITS_PER_WORD * FRV_NUM_ARG_REGS; - - 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)); -} - - -/* Expand __builtin_va_start to do the va_start macro. */ - -void -frv_expand_builtin_va_start (valist, nextarg) - tree valist; - rtx nextarg; -{ - tree t; - int num = cfun->args_info - FIRST_ARG_REGNUM - FRV_NUM_ARG_REGS; - - nextarg = gen_rtx_PLUS (Pmode, virtual_incoming_args_rtx, - GEN_INT (UNITS_PER_WORD * num)); - - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "va_start: args_info = %d, num = %d\n", - cfun->args_info, num); - - debug_rtx (nextarg); - } - - t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, - make_tree (ptr_type_node, nextarg)); - TREE_SIDE_EFFECTS (t) = 1; - - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); -} - - -/* Expand __builtin_va_arg to do the va_arg macro. */ - -rtx -frv_expand_builtin_va_arg(valist, type) - tree valist; - tree type; -{ - rtx addr; - rtx mem; - rtx reg; - - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "va_arg:\n"); - debug_tree (type); - } - - if (! AGGREGATE_TYPE_P (type)) - return std_expand_builtin_va_arg (valist, type); - - addr = std_expand_builtin_va_arg (valist, ptr_type_node); - mem = gen_rtx_MEM (Pmode, addr); - reg = gen_reg_rtx (Pmode); - - set_mem_alias_set (mem, get_varargs_alias_set ()); - emit_move_insn (reg, mem); - - return reg; -} - - -/* Expand a block move operation, and return 1 if successful. Return 0 - if we should let the compiler generate normal code. - - operands[0] is the destination - operands[1] is the source - operands[2] is the length - operands[3] is the alignment */ - -/* Maximum number of loads to do before doing the stores */ -#ifndef MAX_MOVE_REG -#define MAX_MOVE_REG 4 -#endif - -/* Maximum number of total loads to do. */ -#ifndef TOTAL_MOVE_REG -#define TOTAL_MOVE_REG 8 -#endif - -int -frv_expand_block_move (operands) - rtx operands[]; -{ - rtx orig_dest = operands[0]; - rtx orig_src = operands[1]; - rtx bytes_rtx = operands[2]; - rtx align_rtx = operands[3]; - int constp = (GET_CODE (bytes_rtx) == CONST_INT); - int align; - int bytes; - int offset; - int num_reg; - int i; - rtx src_reg; - rtx dest_reg; - rtx src_addr; - rtx dest_addr; - rtx src_mem; - rtx dest_mem; - rtx tmp_reg; - rtx stores[MAX_MOVE_REG]; - int move_bytes; - enum machine_mode mode; - - /* If this is not a fixed size move, just call memcpy */ - if (! constp) - return FALSE; - - /* If this is not a fixed size alignment, abort */ - if (GET_CODE (align_rtx) != CONST_INT) - abort (); - - align = INTVAL (align_rtx); - - /* Anything to move? */ - bytes = INTVAL (bytes_rtx); - if (bytes <= 0) - return TRUE; - - /* Don't support real large moves. */ - if (bytes > TOTAL_MOVE_REG*align) - return FALSE; - - /* Move the address into scratch registers. */ - dest_reg = copy_addr_to_reg (XEXP (orig_dest, 0)); - src_reg = copy_addr_to_reg (XEXP (orig_src, 0)); - - num_reg = offset = 0; - for ( ; bytes > 0; (bytes -= move_bytes), (offset += move_bytes)) - { - /* Calculate the correct offset for src/dest */ - if (offset == 0) - { - src_addr = src_reg; - dest_addr = dest_reg; - } - else - { - src_addr = plus_constant (src_reg, offset); - dest_addr = plus_constant (dest_reg, offset); - } - - /* Generate the appropriate load and store, saving the stores - for later. */ - if (bytes >= 4 && align >= 4) - mode = SImode; - else if (bytes >= 2 && align >= 2) - mode = HImode; - else - mode = QImode; - - move_bytes = GET_MODE_SIZE (mode); - tmp_reg = gen_reg_rtx (mode); - src_mem = change_address (orig_src, mode, src_addr); - dest_mem = change_address (orig_dest, mode, dest_addr); - emit_insn (gen_rtx_SET (VOIDmode, tmp_reg, src_mem)); - stores[num_reg++] = gen_rtx_SET (VOIDmode, dest_mem, tmp_reg); - - if (num_reg >= MAX_MOVE_REG) - { - for (i = 0; i < num_reg; i++) - emit_insn (stores[i]); - num_reg = 0; - } - } - - for (i = 0; i < num_reg; i++) - emit_insn (stores[i]); - - return TRUE; -} - - -/* Expand a block clear operation, and return 1 if successful. Return 0 - if we should let the compiler generate normal code. - - operands[0] is the destination - operands[1] is the length - operands[2] is the alignment */ - -int -frv_expand_block_clear (operands) - rtx operands[]; -{ - rtx orig_dest = operands[0]; - rtx bytes_rtx = operands[1]; - rtx align_rtx = operands[2]; - int constp = (GET_CODE (bytes_rtx) == CONST_INT); - int align; - int bytes; - int offset; - int num_reg; - rtx dest_reg; - rtx dest_addr; - rtx dest_mem; - int clear_bytes; - enum machine_mode mode; - - /* If this is not a fixed size move, just call memcpy */ - if (! constp) - return FALSE; - - /* If this is not a fixed size alignment, abort */ - if (GET_CODE (align_rtx) != CONST_INT) - abort (); - - align = INTVAL (align_rtx); - - /* Anything to move? */ - bytes = INTVAL (bytes_rtx); - if (bytes <= 0) - return TRUE; - - /* Don't support real large clears. */ - if (bytes > TOTAL_MOVE_REG*align) - return FALSE; - - /* Move the address into a scratch register. */ - dest_reg = copy_addr_to_reg (XEXP (orig_dest, 0)); - - num_reg = offset = 0; - for ( ; bytes > 0; (bytes -= clear_bytes), (offset += clear_bytes)) - { - /* Calculate the correct offset for src/dest */ - dest_addr = ((offset == 0) - ? dest_reg - : plus_constant (dest_reg, offset)); - - /* Generate the appropriate store of gr0 */ - if (bytes >= 4 && align >= 4) - mode = SImode; - else if (bytes >= 2 && align >= 2) - mode = HImode; - else - mode = QImode; - - clear_bytes = GET_MODE_SIZE (mode); - dest_mem = change_address (orig_dest, mode, dest_addr); - emit_insn (gen_rtx_SET (VOIDmode, dest_mem, const0_rtx)); - } - - return TRUE; -} - - -/* The following variable is used to output modifiers of assembler - code of the current output insn.. */ - -static rtx *frv_insn_operands; - -/* The following function is used to add assembler insn code suffix .p - if it is necessary. */ - -const char * -frv_asm_output_opcode (f, ptr) - FILE *f; - const char *ptr; -{ - int c; - - if (! PACKING_FLAG_USED_P()) - return ptr; - - for (; *ptr && *ptr != ' ' && *ptr != '\t';) - { - c = *ptr++; - if (c == '%' && ((*ptr >= 'a' && *ptr <= 'z') - || (*ptr >= 'A' && *ptr <= 'Z'))) - { - int letter = *ptr++; - - c = atoi (ptr); - frv_print_operand (f, frv_insn_operands [c], letter); - while ((c = *ptr) >= '0' && c <= '9') - ptr++; - } - else - fputc (c, f); - } - - if (!frv_insn_packing_flag) - fprintf (f, ".p"); - - return ptr; -} - -/* The following function sets up the packing bit for the current - output insn. Remember that the function is not called for asm - insns. */ - -void -frv_final_prescan_insn (insn, opvec, noperands) - rtx insn; - rtx *opvec; - int noperands ATTRIBUTE_UNUSED; -{ - if (! PACKING_FLAG_USED_P()) - return; - - if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') - return; - - frv_insn_operands = opvec; - - /* Look for the next printable instruction. frv_pack_insns () has set - things up so that any printable instruction will have TImode if it - starts a new packet and VOIDmode if it should be packed with the - previous instruction. - - Printable instructions will be asm_operands or match one of the .md - patterns. Since asm instructions cannot be packed -- and will - therefore have TImode -- this loop terminates on any recognisable - instruction, and on any unrecognisable instruction with TImode. */ - for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn)) - { - if (NOTE_P (insn)) - continue; - else if (!INSN_P (insn)) - break; - else if (GET_MODE (insn) == TImode || INSN_CODE (insn) != -1) - break; - } - - /* Set frv_insn_packing_flag to FALSE if the next instruction should - be packed with this one. Set it to TRUE otherwise. If the next - instruction is an asm insntruction, this statement will set the - flag to TRUE, and that value will still hold when the asm operands - themselves are printed. */ - frv_insn_packing_flag = ! (insn && INSN_P (insn) - && GET_MODE (insn) != TImode); -} - - - -/* 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. */ - -/* The default is correct, but we need to make sure the frame gets created. */ -rtx -frv_dynamic_chain_address (frame) - rtx frame; -{ - cfun->machine->frame_needed = 1; - return frame; -} - - -/* 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. */ - -rtx -frv_return_addr_rtx (count, frame) - int count ATTRIBUTE_UNUSED; - rtx frame; -{ - cfun->machine->frame_needed = 1; - return gen_rtx_MEM (Pmode, plus_constant (frame, 8)); -} - -/* Given a memory reference MEMREF, interpret the referenced memory as - an array of MODE values, and return a reference to the element - specified by INDEX. Assume that any pre-modification implicit in - MEMREF has already happened. - - MEMREF must be a legitimate operand for modes larger than SImode. - GO_IF_LEGITIMATE_ADDRESS forbids register+register addresses, which - this function cannot handle. */ -rtx -frv_index_memory (memref, mode, index) - rtx memref; - enum machine_mode mode; - int index; -{ - rtx base = XEXP (memref, 0); - if (GET_CODE (base) == PRE_MODIFY) - base = XEXP (base, 0); - return change_address (memref, mode, - plus_constant (base, index * GET_MODE_SIZE (mode))); -} - - -/* Print a memory address as an operand to reference that memory location. */ -void -frv_print_operand_address (stream, x) - FILE * stream; - rtx x; -{ - if (GET_CODE (x) == MEM) - x = XEXP (x, 0); - - switch (GET_CODE (x)) - { - case REG: - fputs (reg_names [ REGNO (x)], stream); - return; - - case CONST_INT: - fprintf (stream, "%ld", (long) INTVAL (x)); - return; - - case SYMBOL_REF: - assemble_name (stream, XSTR (x, 0)); - return; - - case LABEL_REF: - case CONST: - output_addr_const (stream, x); - return; - - default: - break; - } - - fatal_insn ("Bad insn to frv_print_operand_address:", x); -} - - -static void -frv_print_operand_memory_reference_reg (stream, x) - FILE *stream; - rtx x; -{ - int regno = true_regnum (x); - if (GPR_P (regno)) - fputs (reg_names[regno], stream); - else - fatal_insn ("Bad register to frv_print_operand_memory_reference_reg:", x); -} - -/* Print a memory reference suitable for the ld/st instructions. */ - -static void -frv_print_operand_memory_reference (stream, x, addr_offset) - FILE *stream; - rtx x; - int addr_offset; -{ - rtx x0 = NULL_RTX; - rtx x1 = NULL_RTX; - - switch (GET_CODE (x)) - { - case SUBREG: - case REG: - x0 = x; - break; - - case PRE_MODIFY: /* (pre_modify (reg) (plus (reg) (reg))) */ - x0 = XEXP (x, 0); - x1 = XEXP (XEXP (x, 1), 1); - break; - - case CONST_INT: - x1 = x; - break; - - case PLUS: - x0 = XEXP (x, 0); - x1 = XEXP (x, 1); - if (GET_CODE (x0) == CONST_INT) - { - x0 = XEXP (x, 1); - x1 = XEXP (x, 0); - } - break; - - default: - fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x); - break; - - } - - if (addr_offset) - { - if (!x1) - x1 = const0_rtx; - else if (GET_CODE (x1) != CONST_INT) - fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x); - } - - fputs ("@(", stream); - if (!x0) - fputs (reg_names[GPR_R0], stream); - else if (GET_CODE (x0) == REG || GET_CODE (x0) == SUBREG) - frv_print_operand_memory_reference_reg (stream, x0); - else - fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x); - - fputs (",", stream); - if (!x1) - fputs (reg_names [GPR_R0], stream); - - else - { - switch (GET_CODE (x1)) - { - case SUBREG: - case REG: - frv_print_operand_memory_reference_reg (stream, x1); - break; - - case CONST_INT: - fprintf (stream, "%ld", (long) (INTVAL (x1) + addr_offset)); - break; - - case SYMBOL_REF: - if (x0 && GET_CODE (x0) == REG && REGNO (x0) == SDA_BASE_REG - && symbol_ref_small_data_p (x1)) - { - fputs ("#gprel12(", stream); - assemble_name (stream, XSTR (x1, 0)); - fputs (")", stream); - } - else - fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x); - break; - - case CONST: - if (x0 && GET_CODE (x0) == REG && REGNO (x0) == SDA_BASE_REG - && const_small_data_p (x1)) - { - fputs ("#gprel12(", stream); - assemble_name (stream, XSTR (XEXP (XEXP (x1, 0), 0), 0)); - fprintf (stream, "+%d)", INTVAL (XEXP (XEXP (x1, 0), 1))); - } - else - fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x); - break; - - default: - fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x); - } - } - - fputs (")", stream); -} - - -/* Return 2 for likely branches and 0 for non-likely branches */ - -#define FRV_JUMP_LIKELY 2 -#define FRV_JUMP_NOT_LIKELY 0 - -static int -frv_print_operand_jump_hint (insn) - rtx insn; -{ - rtx note; - rtx labelref; - int ret; - HOST_WIDE_INT prob = -1; - enum { UNKNOWN, BACKWARD, FORWARD } jump_type = UNKNOWN; - - if (GET_CODE (insn) != JUMP_INSN) - abort (); - - /* Assume any non-conditional jump is likely. */ - if (! any_condjump_p (insn)) - ret = FRV_JUMP_LIKELY; - - else - { - labelref = condjump_label (insn); - if (labelref) - { - rtx label = XEXP (labelref, 0); - jump_type = (insn_current_address > INSN_ADDRESSES (INSN_UID (label)) - ? BACKWARD - : FORWARD); - } - - note = find_reg_note (insn, REG_BR_PROB, 0); - if (!note) - ret = ((jump_type == BACKWARD) ? FRV_JUMP_LIKELY : FRV_JUMP_NOT_LIKELY); - - else - { - prob = INTVAL (XEXP (note, 0)); - ret = ((prob >= (REG_BR_PROB_BASE / 2)) - ? FRV_JUMP_LIKELY - : FRV_JUMP_NOT_LIKELY); - } - } - -#if 0 - if (TARGET_DEBUG) - { - char *direction; - - switch (jump_type) - { - default: - case UNKNOWN: direction = "unknown jump direction"; break; - case BACKWARD: direction = "jump backward"; break; - case FORWARD: direction = "jump forward"; break; - } - - fprintf (stderr, - "%s: uid %ld, %s, probability = %ld, max prob. = %ld, hint = %d\n", - IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), - (long)INSN_UID (insn), direction, (long)prob, - (long)REG_BR_PROB_BASE, ret); - } -#endif - - return ret; -} - - -/* Print an operand to a assembler instruction. - - `%' followed by a letter and a digit says to output an operand in an - alternate fashion. Four letters have standard, built-in meanings described - below. The machine description macro `PRINT_OPERAND' can define additional - letters with nonstandard meanings. - - `%cDIGIT' can be used to substitute an operand that is a constant value - without the syntax that normally indicates an immediate operand. - - `%nDIGIT' is like `%cDIGIT' except that the value of the constant is negated - before printing. - - `%aDIGIT' can be used to substitute an operand as if it were a memory - reference, with the actual operand treated as the address. This may be - useful when outputting a "load address" instruction, because often the - assembler syntax for such an instruction requires you to write the operand - as if it were a memory reference. - - `%lDIGIT' is used to substitute a `label_ref' into a jump instruction. - - `%=' outputs a number which is unique to each instruction in the entire - compilation. This is useful for making local labels to be referred to more - than once in a single template that generates multiple assembler - instructions. - - `%' followed by a punctuation character specifies a substitution that does - not use an operand. Only one case is standard: `%%' outputs a `%' into the - assembler code. Other nonstandard cases can be defined in the - `PRINT_OPERAND' macro. You must also define which punctuation characters - are valid with the `PRINT_OPERAND_PUNCT_VALID_P' macro. */ - -void -frv_print_operand (file, x, code) - FILE * file; - rtx x; - int code; -{ - HOST_WIDE_INT value; - int offset; - - if (code != 0 && !isalpha (code)) - value = 0; - - else if (GET_CODE (x) == CONST_INT) - value = INTVAL (x); - - else if (GET_CODE (x) == CONST_DOUBLE) - { - if (GET_MODE (x) == SFmode) - { - REAL_VALUE_TYPE rv; - long l; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, l); - value = l; - } - - else if (GET_MODE (x) == VOIDmode) - value = CONST_DOUBLE_LOW (x); - - else - fatal_insn ("Bad insn in frv_print_operand, bad const_double", x); - } - - else - value = 0; - - switch (code) - { - - case '.': - /* Output r0 */ - fputs (reg_names[GPR_R0], file); - break; - - case '#': - fprintf (file, "%d", frv_print_operand_jump_hint (current_output_insn)); - break; - - case SDATA_FLAG_CHAR: - /* Output small data area base register (gr16). */ - fputs (reg_names[SDA_BASE_REG], file); - break; - - case '~': - /* Output pic register (gr17). */ - fputs (reg_names[PIC_REGNO], file); - break; - - case '*': - /* Output the temporary integer CCR register */ - fputs (reg_names[ICR_TEMP], file); - break; - - case '&': - /* Output the temporary integer CC register */ - fputs (reg_names[ICC_TEMP], file); - break; - - /* case 'a': print an address */ - - case 'C': - /* Print appropriate test for integer branch false operation */ - switch (GET_CODE (x)) - { - default: - fatal_insn ("Bad insn to frv_print_operand, 'C' modifier:", x); - - case EQ: fputs ("ne", file); break; - case NE: fputs ("eq", file); break; - case LT: fputs ("ge", file); break; - case LE: fputs ("gt", file); break; - case GT: fputs ("le", file); break; - case GE: fputs ("lt", file); break; - case LTU: fputs ("nc", file); break; - case LEU: fputs ("hi", file); break; - case GTU: fputs ("ls", file); break; - case GEU: fputs ("c", file); break; - } - break; - - /* case 'c': print a constant without the constant prefix. If - CONSTANT_ADDRESS_P(x) is not true, PRINT_OPERAND is called. */ - - case 'c': - /* Print appropriate test for integer branch true operation */ - switch (GET_CODE (x)) - { - default: - fatal_insn ("Bad insn to frv_print_operand, 'c' modifier:", x); - - case EQ: fputs ("eq", file); break; - case NE: fputs ("ne", file); break; - case LT: fputs ("lt", file); break; - case LE: fputs ("le", file); break; - case GT: fputs ("gt", file); break; - case GE: fputs ("ge", file); break; - case LTU: fputs ("c", file); break; - case LEU: fputs ("ls", file); break; - case GTU: fputs ("hi", file); break; - case GEU: fputs ("nc", file); break; - } - break; - - case 'e': - /* Print 1 for a NE and 0 for an EQ to give the final argument - for a conditional instruction. */ - if (GET_CODE (x) == NE) - fputs ("1", file); - - else if (GET_CODE (x) == EQ) - fputs ("0", file); - - else - fatal_insn ("Bad insn to frv_print_operand, 'e' modifier:", x); - break; - - case 'F': - /* Print appropriate test for floating point branch false operation */ - switch (GET_CODE (x)) - { - default: - fatal_insn ("Bad insn to frv_print_operand, 'F' modifier:", x); - - case EQ: fputs ("ne", file); break; - case NE: fputs ("eq", file); break; - case LT: fputs ("uge", file); break; - case LE: fputs ("ug", file); break; - case GT: fputs ("ule", file); break; - case GE: fputs ("ul", file); break; - } - break; - - case 'f': - /* Print appropriate test for floating point branch true operation */ - switch (GET_CODE (x)) - { - default: - fatal_insn ("Bad insn to frv_print_operand, 'f' modifier:", x); - - case EQ: fputs ("eq", file); break; - case NE: fputs ("ne", file); break; - case LT: fputs ("lt", file); break; - case LE: fputs ("le", file); break; - case GT: fputs ("gt", file); break; - case GE: fputs ("ge", file); break; - } - break; - - case 'I': - /* Print 'i' if the operand is a constant, or is a memory reference that - adds a constant */ - if (GET_CODE (x) == MEM) - x = ((GET_CODE (XEXP (x, 0)) == PLUS) - ? XEXP (XEXP (x, 0), 1) - : XEXP (x, 0)); - - switch (GET_CODE (x)) - { - default: - break; - - case CONST_INT: - case SYMBOL_REF: - case CONST: - fputs ("i", file); - break; - } - break; - - case 'i': - /* For jump instructions, print 'i' if the operand is a constant or - is an expression that adds a constant */ - if (GET_CODE (x) == CONST_INT) - fputs ("i", file); - - else - { - if (GET_CODE (x) == CONST_INT - || (GET_CODE (x) == PLUS - && (GET_CODE (XEXP (x, 1)) == CONST_INT - || GET_CODE (XEXP (x, 0)) == CONST_INT))) - fputs ("i", file); - } - break; - - case 'L': - /* Print the lower register of a double word register pair */ - if (GET_CODE (x) == REG) - fputs (reg_names[ REGNO (x)+1 ], file); - else - fatal_insn ("Bad insn to frv_print_operand, 'L' modifier:", x); - break; - - /* case 'l': print a LABEL_REF */ - - case 'M': - case 'N': - /* Print a memory reference for ld/st/jmp, %N prints a memory reference - for the second word of double memory operations. */ - offset = (code == 'M') ? 0 : UNITS_PER_WORD; - switch (GET_CODE (x)) - { - default: - fatal_insn ("Bad insn to frv_print_operand, 'M/N' modifier:", x); - - case MEM: - frv_print_operand_memory_reference (file, XEXP (x, 0), offset); - break; - - case REG: - case SUBREG: - case CONST_INT: - case PLUS: - case SYMBOL_REF: - frv_print_operand_memory_reference (file, x, offset); - break; - } - break; - - case 'O': - /* Print the opcode of a command. */ - switch (GET_CODE (x)) - { - default: - fatal_insn ("Bad insn to frv_print_operand, 'O' modifier:", x); - - case PLUS: fputs ("add", file); break; - case MINUS: fputs ("sub", file); break; - case AND: fputs ("and", file); break; - case IOR: fputs ("or", file); break; - case XOR: fputs ("xor", file); break; - case ASHIFT: fputs ("sll", file); break; - case ASHIFTRT: fputs ("sra", file); break; - case LSHIFTRT: fputs ("srl", file); break; - } - break; - - /* case 'n': negate and print a constant int */ - - case 'P': - /* Print PIC label using operand as the number. */ - if (GET_CODE (x) != CONST_INT) - fatal_insn ("Bad insn to frv_print_operand, P modifier:", x); - - fprintf (file, ".LCF%ld", (long)INTVAL (x)); - break; - - case 'U': - /* Print 'u' if the operand is a update load/store */ - if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PRE_MODIFY) - fputs ("u", file); - break; - - case 'z': - /* If value is 0, print gr0, otherwise it must be a register */ - if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0) - fputs (reg_names[GPR_R0], file); - - else if (GET_CODE (x) == REG) - fputs (reg_names [REGNO (x)], file); - - else - fatal_insn ("Bad insn in frv_print_operand, z case", x); - break; - - case 'x': - /* Print constant in hex */ - if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) - { - fprintf (file, "%s0x%.4lx", IMMEDIATE_PREFIX, (long) value); - break; - } - - /* fall through */ - - case '\0': - if (GET_CODE (x) == REG) - fputs (reg_names [REGNO (x)], file); - - else if (GET_CODE (x) == CONST_INT - || GET_CODE (x) == CONST_DOUBLE) - fprintf (file, "%s%ld", IMMEDIATE_PREFIX, (long) value); - - else if (GET_CODE (x) == MEM) - frv_print_operand_address (file, XEXP (x, 0)); - - else if (CONSTANT_ADDRESS_P (x)) - frv_print_operand_address (file, x); - - else - fatal_insn ("Bad insn in frv_print_operand, 0 case", x); - - break; - - default: - fatal_insn ("frv_print_operand: unknown code", x); - break; - } - - return; -} - - -/* 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 -frv_init_cumulative_args (cum, fntype, libname, indirect, incoming) - CUMULATIVE_ARGS *cum; - tree fntype; - rtx libname; - int indirect; - int incoming; -{ - *cum = FIRST_ARG_REGNUM; - - 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)); - - if (cfun->returns_struct) - fprintf (stderr, " return-struct"); - - 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 -frv_function_arg_boundary (mode, type) - enum machine_mode mode ATTRIBUTE_UNUSED; - tree type ATTRIBUTE_UNUSED; -{ - return BITS_PER_WORD; -} - - -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way - defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous - arguments so far passed in registers; 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 -frv_function_arg (cum, mode, type, named, incoming) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type ATTRIBUTE_UNUSED; - int named; - int incoming ATTRIBUTE_UNUSED; -{ - enum machine_mode xmode = (mode == BLKmode) ? SImode : mode; - int arg_num = *cum; - rtx ret; - const char *debstr; - - /* Return a marker for use in the call instruction. */ - if (xmode == VOIDmode) - { - ret = const0_rtx; - debstr = "<0>"; - } - - else if (arg_num <= LAST_ARG_REGNUM) - { - ret = gen_rtx (REG, xmode, arg_num); - debstr = reg_names[arg_num]; - } - - else - { - ret = NULL_RTX; - debstr = "memory"; - } - - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "function_arg: words = %2d, mode = %4s, named = %d, size = %3d, arg = %s\n", - arg_num, GET_MODE_NAME (mode), named, GET_MODE_SIZE (mode), debstr); - - 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 -frv_function_arg_advance (cum, mode, type, named) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type ATTRIBUTE_UNUSED; - int named; -{ - enum machine_mode xmode = (mode == BLKmode) ? SImode : mode; - int bytes = GET_MODE_SIZE (xmode); - int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - int arg_num = *cum; - - *cum = arg_num + words; - - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "function_adv: words = %2d, mode = %4s, named = %d, size = %3d\n", - arg_num, GET_MODE_NAME (mode), named, words * UNITS_PER_WORD); -} - - -/* 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 -frv_function_arg_partial_nregs (cum, mode, type, named) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type ATTRIBUTE_UNUSED; - int named ATTRIBUTE_UNUSED; -{ - enum machine_mode xmode = (mode == BLKmode) ? SImode : mode; - int bytes = GET_MODE_SIZE (xmode); - int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - int arg_num = *cum; - int ret; - - ret = ((arg_num <= LAST_ARG_REGNUM && arg_num + words > LAST_ARG_REGNUM+1) - ? LAST_ARG_REGNUM - 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 -frv_function_arg_pass_by_reference (cum, mode, type, named) - CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED; - enum machine_mode mode; - tree type; - int named ATTRIBUTE_UNUSED; -{ - return MUST_PASS_IN_STACK (mode, type); -} - -/* 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 -frv_function_arg_callee_copies (cum, mode, type, named) - CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; - tree type ATTRIBUTE_UNUSED; - int named ATTRIBUTE_UNUSED; -{ - return 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. */ - -int -frv_function_arg_keep_as_reference (cum, mode, type, named) - CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; - tree type ATTRIBUTE_UNUSED; - int named ATTRIBUTE_UNUSED; -{ - return 0; -} - - -/* Return true if a register is ok to use as a base or index register. */ - -static FRV_INLINE int -frv_regno_ok_for_base_p (regno, strict_p) - int regno; - int strict_p; -{ - if (GPR_P (regno)) - return TRUE; - - if (strict_p) - return (reg_renumber[regno] >= 0 && GPR_P (reg_renumber[regno])); - - if (regno == ARG_POINTER_REGNUM) - return TRUE; - - return (regno >= FIRST_PSEUDO_REGISTER); -} - - -/* 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 - `(* targetm.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'. */ - -int -frv_legitimate_address_p (mode, x, strict_p, condexec_p) - enum machine_mode mode; - rtx x; - int strict_p; - int condexec_p; -{ - rtx x0, x1; - int ret = 0; - HOST_WIDE_INT value; - unsigned regno0; - - switch (GET_CODE (x)) - { - default: - break; - - case SUBREG: - x = SUBREG_REG (x); - if (GET_CODE (x) != REG) - break; - - /* fall through */ - - case REG: - ret = frv_regno_ok_for_base_p (REGNO (x), strict_p); - break; - - case PRE_MODIFY: - x0 = XEXP (x, 0); - x1 = XEXP (x, 1); - if (GET_CODE (x0) != REG - || ! frv_regno_ok_for_base_p (REGNO (x0), strict_p) - || GET_CODE (x1) != PLUS - || ! rtx_equal_p (x0, XEXP (x1, 0)) - || GET_CODE (XEXP (x1, 1)) != REG - || ! frv_regno_ok_for_base_p (REGNO (XEXP (x1, 1)), strict_p)) - break; - - ret = 1; - break; - - case CONST_INT: - /* 12 bit immediate */ - if (condexec_p) - ret = FALSE; - else - { - ret = IN_RANGE_P (INTVAL (x), -2048, 2047); - - /* If we can't use load/store double operations, make sure we can - address the second word. */ - if (ret && GET_MODE_SIZE (mode) > UNITS_PER_WORD) - ret = IN_RANGE_P (INTVAL (x) + GET_MODE_SIZE (mode) - 1, - -2048, 2047); - } - break; - - case PLUS: - x0 = XEXP (x, 0); - x1 = XEXP (x, 1); - - if (GET_CODE (x0) == SUBREG) - x0 = SUBREG_REG (x0); - - if (GET_CODE (x0) != REG) - break; - - regno0 = REGNO (x0); - if (!frv_regno_ok_for_base_p (regno0, 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: - /* Do not allow reg+reg addressing for modes > 1 word if we can't depend - on having move double instructions */ - if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) - ret = FALSE; - else - ret = frv_regno_ok_for_base_p (REGNO (x1), strict_p); - break; - - case CONST_INT: - /* 12 bit immediate */ - if (condexec_p) - ret = FALSE; - else - { - value = INTVAL (x1); - ret = IN_RANGE_P (value, -2048, 2047); - - /* If we can't use load/store double operations, make sure we can - address the second word. */ - if (ret && GET_MODE_SIZE (mode) > UNITS_PER_WORD) - ret = IN_RANGE_P (value + GET_MODE_SIZE (mode) - 1, -2048, 2047); - } - break; - - case SYMBOL_REF: - if (!condexec_p - && regno0 == SDA_BASE_REG - && symbol_ref_small_data_p (x1)) - ret = TRUE; - break; - - case CONST: - if (!condexec_p && regno0 == SDA_BASE_REG && const_small_data_p (x1)) - ret = TRUE; - break; - - } - break; - } - - if (TARGET_DEBUG_ADDR) - { - fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, mode = %s, result = %d, addresses are %sstrict%s\n", - GET_MODE_NAME (mode), ret, (strict_p) ? "" : "not ", - (condexec_p) ? ", inside conditional code" : ""); - 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 -frv_legitimize_address (x, oldx, mode) - rtx x; - rtx oldx ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx ret = NULL_RTX; - - /* Don't try to legitimize addreses if we are not optimizing, since the - address we generate is not a general operand, and will horribly mess - things up when force_reg is called to try and put it in a register because - we aren't optimizing. */ - if (optimize - && ((GET_CODE (x) == SYMBOL_REF && symbol_ref_small_data_p (x)) - || (GET_CODE (x) == CONST && const_small_data_p (x)))) - { - ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, SDA_BASE_REG), x); - if (flag_pic) - cfun->uses_pic_offset_table = TRUE; - } - - if (TARGET_DEBUG_ADDR && ret != NULL_RTX) - { - fprintf (stderr, "\n========== LEGITIMIZE_ADDRESS, mode = %s, modified address\n", - GET_MODE_NAME (mode)); - debug_rtx (ret); - } - - return ret; -} - -/* Return 1 if operand is a valid FRV address. CONDEXEC_P is true if - the operand is used by a predicated instruction. */ - -static int -frv_legitimate_memory_operand (op, mode, condexec_p) - rtx op; - enum machine_mode mode; - int condexec_p; -{ - return ((GET_MODE (op) == mode || mode == VOIDmode) - && GET_CODE (op) == MEM - && frv_legitimate_address_p (mode, XEXP (op, 0), - reload_completed, condexec_p)); -} - - -/* Return 1 is OP is a memory operand, or will be turned into one by - reload. */ - -int frv_load_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (reload_in_progress) - { - rtx tmp = op; - if (GET_CODE (tmp) == SUBREG) - tmp = SUBREG_REG (tmp); - if (GET_CODE (tmp) == REG - && REGNO (tmp) >= FIRST_PSEUDO_REGISTER) - op = reg_equiv_memory_loc[REGNO (tmp)]; - } - - return op && memory_operand (op, mode); -} - - -/* Return 1 if operand is a GPR register or a FPR register. */ - -int gpr_or_fpr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - if (GPR_P (regno) || FPR_P (regno) || regno >= FIRST_PSEUDO_REGISTER) - return TRUE; - - return FALSE; -} - -/* Return 1 if operand is a GPR register or 12 bit signed immediate. */ - -int gpr_or_int12_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -2048, 2047); - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return 1 if operand is a GPR register, or a FPR register, or a 12 bit - signed immediate. */ - -int gpr_fpr_or_int12_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -2048, 2047); - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - if (GPR_P (regno) || FPR_P (regno) || regno >= FIRST_PSEUDO_REGISTER) - return TRUE; - - return FALSE; -} - -/* Return 1 if operand is a register or 6 bit signed immediate. */ - -int fpr_or_int6_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -32, 31); - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return FPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return 1 if operand is a register or 10 bit signed immediate. */ - -int gpr_or_int10_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -512, 511); - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return 1 if operand is a register or an integer immediate. */ - -int gpr_or_int_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == CONST_INT) - return TRUE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return 1 if operand is a 12 bit signed immediate. */ - -int int12_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) != CONST_INT) - return FALSE; - - return IN_RANGE_P (INTVAL (op), -2048, 2047); -} - -/* Return 1 if operand is a 6 bit signed immediate. */ - -int int6_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) != CONST_INT) - return FALSE; - - return IN_RANGE_P (INTVAL (op), -32, 31); -} - -/* Return 1 if operand is a 5 bit signed immediate. */ - -int int5_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return GET_CODE (op) == CONST_INT && IN_RANGE_P (INTVAL (op), -16, 15); -} - -/* Return 1 if operand is a 5 bit unsigned immediate. */ - -int uint5_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return GET_CODE (op) == CONST_INT && IN_RANGE_P (INTVAL (op), 0, 31); -} - -/* Return 1 if operand is a 4 bit unsigned immediate. */ - -int uint4_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return GET_CODE (op) == CONST_INT && IN_RANGE_P (INTVAL (op), 0, 15); -} - -/* Return 1 if operand is a 1 bit unsigned immediate (0 or 1). */ - -int uint1_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return GET_CODE (op) == CONST_INT && IN_RANGE_P (INTVAL (op), 0, 1); -} - -/* Return 1 if operand is an integer constant that takes 2 instructions - to load up and can be split into sethi/setlo instructions.. */ - -int int_2word_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - HOST_WIDE_INT value; - REAL_VALUE_TYPE rv; - long l; - - switch (GET_CODE (op)) - { - default: - break; - - case LABEL_REF: - return (flag_pic == 0); - - case CONST: - /* small data references are already 1 word */ - return (flag_pic == 0) && (! const_small_data_p (op)); - - case SYMBOL_REF: - /* small data references are already 1 word */ - return (flag_pic == 0) && (! symbol_ref_small_data_p (op)); - - case CONST_INT: - return ! IN_RANGE_P (INTVAL (op), -32768, 32767); - - case CONST_DOUBLE: - if (GET_MODE (op) == SFmode) - { - REAL_VALUE_FROM_CONST_DOUBLE (rv, op); - REAL_VALUE_TO_TARGET_SINGLE (rv, l); - value = l; - return ! IN_RANGE_P (value, -32768, 32767); - } - else if (GET_MODE (op) == VOIDmode) - { - value = CONST_DOUBLE_LOW (op); - return ! IN_RANGE_P (value, -32768, 32767); - } - break; - } - - return FALSE; -} - -/* Return 1 if operand is the pic address register. */ -int -pic_register_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (! flag_pic) - return FALSE; - - if (GET_CODE (op) != REG) - return FALSE; - - if (REGNO (op) != PIC_REGNO) - return FALSE; - - return TRUE; -} - -/* Return 1 if operand is a symbolic reference when a PIC option is specified - that takes 3 seperate instructions to form. */ - -int pic_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (! flag_pic) - return FALSE; - - switch (GET_CODE (op)) - { - default: - break; - - case LABEL_REF: - return TRUE; - - case SYMBOL_REF: - /* small data references are already 1 word */ - return ! symbol_ref_small_data_p (op); - - case CONST: - /* small data references are already 1 word */ - return ! const_small_data_p (op); - } - - return FALSE; -} - -/* Return 1 if operand is the small data register. */ -int -small_data_register_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) != REG) - return FALSE; - - if (REGNO (op) != SDA_BASE_REG) - return FALSE; - - return TRUE; -} - -/* Return 1 if operand is a symbolic reference to a small data area static or - global object. */ - -int small_data_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - switch (GET_CODE (op)) - { - default: - break; - - case CONST: - return const_small_data_p (op); - - case SYMBOL_REF: - return symbol_ref_small_data_p (op); - } - - return FALSE; -} - -/* Return 1 if operand is a 16 bit unsigned immediate */ - -int uint16_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) != CONST_INT) - return FALSE; - - return IN_RANGE_P (INTVAL (op), 0, 0xffff); -} - -/* Return 1 if operand is an integer constant with the bottom 16 bits clear */ - -int upper_int16_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) != CONST_INT) - return FALSE; - - return ((INTVAL (op) & 0xffff) == 0); -} - -/* Return true if operand is a GPR register. */ - -int -integer_register_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a GPR register. Do not allow SUBREG's - here, in order to prevent a combine bug. */ - -int -gpr_no_subreg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != REG) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a FPR register. */ - -int -fpr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return FPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is an even GPR or FPR register. */ - -int -even_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - if (regno >= FIRST_PSEUDO_REGISTER) - return TRUE; - - if (GPR_P (regno)) - return (((regno - GPR_FIRST) & 1) == 0); - - if (FPR_P (regno)) - return (((regno - FPR_FIRST) & 1) == 0); - - return FALSE; -} - -/* Return true if operand is an odd GPR register. */ - -int -odd_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - /* assume that reload will give us an even register */ - if (regno >= FIRST_PSEUDO_REGISTER) - return FALSE; - - if (GPR_P (regno)) - return (((regno - GPR_FIRST) & 1) != 0); - - if (FPR_P (regno)) - return (((regno - FPR_FIRST) & 1) != 0); - - return FALSE; -} - -/* Return true if operand is an even GPR register. */ - -int -even_gpr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - if (regno >= FIRST_PSEUDO_REGISTER) - return TRUE; - - if (! GPR_P (regno)) - return FALSE; - - return (((regno - GPR_FIRST) & 1) == 0); -} - -/* Return true if operand is an odd GPR register. */ - -int -odd_gpr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - /* assume that reload will give us an even register */ - if (regno >= FIRST_PSEUDO_REGISTER) - return FALSE; - - if (! GPR_P (regno)) - return FALSE; - - return (((regno - GPR_FIRST) & 1) != 0); -} - -/* Return true if operand is a quad aligned FPR register. */ - -int -quad_fpr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - if (regno >= FIRST_PSEUDO_REGISTER) - return TRUE; - - if (! FPR_P (regno)) - return FALSE; - - return (((regno - FPR_FIRST) & 3) == 0); -} - -/* Return true if operand is an even FPR register. */ - -int -even_fpr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - if (regno >= FIRST_PSEUDO_REGISTER) - return TRUE; - - if (! FPR_P (regno)) - return FALSE; - - return (((regno - FPR_FIRST) & 1) == 0); -} - -/* Return true if operand is an odd FPR register. */ - -int -odd_fpr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - /* assume that reload will give us an even register */ - if (regno >= FIRST_PSEUDO_REGISTER) - return FALSE; - - if (! FPR_P (regno)) - return FALSE; - - return (((regno - FPR_FIRST) & 1) != 0); -} - -/* Return true if operand is a 2 word memory address that can be loaded in one - instruction to load or store. We assume the stack and frame pointers are - suitably aligned, and variables in the small data area. FIXME -- at some we - should recognize other globals and statics. We can't assume that any old - pointer is aligned, given that arguments could be passed on an odd word on - the stack and the address taken and passed through to another function. */ - -int -dbl_memory_one_insn_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx addr; - rtx addr_reg; - - if (! TARGET_DWORD) - return FALSE; - - if (GET_CODE (op) != MEM) - return FALSE; - - if (mode != VOIDmode && GET_MODE_SIZE (mode) != 2*UNITS_PER_WORD) - return FALSE; - - addr = XEXP (op, 0); - if (GET_CODE (addr) == REG) - addr_reg = addr; - - else if (GET_CODE (addr) == PLUS) - { - rtx addr0 = XEXP (addr, 0); - rtx addr1 = XEXP (addr, 1); - - if (GET_CODE (addr0) != REG) - return FALSE; - - if (plus_small_data_p (addr0, addr1)) - return TRUE; - - if (GET_CODE (addr1) != CONST_INT) - return FALSE; - - if ((INTVAL (addr1) & 7) != 0) - return FALSE; - - addr_reg = addr0; - } - - else - return FALSE; - - if (addr_reg == frame_pointer_rtx || addr_reg == stack_pointer_rtx) - return TRUE; - - return FALSE; -} - -/* Return true if operand is a 2 word memory address that needs to - use two instructions to load or store. */ - -int -dbl_memory_two_insn_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM) - return FALSE; - - if (mode != VOIDmode && GET_MODE_SIZE (mode) != 2*UNITS_PER_WORD) - return FALSE; - - if (! TARGET_DWORD) - return TRUE; - - return ! dbl_memory_one_insn_operand (op, mode); -} - -/* Return true if operand is something that can be an output for a move - operation. */ - -int -move_destination_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx subreg; - enum rtx_code code; - - switch (GET_CODE (op)) - { - default: - break; - - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - subreg = SUBREG_REG (op); - code = GET_CODE (subreg); - if (code == MEM) - return frv_legitimate_address_p (mode, XEXP (subreg, 0), - reload_completed, FALSE); - - return (code == REG); - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return TRUE; - - case MEM: - if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) - return TRUE; - - return frv_legitimate_memory_operand (op, mode, FALSE); - } - - return FALSE; -} - -/* Return true if operand is something that can be an input for a move - operation. */ - -int -move_source_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx subreg; - enum rtx_code code; - - switch (GET_CODE (op)) - { - default: - break; - - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return immediate_operand (op, mode); - - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - subreg = SUBREG_REG (op); - code = GET_CODE (subreg); - if (code == MEM) - return frv_legitimate_address_p (mode, XEXP (subreg, 0), - reload_completed, FALSE); - - return (code == REG); - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return TRUE; - - case MEM: - if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) - return TRUE; - - return frv_legitimate_memory_operand (op, mode, FALSE); - } - - return FALSE; -} - -/* Return true if operand is something that can be an output for a conditional - move operation. */ - -int -condexec_dest_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx subreg; - enum rtx_code code; - - switch (GET_CODE (op)) - { - default: - break; - - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - subreg = SUBREG_REG (op); - code = GET_CODE (subreg); - if (code == MEM) - return frv_legitimate_address_p (mode, XEXP (subreg, 0), - reload_completed, TRUE); - - return (code == REG); - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return TRUE; - - case MEM: - if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) - return TRUE; - - return frv_legitimate_memory_operand (op, mode, TRUE); - } - - return FALSE; -} - -/* Return true if operand is something that can be an input for a conditional - move operation. */ - -int -condexec_source_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx subreg; - enum rtx_code code; - - switch (GET_CODE (op)) - { - default: - break; - - case CONST_INT: - case CONST_DOUBLE: - return ZERO_P (op); - - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - subreg = SUBREG_REG (op); - code = GET_CODE (subreg); - if (code == MEM) - return frv_legitimate_address_p (mode, XEXP (subreg, 0), - reload_completed, TRUE); - - return (code == REG); - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return TRUE; - - case MEM: - if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) - return TRUE; - - return frv_legitimate_memory_operand (op, mode, TRUE); - } - - return FALSE; -} - -/* Return true if operand is a register of any flavor or a 0 of the - appropriate type. */ - -int -reg_or_0_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - default: - break; - - case REG: - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return register_operand (op, mode); - - case CONST_INT: - case CONST_DOUBLE: - return ZERO_P (op); - } - - return FALSE; -} - -/* Return true if operand is the link register */ - -int -lr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (REGNO (op) != LR_REGNO && REGNO (op) < FIRST_PSEUDO_REGISTER) - return FALSE; - - return TRUE; -} - -/* Return true if operand is a gpr register or a valid memory operation. */ - -int -gpr_or_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (integer_register_operand (op, mode) - || frv_legitimate_memory_operand (op, mode, FALSE)); -} - -/* Return true if operand is a fpr register or a valid memory operation. */ - -int -fpr_or_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (fpr_operand (op, mode) - || frv_legitimate_memory_operand (op, mode, FALSE)); -} - -/* Return true if operand is an icc register */ - -int -icc_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - return ICC_OR_PSEUDO_P (regno); -} - -/* Return true if operand is an fcc register */ - -int -fcc_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - return FCC_OR_PSEUDO_P (regno); -} - -/* Return true if operand is either an fcc or icc register */ - -int -cc_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - if (CC_OR_PSEUDO_P (regno)) - return TRUE; - - return FALSE; -} - -/* Return true if operand is an integer CCR register */ - -int -icr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - return ICR_OR_PSEUDO_P (regno); -} - -/* Return true if operand is an fcc register */ - -int -fcr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - return FCR_OR_PSEUDO_P (regno); -} - -/* Return true if operand is either an fcc or icc register */ - -int -cr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - if (CR_OR_PSEUDO_P (regno)) - return TRUE; - - return FALSE; -} - -/* Return true if operand is a memory reference suitable for a call. */ - -int -call_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode && GET_CODE (op) != CONST_INT) - return FALSE; - - if (GET_CODE (op) == SYMBOL_REF) - return TRUE; - - /* Note this doesn't allow reg+reg or reg+imm12 addressing (which should - never occur anyway), but prevents reload from not handling the case - properly of a call through a pointer on a function that calls - vfork/setjmp, etc. due to the need to flush all of the registers to stack. */ - return gpr_or_int12_operand (op, mode); -} - -/* Return true if operator is an kind of relational operator */ - -int -relational_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx op0; - rtx op1; - int regno; - - if (mode != VOIDmode && mode != GET_MODE (op)) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case EQ: - case NE: - case LE: - case LT: - case GE: - case GT: - case LEU: - case LTU: - case GEU: - case GTU: - break; - } - - op1 = XEXP (op, 1); - if (op1 != const0_rtx) - return FALSE; - - op0 = XEXP (op, 0); - if (GET_CODE (op0) != REG) - return FALSE; - - regno = REGNO (op0); - switch (GET_MODE (op0)) - { - default: - break; - - case CCmode: - case CC_UNSmode: - return ICC_OR_PSEUDO_P (regno); - - case CC_FPmode: - return FCC_OR_PSEUDO_P (regno); - - case CC_CCRmode: - return CR_OR_PSEUDO_P (regno); - } - - return FALSE; -} - -/* Return true if operator is a signed integer relational operator */ - -int -signed_relational_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx op0; - rtx op1; - int regno; - - if (mode != VOIDmode && mode != GET_MODE (op)) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case EQ: - case NE: - case LE: - case LT: - case GE: - case GT: - break; - } - - op1 = XEXP (op, 1); - if (op1 != const0_rtx) - return FALSE; - - op0 = XEXP (op, 0); - if (GET_CODE (op0) != REG) - return FALSE; - - regno = REGNO (op0); - if (GET_MODE (op0) == CCmode && ICC_OR_PSEUDO_P (regno)) - return TRUE; - - if (GET_MODE (op0) == CC_CCRmode && CR_OR_PSEUDO_P (regno)) - return TRUE; - - return FALSE; -} - -/* Return true if operator is a signed integer relational operator */ - -int -unsigned_relational_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx op0; - rtx op1; - int regno; - - if (mode != VOIDmode && mode != GET_MODE (op)) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case LEU: - case LTU: - case GEU: - case GTU: - break; - } - - op1 = XEXP (op, 1); - if (op1 != const0_rtx) - return FALSE; - - op0 = XEXP (op, 0); - if (GET_CODE (op0) != REG) - return FALSE; - - regno = REGNO (op0); - if (GET_MODE (op0) == CC_UNSmode && ICC_OR_PSEUDO_P (regno)) - return TRUE; - - if (GET_MODE (op0) == CC_CCRmode && CR_OR_PSEUDO_P (regno)) - return TRUE; - - return FALSE; -} - -/* Return true if operator is a floating point relational operator */ - -int -float_relational_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx op0; - rtx op1; - int regno; - - if (mode != VOIDmode && mode != GET_MODE (op)) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case EQ: case NE: - case LE: case LT: - case GE: case GT: -#if 0 - case UEQ: case UNE: - case ULE: case ULT: - case UGE: case UGT: - case ORDERED: - case UNORDERED: -#endif - break; - } - - op1 = XEXP (op, 1); - if (op1 != const0_rtx) - return FALSE; - - op0 = XEXP (op, 0); - if (GET_CODE (op0) != REG) - return FALSE; - - regno = REGNO (op0); - if (GET_MODE (op0) == CC_FPmode && FCC_OR_PSEUDO_P (regno)) - return TRUE; - - if (GET_MODE (op0) == CC_CCRmode && CR_OR_PSEUDO_P (regno)) - return TRUE; - - return FALSE; -} - -/* Return true if operator is EQ/NE of a conditional execution register. */ - -int -ccr_eqne_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - rtx op0; - rtx op1; - int regno; - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case EQ: - case NE: - break; - } - - op1 = XEXP (op, 1); - if (op1 != const0_rtx) - return FALSE; - - op0 = XEXP (op, 0); - if (GET_CODE (op0) != REG) - return FALSE; - - regno = REGNO (op0); - if (op_mode == CC_CCRmode && CR_OR_PSEUDO_P (regno)) - return TRUE; - - return FALSE; -} - -/* Return true if operator is a minimum or maximum operator (both signed and - unsigned). */ - -int -minmax_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case SMIN: - case SMAX: - case UMIN: - case UMAX: - break; - } - - if (! integer_register_operand (XEXP (op, 0), mode)) - return FALSE; - - if (! gpr_or_int10_operand (XEXP (op, 1), mode)) - return FALSE; - - return TRUE; -} - -/* Return true if operator is an integer binary operator that can executed - conditionally and takes 1 cycle. */ - -int -condexec_si_binary_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case PLUS: - case MINUS: - case AND: - case IOR: - case XOR: - case ASHIFT: - case ASHIFTRT: - case LSHIFTRT: - return TRUE; - } -} - -/* Return true if operator is an integer binary operator that can be - executed conditionally by a media instruction. */ - -int -condexec_si_media_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case AND: - case IOR: - case XOR: - return TRUE; - } -} - -/* Return true if operator is an integer division operator that can executed - conditionally. */ - -int -condexec_si_divide_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case DIV: - case UDIV: - return TRUE; - } -} - -/* Return true if operator is an integer unary operator that can executed - conditionally. */ - -int -condexec_si_unary_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case NEG: - case NOT: - return TRUE; - } -} - -/* Return true if operator is a conversion-type expression that can be - evaluated conditionally by floating-point instructions. */ - -int -condexec_sf_conv_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case NEG: - case ABS: - return TRUE; - } -} - -/* Return true if operator is an addition or subtraction expression. - Such expressions can be evaluated conditionally by floating-point - instructions. */ - -int -condexec_sf_add_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case PLUS: - case MINUS: - return TRUE; - } -} - -/* Return true if the memory operand is one that can be conditionally - executed. */ - -int -condexec_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - rtx addr; - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (op_mode) - { - default: - return FALSE; - - case QImode: - case HImode: - case SImode: - case SFmode: - break; - } - - if (GET_CODE (op) != MEM) - return FALSE; - - addr = XEXP (op, 0); - if (GET_CODE (addr) == ADDRESSOF) - return TRUE; - - return frv_legitimate_address_p (mode, addr, reload_completed, TRUE); -} - -/* Return true if operator is an integer binary operator that can be combined - with a setcc operation. Do not allow the arithmetic operations that could - potentially overflow since the FR-V sets the condition code based on the - "true" value of the result, not the result after truncating to a 32-bit - register. */ - -int -intop_compare_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case AND: - case IOR: - case XOR: - case ASHIFTRT: - case LSHIFTRT: - break; - } - - if (! integer_register_operand (XEXP (op, 0), SImode)) - return FALSE; - - if (! gpr_or_int10_operand (XEXP (op, 1), SImode)) - return FALSE; - - return TRUE; -} - -/* Return true if operator is an integer binary operator that can be combined - with a setcc operation inside of a conditional execution. */ - -int -condexec_intop_cmp_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - enum machine_mode op_mode = GET_MODE (op); - - if (mode != VOIDmode && op_mode != mode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case AND: - case IOR: - case XOR: - case ASHIFTRT: - case LSHIFTRT: - break; - } - - if (! integer_register_operand (XEXP (op, 0), SImode)) - return FALSE; - - if (! integer_register_operand (XEXP (op, 1), SImode)) - return FALSE; - - return TRUE; -} - -/* Return 1 if operand is a valid ACC register number */ - -int -acc_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - return ACC_OR_PSEUDO_P (regno); -} - -/* Return 1 if operand is a valid even ACC register number */ - -int -even_acc_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - return (ACC_OR_PSEUDO_P (regno) && ((regno - ACC_FIRST) & 1) == 0); -} - -/* Return 1 if operand is zero or four */ - -int -quad_acc_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - int regno; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - regno = REGNO (op); - return (ACC_OR_PSEUDO_P (regno) && ((regno - ACC_FIRST) & 3) == 0); -} - -/* Return 1 if operand is a valid ACCG register number */ - -int -accg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return ACCG_OR_PSEUDO_P (REGNO (op)); -} - - -/* Return true if the bare return instruction can be used outside of the - epilog code. For frv, we only do it if there was no stack allocation. */ - -int -direct_return_p () -{ - frv_stack_t *info; - - if (!reload_completed) - return FALSE; - - info = frv_stack_info (); - return (info->total_size == 0); -} - - -/* Emit code to handle a MOVSI, adding in the small data register or pic - register if needed to load up addresses. Return TRUE if the appropriate - instructions are emitted. */ - -int -frv_emit_movsi (dest, src) - rtx dest; - rtx src; -{ - int base_regno = -1; - - if (!reload_in_progress - && !reload_completed - && !register_operand (dest, SImode) - && (!reg_or_0_operand (src, SImode) - /* Virtual registers will almost always be replaced by an - add instruction, so expose this to CSE by copying to - an intermediate register */ - || (GET_CODE (src) == REG - && IN_RANGE_P (REGNO (src), - FIRST_VIRTUAL_REGISTER, - LAST_VIRTUAL_REGISTER)))) - { - emit_insn (gen_rtx_SET (VOIDmode, dest, copy_to_mode_reg (SImode, src))); - return TRUE; - } - - /* Explicitly add in the PIC or small data register if needed. */ - switch (GET_CODE (src)) - { - default: - break; - - case LABEL_REF: - if (flag_pic) - base_regno = PIC_REGNO; - - break; - - case CONST: - if (const_small_data_p (src)) - base_regno = SDA_BASE_REG; - - else if (flag_pic) - base_regno = PIC_REGNO; - - break; - - case SYMBOL_REF: - if (symbol_ref_small_data_p (src)) - base_regno = SDA_BASE_REG; - - else if (flag_pic) - base_regno = PIC_REGNO; - - break; - } - - if (base_regno >= 0) - { - emit_insn (gen_rtx_SET (VOIDmode, dest, - gen_rtx_PLUS (Pmode, - gen_rtx_REG (Pmode, base_regno), - src))); - - if (base_regno == PIC_REGNO) - cfun->uses_pic_offset_table = TRUE; - - return TRUE; - } - - return FALSE; -} - - -/* Return a string to output a single word move. */ - -const char * -output_move_single (operands, insn) - rtx operands[]; - rtx insn; -{ - rtx dest = operands[0]; - rtx src = operands[1]; - - if (GET_CODE (dest) == REG) - { - int dest_regno = REGNO (dest); - enum machine_mode mode = GET_MODE (dest); - - if (GPR_P (dest_regno)) - { - if (GET_CODE (src) == REG) - { - /* gpr <- some sort of register */ - int src_regno = REGNO (src); - - if (GPR_P (src_regno)) - return "mov %1, %0"; - - else if (FPR_P (src_regno)) - return "movfg %1, %0"; - - else if (SPR_P (src_regno)) - return "movsg %1, %0"; - } - - else if (GET_CODE (src) == MEM) - { - /* gpr <- memory */ - switch (mode) - { - default: - break; - - case QImode: - return "ldsb%I1%U1 %M1,%0"; - - case HImode: - return "ldsh%I1%U1 %M1,%0"; - - case SImode: - case SFmode: - return "ld%I1%U1 %M1, %0"; - } - } - - else if (GET_CODE (src) == CONST_INT - || GET_CODE (src) == CONST_DOUBLE) - { - /* gpr <- integer/floating constant */ - HOST_WIDE_INT value; - - if (GET_CODE (src) == CONST_INT) - value = INTVAL (src); - - else if (mode == SFmode) - { - REAL_VALUE_TYPE rv; - long l; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, src); - REAL_VALUE_TO_TARGET_SINGLE (rv, l); - value = l; - } - - else - value = CONST_DOUBLE_LOW (src); - - if (IN_RANGE_P (value, -32768, 32767)) - return "setlos %1, %0"; - - return "#"; - } - - else if (GET_CODE (src) == SYMBOL_REF - || GET_CODE (src) == LABEL_REF - || GET_CODE (src) == CONST) - { - /* Silently fix up instances where the small data pointer is not - used in the address. */ - if (small_data_symbolic_operand (src, GET_MODE (src))) - return "addi %@, #gprel12(%1), %0"; - - return "#"; - } - } - - else if (FPR_P (dest_regno)) - { - if (GET_CODE (src) == REG) - { - /* fpr <- some sort of register */ - int src_regno = REGNO (src); - - if (GPR_P (src_regno)) - return "movgf %1, %0"; - - else if (FPR_P (src_regno)) - { - if (TARGET_HARD_FLOAT) - return "fmovs %1, %0"; - else - return "mor %1, %1, %0"; - } - } - - else if (GET_CODE (src) == MEM) - { - /* fpr <- memory */ - switch (mode) - { - default: - break; - - case QImode: - return "ldbf%I1%U1 %M1,%0"; - - case HImode: - return "ldhf%I1%U1 %M1,%0"; - - case SImode: - case SFmode: - return "ldf%I1%U1 %M1, %0"; - } - } - - else if (ZERO_P (src)) - return "movgf %., %0"; - } - - else if (SPR_P (dest_regno)) - { - if (GET_CODE (src) == REG) - { - /* spr <- some sort of register */ - int src_regno = REGNO (src); - - if (GPR_P (src_regno)) - return "movgs %1, %0"; - } - } - } - - else if (GET_CODE (dest) == MEM) - { - if (GET_CODE (src) == REG) - { - int src_regno = REGNO (src); - enum machine_mode mode = GET_MODE (dest); - - if (GPR_P (src_regno)) - { - switch (mode) - { - default: - break; - - case QImode: - return "stb%I0%U0 %1, %M0"; - - case HImode: - return "sth%I0%U0 %1, %M0"; - - case SImode: - case SFmode: - return "st%I0%U0 %1, %M0"; - } - } - - else if (FPR_P (src_regno)) - { - switch (mode) - { - default: - break; - - case QImode: - return "stbf%I0%U0 %1, %M0"; - - case HImode: - return "sthf%I0%U0 %1, %M0"; - - case SImode: - case SFmode: - return "stf%I0%U0 %1, %M0"; - } - } - } - - else if (ZERO_P (src)) - { - switch (GET_MODE (dest)) - { - default: - break; - - case QImode: - return "stb%I0%U0 %., %M0"; - - case HImode: - return "sth%I0%U0 %., %M0"; - - case SImode: - case SFmode: - return "st%I0%U0 %., %M0"; - } - } - } - - fatal_insn ("Bad output_move_single operand", insn); - return ""; -} - - -/* Return a string to output a double word move. */ - -const char * -output_move_double (operands, insn) - rtx operands[]; - rtx insn; -{ - rtx dest = operands[0]; - rtx src = operands[1]; - enum machine_mode mode = GET_MODE (dest); - - if (GET_CODE (dest) == REG) - { - int dest_regno = REGNO (dest); - - if (GPR_P (dest_regno)) - { - if (GET_CODE (src) == REG) - { - /* gpr <- some sort of register */ - int src_regno = REGNO (src); - - if (GPR_P (src_regno)) - return "#"; - - else if (FPR_P (src_regno)) - { - if (((dest_regno - GPR_FIRST) & 1) == 0 - && ((src_regno - FPR_FIRST) & 1) == 0) - return "movfgd %1, %0"; - - return "#"; - } - } - - else if (GET_CODE (src) == MEM) - { - /* gpr <- memory */ - if (dbl_memory_one_insn_operand (src, mode)) - return "ldd%I1%U1 %M1, %0"; - - return "#"; - } - - else if (GET_CODE (src) == CONST_INT - || GET_CODE (src) == CONST_DOUBLE) - return "#"; - } - - else if (FPR_P (dest_regno)) - { - if (GET_CODE (src) == REG) - { - /* fpr <- some sort of register */ - int src_regno = REGNO (src); - - if (GPR_P (src_regno)) - { - if (((dest_regno - FPR_FIRST) & 1) == 0 - && ((src_regno - GPR_FIRST) & 1) == 0) - return "movgfd %1, %0"; - - return "#"; - } - - else if (FPR_P (src_regno)) - { - if (TARGET_DOUBLE - && ((dest_regno - FPR_FIRST) & 1) == 0 - && ((src_regno - FPR_FIRST) & 1) == 0) - return "fmovd %1, %0"; - - return "#"; - } - } - - else if (GET_CODE (src) == MEM) - { - /* fpr <- memory */ - if (dbl_memory_one_insn_operand (src, mode)) - return "lddf%I1%U1 %M1, %0"; - - return "#"; - } - - else if (ZERO_P (src)) - return "#"; - } - } - - else if (GET_CODE (dest) == MEM) - { - if (GET_CODE (src) == REG) - { - int src_regno = REGNO (src); - - if (GPR_P (src_regno)) - { - if (((src_regno - GPR_FIRST) & 1) == 0 - && dbl_memory_one_insn_operand (dest, mode)) - return "std%I0%U0 %1, %M0"; - - return "#"; - } - - if (FPR_P (src_regno)) - { - if (((src_regno - FPR_FIRST) & 1) == 0 - && dbl_memory_one_insn_operand (dest, mode)) - return "stdf%I0%U0 %1, %M0"; - - return "#"; - } - } - - else if (ZERO_P (src)) - { - if (dbl_memory_one_insn_operand (dest, mode)) - return "std%I0%U0 %., %M0"; - - return "#"; - } - } - - fatal_insn ("Bad output_move_double operand", insn); - return ""; -} - - -/* Return a string to output a single word conditional move. - Operand0 -- EQ/NE of ccr register and 0 - Operand1 -- CCR register - Operand2 -- destination - Operand3 -- source */ - -const char * -output_condmove_single (operands, insn) - rtx operands[]; - rtx insn; -{ - rtx dest = operands[2]; - rtx src = operands[3]; - - if (GET_CODE (dest) == REG) - { - int dest_regno = REGNO (dest); - enum machine_mode mode = GET_MODE (dest); - - if (GPR_P (dest_regno)) - { - if (GET_CODE (src) == REG) - { - /* gpr <- some sort of register */ - int src_regno = REGNO (src); - - if (GPR_P (src_regno)) - return "cmov %z3, %2, %1, %e0"; - - else if (FPR_P (src_regno)) - return "cmovfg %3, %2, %1, %e0"; - } - - else if (GET_CODE (src) == MEM) - { - /* gpr <- memory */ - switch (mode) - { - default: - break; - - case QImode: - return "cldsb%I3%U3 %M3, %2, %1, %e0"; - - case HImode: - return "cldsh%I3%U3 %M3, %2, %1, %e0"; - - case SImode: - case SFmode: - return "cld%I3%U3 %M3, %2, %1, %e0"; - } - } - - else if (ZERO_P (src)) - return "cmov %., %2, %1, %e0"; - } - - else if (FPR_P (dest_regno)) - { - if (GET_CODE (src) == REG) - { - /* fpr <- some sort of register */ - int src_regno = REGNO (src); - - if (GPR_P (src_regno)) - return "cmovgf %3, %2, %1, %e0"; - - else if (FPR_P (src_regno)) - { - if (TARGET_HARD_FLOAT) - return "cfmovs %3,%2,%1,%e0"; - else - return "cmor %3, %3, %2, %1, %e0"; - } - } - - else if (GET_CODE (src) == MEM) - { - /* fpr <- memory */ - if (mode == SImode || mode == SFmode) - return "cldf%I3%U3 %M3, %2, %1, %e0"; - } - - else if (ZERO_P (src)) - return "cmovgf %., %2, %1, %e0"; - } - } - - else if (GET_CODE (dest) == MEM) - { - if (GET_CODE (src) == REG) - { - int src_regno = REGNO (src); - enum machine_mode mode = GET_MODE (dest); - - if (GPR_P (src_regno)) - { - switch (mode) - { - default: - break; - - case QImode: - return "cstb%I2%U2 %3, %M2, %1, %e0"; - - case HImode: - return "csth%I2%U2 %3, %M2, %1, %e0"; - - case SImode: - case SFmode: - return "cst%I2%U2 %3, %M2, %1, %e0"; - } - } - - else if (FPR_P (src_regno) && (mode == SImode || mode == SFmode)) - return "cstf%I2%U2 %3, %M2, %1, %e0"; - } - - else if (ZERO_P (src)) - { - enum machine_mode mode = GET_MODE (dest); - switch (mode) - { - default: - break; - - case QImode: - return "cstb%I2%U2 %., %M2, %1, %e0"; - - case HImode: - return "csth%I2%U2 %., %M2, %1, %e0"; - - case SImode: - case SFmode: - return "cst%I2%U2 %., %M2, %1, %e0"; - } - } - } - - fatal_insn ("Bad output_condmove_single operand", insn); - return ""; -} - - -/* Emit the appropriate code to do a comparison, returning the register the - comparison was done it. */ - -static rtx -frv_emit_comparison (test, op0, op1) - enum rtx_code test; - rtx op0; - rtx op1; -{ - enum machine_mode cc_mode; - rtx cc_reg; - - /* Floating point doesn't have comparison against a constant */ - if (GET_MODE (op0) == CC_FPmode && GET_CODE (op1) != REG) - op1 = force_reg (GET_MODE (op0), op1); - - /* Possibly disable using anything but a fixed register in order to work - around cse moving comparisons past function calls. */ - cc_mode = SELECT_CC_MODE (test, op0, op1); - cc_reg = ((TARGET_ALLOC_CC) - ? gen_reg_rtx (cc_mode) - : gen_rtx_REG (cc_mode, - (cc_mode == CC_FPmode) ? FCC_FIRST : ICC_FIRST)); - - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, - gen_rtx_COMPARE (cc_mode, op0, op1))); - - return cc_reg; -} - - -/* Emit code for a conditional branch. The comparison operands were previously - stored in frv_compare_op0 and frv_compare_op1. - - XXX: I originally wanted to add a clobber of a CCR register to use in - conditional execution, but that confuses the rest of the compiler. */ - -int -frv_emit_cond_branch (test, label) - enum rtx_code test; - rtx label; -{ - rtx test_rtx; - rtx label_ref; - rtx if_else; - rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1); - enum machine_mode cc_mode = GET_MODE (cc_reg); - - /* Branches generate: - (set (pc) - (if_then_else (, , (const_int 0)) - (label_ref ) - (pc))) */ - label_ref = gen_rtx_LABEL_REF (VOIDmode, label); - test_rtx = gen_rtx (test, cc_mode, cc_reg, const0_rtx); - if_else = gen_rtx_IF_THEN_ELSE (cc_mode, test_rtx, label_ref, pc_rtx); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_else)); - return TRUE; -} - - -/* Emit code to set a gpr to 1/0 based on a comparison. The comparison - operands were previously stored in frv_compare_op0 and frv_compare_op1. */ - -int -frv_emit_scc (test, target) - enum rtx_code test; - rtx target; -{ - rtx set; - rtx test_rtx; - rtx clobber; - rtx cr_reg; - rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1); - - /* SCC instructions generate: - (parallel [(set (, , (const_int 0)) - (clobber ())]) */ - test_rtx = gen_rtx_fmt_ee (test, SImode, cc_reg, const0_rtx); - set = gen_rtx_SET (VOIDmode, target, test_rtx); - - cr_reg = ((TARGET_ALLOC_CC) - ? gen_reg_rtx (CC_CCRmode) - : gen_rtx_REG (CC_CCRmode, - ((GET_MODE (cc_reg) == CC_FPmode) - ? FCR_FIRST - : ICR_FIRST))); - - clobber = gen_rtx_CLOBBER (VOIDmode, cr_reg); - emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber))); - return TRUE; -} - - -/* Split a SCC instruction into component parts, returning a SEQUENCE to hold - the seperate insns. */ - -rtx -frv_split_scc (dest, test, cc_reg, cr_reg, value) - rtx dest; - rtx test; - rtx cc_reg; - rtx cr_reg; - HOST_WIDE_INT value; -{ - rtx ret; - - start_sequence (); - - /* Set the appropriate CCR bit. */ - emit_insn (gen_rtx_SET (VOIDmode, - cr_reg, - gen_rtx_fmt_ee (GET_CODE (test), - GET_MODE (cr_reg), - cc_reg, - const0_rtx))); - - /* Move the value into the destination. */ - emit_move_insn (dest, GEN_INT (value)); - - /* Move 0 into the destination if the test failed */ - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_EQ (GET_MODE (cr_reg), - cr_reg, - const0_rtx), - gen_rtx_SET (VOIDmode, dest, const0_rtx))); - - /* Finish up, return sequence. */ - ret = get_insns (); - end_sequence (); - return ret; -} - - -/* Emit the code for a conditional move, return TRUE if we could do the - move. */ - -int -frv_emit_cond_move (dest, test_rtx, src1, src2) - rtx dest; - rtx test_rtx; - rtx src1; - rtx src2; -{ - rtx set; - rtx clobber_cc; - rtx test2; - rtx cr_reg; - rtx if_rtx; - enum rtx_code test = GET_CODE (test_rtx); - rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1); - enum machine_mode cc_mode = GET_MODE (cc_reg); - - /* Conditional move instructions generate: - (parallel [(set - (if_then_else ( (const_int 0)) - - )) - (clobber ())]) */ - - /* Handle various cases of conditional move involving two constants. */ - if (GET_CODE (src1) == CONST_INT && GET_CODE (src2) == CONST_INT) - { - HOST_WIDE_INT value1 = INTVAL (src1); - HOST_WIDE_INT value2 = INTVAL (src2); - - /* having 0 as one of the constants can be done by loading the other - constant, and optionally moving in gr0. */ - if (value1 == 0 || value2 == 0) - ; - - /* If the first value is within an addi range and also the difference - between the two fits in an addi's range, load up the difference, then - conditionally move in 0, and then unconditionally add the first - value. */ - else if (IN_RANGE_P (value1, -2048, 2047) - && IN_RANGE_P (value2 - value1, -2048, 2047)) - ; - - /* If neither condition holds, just force the constant into a - register. */ - else - { - src1 = force_reg (GET_MODE (dest), src1); - src2 = force_reg (GET_MODE (dest), src2); - } - } - - /* If one value is a register, insure the other value is either 0 or a - register. */ - else - { - if (GET_CODE (src1) == CONST_INT && INTVAL (src1) != 0) - src1 = force_reg (GET_MODE (dest), src1); - - if (GET_CODE (src2) == CONST_INT && INTVAL (src2) != 0) - src2 = force_reg (GET_MODE (dest), src2); - } - - test2 = gen_rtx_fmt_ee (test, cc_mode, cc_reg, const0_rtx); - if_rtx = gen_rtx_IF_THEN_ELSE (GET_MODE (dest), test2, src1, src2); - - set = gen_rtx_SET (VOIDmode, dest, if_rtx); - - cr_reg = ((TARGET_ALLOC_CC) - ? gen_reg_rtx (CC_CCRmode) - : gen_rtx_REG (CC_CCRmode, - (cc_mode == CC_FPmode) ? FCR_FIRST : ICR_FIRST)); - - clobber_cc = gen_rtx_CLOBBER (VOIDmode, cr_reg); - emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber_cc))); - return TRUE; -} - - -/* Split a conditonal move into constituent parts, returning a SEQUENCE - containing all of the insns. */ - -rtx -frv_split_cond_move (operands) - rtx operands[]; -{ - rtx dest = operands[0]; - rtx test = operands[1]; - rtx cc_reg = operands[2]; - rtx src1 = operands[3]; - rtx src2 = operands[4]; - rtx cr_reg = operands[5]; - rtx ret; - enum machine_mode cr_mode = GET_MODE (cr_reg); - - start_sequence (); - - /* Set the appropriate CCR bit. */ - emit_insn (gen_rtx_SET (VOIDmode, - cr_reg, - gen_rtx_fmt_ee (GET_CODE (test), - GET_MODE (cr_reg), - cc_reg, - const0_rtx))); - - /* Handle various cases of conditional move involving two constants. */ - if (GET_CODE (src1) == CONST_INT && GET_CODE (src2) == CONST_INT) - { - HOST_WIDE_INT value1 = INTVAL (src1); - HOST_WIDE_INT value2 = INTVAL (src2); - - /* having 0 as one of the constants can be done by loading the other - constant, and optionally moving in gr0. */ - if (value1 == 0) - { - emit_move_insn (dest, src2); - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (cr_mode, cr_reg, - const0_rtx), - gen_rtx_SET (VOIDmode, dest, src1))); - } - - else if (value2 == 0) - { - emit_move_insn (dest, src1); - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_EQ (cr_mode, cr_reg, - const0_rtx), - gen_rtx_SET (VOIDmode, dest, src2))); - } - - /* If the first value is within an addi range and also the difference - between the two fits in an addi's range, load up the difference, then - conditionally move in 0, and then unconditionally add the first - value. */ - else if (IN_RANGE_P (value1, -2048, 2047) - && IN_RANGE_P (value2 - value1, -2048, 2047)) - { - rtx dest_si = ((GET_MODE (dest) == SImode) - ? dest - : gen_rtx_SUBREG (SImode, dest, 0)); - - emit_move_insn (dest_si, GEN_INT (value2 - value1)); - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (cr_mode, cr_reg, - const0_rtx), - gen_rtx_SET (VOIDmode, dest_si, - const0_rtx))); - emit_insn (gen_addsi3 (dest_si, dest_si, src1)); - } - - else - abort (); - } - else - { - /* Emit the conditional move for the test being true if needed. */ - if (! rtx_equal_p (dest, src1)) - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (cr_mode, cr_reg, const0_rtx), - gen_rtx_SET (VOIDmode, dest, src1))); - - /* Emit the conditional move for the test being false if needed. */ - if (! rtx_equal_p (dest, src2)) - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_EQ (cr_mode, cr_reg, const0_rtx), - gen_rtx_SET (VOIDmode, dest, src2))); - } - - /* Finish up, return sequence. */ - ret = get_insns (); - end_sequence (); - return ret; -} - - -/* Split (set DEST SOURCE), where DEST is a double register and SOURCE is a - memory location that is not known to be dword-aligned. */ -void -frv_split_double_load (dest, source) - rtx dest; - rtx source; -{ - int regno = REGNO (dest); - rtx dest1 = gen_highpart (SImode, dest); - rtx dest2 = gen_lowpart (SImode, dest); - rtx address = XEXP (source, 0); - - /* If the address is pre-modified, load the lower-numbered register - first, then load the other register using an integer offset from - the modified base register. This order should always be safe, - since the pre-modification cannot affect the same registers as the - load does. - - The situation for other loads is more complicated. Loading one - of the registers could affect the value of ADDRESS, so we must - be careful which order we do them in. */ - if (GET_CODE (address) == PRE_MODIFY - || ! refers_to_regno_p (regno, regno + 1, address, NULL)) - { - /* It is safe to load the lower-numbered register first. */ - emit_move_insn (dest1, change_address (source, SImode, NULL)); - emit_move_insn (dest2, frv_index_memory (source, SImode, 1)); - } - else - { - /* ADDRESS is not pre-modified and the address depends on the - lower-numbered register. Load the higher-numbered register - first. */ - emit_move_insn (dest2, frv_index_memory (source, SImode, 1)); - emit_move_insn (dest1, change_address (source, SImode, NULL)); - } -} - -/* Split (set DEST SOURCE), where DEST refers to a dword memory location - and SOURCE is either a double register or the constant zero. */ -void -frv_split_double_store (dest, source) - rtx dest; - rtx source; -{ - rtx dest1 = change_address (dest, SImode, NULL); - rtx dest2 = frv_index_memory (dest, SImode, 1); - if (ZERO_P (source)) - { - emit_move_insn (dest1, CONST0_RTX (SImode)); - emit_move_insn (dest2, CONST0_RTX (SImode)); - } - else - { - emit_move_insn (dest1, gen_highpart (SImode, source)); - emit_move_insn (dest2, gen_lowpart (SImode, source)); - } -} - - -/* Split a min/max operation returning a SEQUENCE containing all of the - insns. */ - -rtx -frv_split_minmax (operands) - rtx operands[]; -{ - rtx dest = operands[0]; - rtx minmax = operands[1]; - rtx src1 = operands[2]; - rtx src2 = operands[3]; - rtx cc_reg = operands[4]; - rtx cr_reg = operands[5]; - rtx ret; - enum rtx_code test_code; - enum machine_mode cr_mode = GET_MODE (cr_reg); - - start_sequence (); - - /* Figure out which test to use */ - switch (GET_CODE (minmax)) - { - default: - abort (); - - case SMIN: test_code = LT; break; - case SMAX: test_code = GT; break; - case UMIN: test_code = LTU; break; - case UMAX: test_code = GTU; break; - } - - /* Issue the compare instruction. */ - emit_insn (gen_rtx_SET (VOIDmode, - cc_reg, - gen_rtx_COMPARE (GET_MODE (cc_reg), - src1, src2))); - - /* Set the appropriate CCR bit. */ - emit_insn (gen_rtx_SET (VOIDmode, - cr_reg, - gen_rtx_fmt_ee (test_code, - GET_MODE (cr_reg), - cc_reg, - const0_rtx))); - - /* If are taking the min/max of a non-zero constant, load that first, and - then do a conditional move of the other value. */ - if (GET_CODE (src2) == CONST_INT && INTVAL (src2) != 0) - { - if (rtx_equal_p (dest, src1)) - abort (); - - emit_move_insn (dest, src2); - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (cr_mode, cr_reg, const0_rtx), - gen_rtx_SET (VOIDmode, dest, src1))); - } - - /* Otherwise, do each half of the move. */ - else - { - /* Emit the conditional move for the test being true if needed. */ - if (! rtx_equal_p (dest, src1)) - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (cr_mode, cr_reg, const0_rtx), - gen_rtx_SET (VOIDmode, dest, src1))); - - /* Emit the conditional move for the test being false if needed. */ - if (! rtx_equal_p (dest, src2)) - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_EQ (cr_mode, cr_reg, const0_rtx), - gen_rtx_SET (VOIDmode, dest, src2))); - } - - /* Finish up, return sequence. */ - ret = get_insns (); - end_sequence (); - return ret; -} - - -/* Split an integer abs operation returning a SEQUENCE containing all of the - insns. */ - -rtx -frv_split_abs (operands) - rtx operands[]; -{ - rtx dest = operands[0]; - rtx src = operands[1]; - rtx cc_reg = operands[2]; - rtx cr_reg = operands[3]; - rtx ret; - - start_sequence (); - - /* Issue the compare < 0 instruction. */ - emit_insn (gen_rtx_SET (VOIDmode, - cc_reg, - gen_rtx_COMPARE (CCmode, src, const0_rtx))); - - /* Set the appropriate CCR bit. */ - emit_insn (gen_rtx_SET (VOIDmode, - cr_reg, - gen_rtx_fmt_ee (LT, CC_CCRmode, cc_reg, const0_rtx))); - - /* Emit the conditional negate if the value is negative */ - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (CC_CCRmode, cr_reg, const0_rtx), - gen_negsi2 (dest, src))); - - /* Emit the conditional move for the test being false if needed. */ - if (! rtx_equal_p (dest, src)) - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_EQ (CC_CCRmode, cr_reg, const0_rtx), - gen_rtx_SET (VOIDmode, dest, src))); - - /* Finish up, return sequence. */ - ret = get_insns (); - end_sequence (); - return ret; -} - - -/* An internal function called by for_each_rtx to clear in a hard_reg set each - register used in an insn. */ - -static int -frv_clear_registers_used (ptr, data) - rtx *ptr; - void *data; -{ - if (GET_CODE (*ptr) == REG) - { - int regno = REGNO (*ptr); - HARD_REG_SET *p_regs = (HARD_REG_SET *)data; - - if (regno < FIRST_PSEUDO_REGISTER) - { - int reg_max = regno + HARD_REGNO_NREGS (regno, GET_MODE (*ptr)); - - while (regno < reg_max) - { - CLEAR_HARD_REG_BIT (*p_regs, regno); - regno++; - } - } - } - - return 0; -} - - -/* Initialize the extra fields provided by IFCVT_EXTRA_FIELDS. */ - -/* On the FR-V, we don't have any extra fields per se, but it is useful hook to - initialize the static storage. */ -void -frv_ifcvt_init_extra_fields (ce_info) - ce_if_block_t *ce_info ATTRIBUTE_UNUSED; -{ - frv_ifcvt.added_insns_list = NULL_RTX; - frv_ifcvt.cur_scratch_regs = 0; - frv_ifcvt.num_nested_cond_exec = 0; - frv_ifcvt.cr_reg = NULL_RTX; - frv_ifcvt.nested_cc_reg = NULL_RTX; - frv_ifcvt.extra_int_cr = NULL_RTX; - frv_ifcvt.extra_fp_cr = NULL_RTX; - frv_ifcvt.last_nested_if_cr = NULL_RTX; -} - - -/* Internal function to add a potenial insn to the list of insns to be inserted - if the conditional execution conversion is successful. */ - -static void -frv_ifcvt_add_insn (pattern, insn, before_p) - rtx pattern; - rtx insn; - int before_p; -{ - rtx link = alloc_EXPR_LIST (VOIDmode, pattern, insn); - - link->jump = before_p; /* mark to add this before or after insn */ - frv_ifcvt.added_insns_list = alloc_EXPR_LIST (VOIDmode, link, - frv_ifcvt.added_insns_list); - - if (TARGET_DEBUG_COND_EXEC) - { - fprintf (stderr, - "\n:::::::::: frv_ifcvt_add_insn: add the following %s insn %d:\n", - (before_p) ? "before" : "after", - (int)INSN_UID (insn)); - - debug_rtx (pattern); - } -} - - -/* A C expression to modify the code described by the conditional if - information CE_INFO, possibly updating the tests in TRUE_EXPR, and - FALSE_EXPR for converting if-then and if-then-else code to conditional - instructions. Set either TRUE_EXPR or FALSE_EXPR to a null pointer if the - tests cannot be converted. */ - -void -frv_ifcvt_modify_tests (ce_info, p_true, p_false) - ce_if_block_t *ce_info; - rtx *p_true; - rtx *p_false; -{ - basic_block test_bb = ce_info->test_bb; /* test basic block */ - basic_block then_bb = ce_info->then_bb; /* THEN */ - basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */ - basic_block join_bb = ce_info->join_bb; /* join block or NULL */ - rtx true_expr = *p_true; - rtx cr; - rtx cc; - rtx nested_cc; - enum machine_mode mode = GET_MODE (true_expr); - int j; - basic_block *bb; - int num_bb; - frv_tmp_reg_t *tmp_reg = &frv_ifcvt.tmp_reg; - rtx check_insn; - rtx sub_cond_exec_reg; - enum rtx_code code; - enum rtx_code code_true; - enum rtx_code code_false; - enum reg_class cc_class; - enum reg_class cr_class; - int cc_first; - int cc_last; - - /* Make sure we are only dealing with hard registers. Also honor the - -mno-cond-exec switch, and -mno-nested-cond-exec switches if - applicable. */ - if (!reload_completed || TARGET_NO_COND_EXEC - || (TARGET_NO_NESTED_CE && ce_info->pass > 1)) - goto fail; - - /* Figure out which registers we can allocate for our own purposes. Only - consider registers that are not preserved across function calls and are - not fixed. However, allow the ICC/ICR temporary registers to be allocated - if we did not need to use them in reloading other registers. */ - memset ((PTR) &tmp_reg->regs, 0, sizeof (tmp_reg->regs)); - COPY_HARD_REG_SET (tmp_reg->regs, call_used_reg_set); - AND_COMPL_HARD_REG_SET (tmp_reg->regs, fixed_reg_set); - SET_HARD_REG_BIT (tmp_reg->regs, ICC_TEMP); - SET_HARD_REG_BIT (tmp_reg->regs, ICR_TEMP); - - /* If this is a nested IF, we need to discover whether the CC registers that - are set/used inside of the block are used anywhere else. If not, we can - change them to be the CC register that is paired with the CR register that - controls the outermost IF block. */ - if (ce_info->pass > 1) - { - CLEAR_HARD_REG_SET (frv_ifcvt.nested_cc_ok_rewrite); - for (j = CC_FIRST; j <= CC_LAST; j++) - if (TEST_HARD_REG_BIT (tmp_reg->regs, j)) - { - if (REGNO_REG_SET_P (then_bb->global_live_at_start, j)) - continue; - - if (else_bb && REGNO_REG_SET_P (else_bb->global_live_at_start, j)) - continue; - - if (join_bb && REGNO_REG_SET_P (join_bb->global_live_at_start, j)) - continue; - - SET_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, j); - } - } - - for (j = 0; j < frv_ifcvt.cur_scratch_regs; j++) - frv_ifcvt.scratch_regs[j] = NULL_RTX; - - frv_ifcvt.added_insns_list = NULL_RTX; - frv_ifcvt.cur_scratch_regs = 0; - - bb = (basic_block *) alloca ((2 + ce_info->num_multiple_test_blocks) - * sizeof (basic_block)); - - if (join_bb) - { - int regno; - - /* Remove anything live at the beginning of the join block from being - available for allocation. */ - EXECUTE_IF_SET_IN_REG_SET (join_bb->global_live_at_start, 0, regno, - { - if (regno < FIRST_PSEUDO_REGISTER) - CLEAR_HARD_REG_BIT (tmp_reg->regs, regno); - }); - } - - /* Add in all of the blocks in multiple &&/|| blocks to be scanned. */ - num_bb = 0; - if (ce_info->num_multiple_test_blocks) - { - basic_block multiple_test_bb = ce_info->last_test_bb; - - while (multiple_test_bb != test_bb) - { - bb[num_bb++] = multiple_test_bb; - multiple_test_bb = multiple_test_bb->pred->src; - } - } - - /* Add in the THEN and ELSE blocks to be scanned. */ - bb[num_bb++] = then_bb; - if (else_bb) - bb[num_bb++] = else_bb; - - sub_cond_exec_reg = NULL_RTX; - frv_ifcvt.num_nested_cond_exec = 0; - - /* Scan all of the blocks for registers that must not be allocated. */ - for (j = 0; j < num_bb; j++) - { - rtx last_insn = bb[j]->end; - rtx insn = bb[j]->head; - int regno; - - if (rtl_dump_file) - fprintf (rtl_dump_file, "Scanning %s block %d, start %d, end %d\n", - (bb[j] == else_bb) ? "else" : ((bb[j] == then_bb) ? "then" : "test"), - (int) bb[j]->index, - (int) INSN_UID (bb[j]->head), - (int) INSN_UID (bb[j]->end)); - - /* Anything live at the beginning of the block is obviously unavailable - for allocation. */ - EXECUTE_IF_SET_IN_REG_SET (bb[j]->global_live_at_start, 0, regno, - { - if (regno < FIRST_PSEUDO_REGISTER) - CLEAR_HARD_REG_BIT (tmp_reg->regs, regno); - }); - - /* loop through the insns in the block. */ - for (;;) - { - /* Mark any new registers that are created as being unavailable for - allocation. Also see if the CC register used in nested IFs can be - reallocated. */ - if (INSN_P (insn)) - { - rtx pattern; - rtx set; - int skip_nested_if = FALSE; - - for_each_rtx (&PATTERN (insn), frv_clear_registers_used, - (void *)&tmp_reg->regs); - - pattern = PATTERN (insn); - if (GET_CODE (pattern) == COND_EXEC) - { - rtx reg = XEXP (COND_EXEC_TEST (pattern), 0); - - if (reg != sub_cond_exec_reg) - { - sub_cond_exec_reg = reg; - frv_ifcvt.num_nested_cond_exec++; - } - } - - set = single_set_pattern (pattern); - if (set) - { - rtx dest = SET_DEST (set); - rtx src = SET_SRC (set); - - if (GET_CODE (dest) == REG) - { - int regno = REGNO (dest); - enum rtx_code src_code = GET_CODE (src); - - if (CC_P (regno) && src_code == COMPARE) - skip_nested_if = TRUE; - - else if (CR_P (regno) - && (src_code == IF_THEN_ELSE - || GET_RTX_CLASS (src_code) == '<')) - skip_nested_if = TRUE; - } - } - - if (! skip_nested_if) - for_each_rtx (&PATTERN (insn), frv_clear_registers_used, - (void *)&frv_ifcvt.nested_cc_ok_rewrite); - } - - if (insn == last_insn) - break; - - insn = NEXT_INSN (insn); - } - } - - /* If this is a nested if, rewrite the CC registers that are available to - include the ones that can be rewritten, to increase the chance of being - able to allocate a paired CC/CR register combination. */ - if (ce_info->pass > 1) - { - for (j = CC_FIRST; j <= CC_LAST; j++) - if (TEST_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, j)) - SET_HARD_REG_BIT (tmp_reg->regs, j); - else - CLEAR_HARD_REG_BIT (tmp_reg->regs, j); - } - - if (rtl_dump_file) - { - int num_gprs = 0; - fprintf (rtl_dump_file, "Available GPRs: "); - - for (j = GPR_FIRST; j <= GPR_LAST; j++) - if (TEST_HARD_REG_BIT (tmp_reg->regs, j)) - { - fprintf (rtl_dump_file, " %d [%s]", j, reg_names[j]); - if (++num_gprs > GPR_TEMP_NUM+2) - break; - } - - fprintf (rtl_dump_file, "%s\nAvailable CRs: ", - (num_gprs > GPR_TEMP_NUM+2) ? " ..." : ""); - - for (j = CR_FIRST; j <= CR_LAST; j++) - if (TEST_HARD_REG_BIT (tmp_reg->regs, j)) - fprintf (rtl_dump_file, " %d [%s]", j, reg_names[j]); - - fputs ("\n", rtl_dump_file); - - if (ce_info->pass > 1) - { - fprintf (rtl_dump_file, "Modifiable CCs: "); - for (j = CC_FIRST; j <= CC_LAST; j++) - if (TEST_HARD_REG_BIT (tmp_reg->regs, j)) - fprintf (rtl_dump_file, " %d [%s]", j, reg_names[j]); - - fprintf (rtl_dump_file, "\n%d nested COND_EXEC statements\n", - frv_ifcvt.num_nested_cond_exec); - } - } - - /* Allocate the appropriate temporary condition code register. Try to - allocate the ICR/FCR register that corresponds to the ICC/FCC register so - that conditional cmp's can be done. */ - if (mode == CCmode || mode == CC_UNSmode) - { - cr_class = ICR_REGS; - cc_class = ICC_REGS; - cc_first = ICC_FIRST; - cc_last = ICC_LAST; - } - else if (mode == CC_FPmode) - { - cr_class = FCR_REGS; - cc_class = FCC_REGS; - cc_first = FCC_FIRST; - cc_last = FCC_LAST; - } - else - { - cc_first = cc_last = 0; - cr_class = cc_class = NO_REGS; - } - - cc = XEXP (true_expr, 0); - nested_cc = cr = NULL_RTX; - if (cc_class != NO_REGS) - { - /* For nested IFs and &&/||, see if we can find a CC and CR register pair - so we can execute a csubcc/caddcc/cfcmps instruction. */ - int cc_regno; - - for (cc_regno = cc_first; cc_regno <= cc_last; cc_regno++) - { - int cr_regno = cc_regno - CC_FIRST + CR_FIRST; - - if (TEST_HARD_REG_BIT (frv_ifcvt.tmp_reg.regs, cc_regno) - && TEST_HARD_REG_BIT (frv_ifcvt.tmp_reg.regs, cr_regno)) - { - frv_ifcvt.tmp_reg.next_reg[ (int)cr_class ] = cr_regno; - cr = frv_alloc_temp_reg (tmp_reg, cr_class, CC_CCRmode, TRUE, - TRUE); - - frv_ifcvt.tmp_reg.next_reg[ (int)cc_class ] = cc_regno; - nested_cc = frv_alloc_temp_reg (tmp_reg, cc_class, CCmode, - TRUE, TRUE); - break; - } - } - } - - if (! cr) - { - if (rtl_dump_file) - fprintf (rtl_dump_file, "Could not allocate a CR temporary register\n"); - - goto fail; - } - - if (rtl_dump_file) - fprintf (rtl_dump_file, - "Will use %s for conditional execution, %s for nested comparisons\n", - reg_names[ REGNO (cr)], - (nested_cc) ? reg_names[ REGNO (nested_cc) ] : ""); - - /* Set the CCR bit. Note for integer tests, we reverse the condition so that - in an IF-THEN-ELSE sequence, we are testing the TRUE case against the CCR - bit being true. We don't do this for floating point, because of NaNs. */ - code = GET_CODE (true_expr); - if (GET_MODE (cc) != CC_FPmode) - { - code = reverse_condition (code); - code_true = EQ; - code_false = NE; - } - else - { - code_true = NE; - code_false = EQ; - } - - check_insn = gen_rtx_SET (VOIDmode, cr, - gen_rtx_fmt_ee (code, CC_CCRmode, cc, const0_rtx)); - - /* Record the check insn to be inserted later. */ - frv_ifcvt_add_insn (check_insn, test_bb->end, TRUE); - - /* Update the tests. */ - frv_ifcvt.cr_reg = cr; - frv_ifcvt.nested_cc_reg = nested_cc; - *p_true = gen_rtx_fmt_ee (code_true, CC_CCRmode, cr, const0_rtx); - *p_false = gen_rtx_fmt_ee (code_false, CC_CCRmode, cr, const0_rtx); - return; - - /* Fail, don't do this conditional execution. */ - fail: - *p_true = NULL_RTX; - *p_false = NULL_RTX; - if (rtl_dump_file) - fprintf (rtl_dump_file, "Disabling this conditional execution.\n"); - - return; -} - - -/* A C expression to modify the code described by the conditional if - information CE_INFO, for the basic block BB, possibly updating the tests in - TRUE_EXPR, and FALSE_EXPR for converting the && and || parts of if-then or - if-then-else code to conditional instructions. Set either TRUE_EXPR or - FALSE_EXPR to a null pointer if the tests cannot be converted. */ - -/* p_true and p_false are given expressions of the form: - - (and (eq:CC_CCR (reg:CC_CCR) - (const_int 0)) - (eq:CC (reg:CC) - (const_int 0))) */ - -void -frv_ifcvt_modify_multiple_tests (ce_info, bb, p_true, p_false) - ce_if_block_t *ce_info; - basic_block bb; - rtx *p_true; - rtx *p_false; -{ - rtx old_true = XEXP (*p_true, 0); - rtx old_false = XEXP (*p_false, 0); - rtx true_expr = XEXP (*p_true, 1); - rtx false_expr = XEXP (*p_false, 1); - rtx test_expr; - rtx old_test; - rtx cr = XEXP (old_true, 0); - rtx check_insn; - rtx new_cr = NULL_RTX; - rtx *p_new_cr = (rtx *)0; - rtx if_else; - rtx compare; - rtx cc; - enum reg_class cr_class; - enum machine_mode mode = GET_MODE (true_expr); - rtx (*logical_func)(rtx, rtx, rtx); - - if (TARGET_DEBUG_COND_EXEC) - { - fprintf (stderr, - "\n:::::::::: frv_ifcvt_modify_multiple_tests, before modification for %s\ntrue insn:\n", - ce_info->and_and_p ? "&&" : "||"); - - debug_rtx (*p_true); - - fputs ("\nfalse insn:\n", stderr); - debug_rtx (*p_false); - } - - if (TARGET_NO_MULTI_CE) - goto fail; - - if (GET_CODE (cr) != REG) - goto fail; - - if (mode == CCmode || mode == CC_UNSmode) - { - cr_class = ICR_REGS; - p_new_cr = &frv_ifcvt.extra_int_cr; - } - else if (mode == CC_FPmode) - { - cr_class = FCR_REGS; - p_new_cr = &frv_ifcvt.extra_fp_cr; - } - else - goto fail; - - /* Allocate a temp CR, reusing a previously allocated temp CR if we have 3 or - more &&/|| tests. */ - new_cr = *p_new_cr; - if (! new_cr) - { - new_cr = *p_new_cr = frv_alloc_temp_reg (&frv_ifcvt.tmp_reg, cr_class, - CC_CCRmode, TRUE, TRUE); - if (! new_cr) - goto fail; - } - - if (ce_info->and_and_p) - { - old_test = old_false; - test_expr = true_expr; - logical_func = (GET_CODE (old_true) == EQ) ? gen_andcr : gen_andncr; - *p_true = gen_rtx_NE (CC_CCRmode, cr, const0_rtx); - *p_false = gen_rtx_EQ (CC_CCRmode, cr, const0_rtx); - } - else - { - old_test = old_false; - test_expr = false_expr; - logical_func = (GET_CODE (old_false) == EQ) ? gen_orcr : gen_orncr; - *p_true = gen_rtx_EQ (CC_CCRmode, cr, const0_rtx); - *p_false = gen_rtx_NE (CC_CCRmode, cr, const0_rtx); - } - - /* First add the andcr/andncr/orcr/orncr, which will be added after the - conditional check instruction, due to frv_ifcvt_add_insn being a LIFO - stack. */ - frv_ifcvt_add_insn ((*logical_func) (cr, cr, new_cr), bb->end, TRUE); - - /* Now add the conditional check insn. */ - cc = XEXP (test_expr, 0); - compare = gen_rtx_fmt_ee (GET_CODE (test_expr), CC_CCRmode, cc, const0_rtx); - if_else = gen_rtx_IF_THEN_ELSE (CC_CCRmode, old_test, compare, const0_rtx); - - check_insn = gen_rtx_SET (VOIDmode, new_cr, if_else); - - /* add the new check insn to the list of check insns that need to be - inserted. */ - frv_ifcvt_add_insn (check_insn, bb->end, TRUE); - - if (TARGET_DEBUG_COND_EXEC) - { - fputs ("\n:::::::::: frv_ifcvt_modify_multiple_tests, after modification\ntrue insn:\n", - stderr); - - debug_rtx (*p_true); - - fputs ("\nfalse insn:\n", stderr); - debug_rtx (*p_false); - } - - return; - - fail: - *p_true = *p_false = NULL_RTX; - - /* If we allocated a CR register, release it. */ - if (new_cr) - { - CLEAR_HARD_REG_BIT (frv_ifcvt.tmp_reg.regs, REGNO (new_cr)); - *p_new_cr = NULL_RTX; - } - - if (TARGET_DEBUG_COND_EXEC) - fputs ("\n:::::::::: frv_ifcvt_modify_multiple_tests, failed.\n", stderr); - - return; -} - - -/* Return a register which will be loaded with a value if an IF block is - converted to conditional execution. This is used to rewrite instructions - that use constants to ones that just use registers. */ - -static rtx -frv_ifcvt_load_value (value, insn) - rtx value; - rtx insn ATTRIBUTE_UNUSED; -{ - int num_alloc = frv_ifcvt.cur_scratch_regs; - int i; - rtx reg; - - /* We know gr0 == 0, so replace any errant uses. */ - if (value == const0_rtx) - return gen_rtx_REG (SImode, GPR_FIRST); - - /* First search all registers currently loaded to see if we have an - applicable constant. */ - if (CONSTANT_P (value) - || (GET_CODE (value) == REG && REGNO (value) == LR_REGNO)) - { - for (i = 0; i < num_alloc; i++) - { - if (rtx_equal_p (SET_SRC (frv_ifcvt.scratch_regs[i]), value)) - return SET_DEST (frv_ifcvt.scratch_regs[i]); - } - } - - /* Have we exhausted the number of registers available? */ - if (num_alloc >= GPR_TEMP_NUM) - { - if (rtl_dump_file) - fprintf (rtl_dump_file, "Too many temporary registers allocated\n"); - - return NULL_RTX; - } - - /* Allocate the new register. */ - reg = frv_alloc_temp_reg (&frv_ifcvt.tmp_reg, GPR_REGS, SImode, TRUE, TRUE); - if (! reg) - { - if (rtl_dump_file) - fputs ("Could not find a scratch register\n", rtl_dump_file); - - return NULL_RTX; - } - - frv_ifcvt.cur_scratch_regs++; - frv_ifcvt.scratch_regs[num_alloc] = gen_rtx_SET (VOIDmode, reg, value); - - if (rtl_dump_file) - { - if (GET_CODE (value) == CONST_INT) - fprintf (rtl_dump_file, "Register %s will hold %ld\n", - reg_names[ REGNO (reg)], (long)INTVAL (value)); - - else if (GET_CODE (value) == REG && REGNO (value) == LR_REGNO) - fprintf (rtl_dump_file, "Register %s will hold LR\n", - reg_names[ REGNO (reg)]); - - else - fprintf (rtl_dump_file, "Register %s will hold a saved value\n", - reg_names[ REGNO (reg)]); - } - - return reg; -} - - -/* Update a MEM used in conditional code that might contain an offset to put - the offset into a scratch register, so that the conditional load/store - operations can be used. This function returns the original pointer if the - MEM is valid to use in conditional code, NULL if we can't load up the offset - into a temporary register, or the new MEM if we were successful. */ - -static rtx -frv_ifcvt_rewrite_mem (mem, mode, insn) - rtx mem; - enum machine_mode mode; - rtx insn; -{ - rtx addr = XEXP (mem, 0); - - if (!frv_legitimate_address_p (mode, addr, reload_completed, TRUE)) - { - if (GET_CODE (addr) == PLUS) - { - rtx addr_op0 = XEXP (addr, 0); - rtx addr_op1 = XEXP (addr, 1); - - if (plus_small_data_p (addr_op0, addr_op1)) - addr = frv_ifcvt_load_value (addr, insn); - - else if (GET_CODE (addr_op0) == REG && CONSTANT_P (addr_op1)) - { - rtx reg = frv_ifcvt_load_value (addr_op1, insn); - if (!reg) - return NULL_RTX; - - addr = gen_rtx_PLUS (Pmode, addr_op0, reg); - } - - else - return NULL_RTX; - } - - else if (CONSTANT_P (addr)) - addr = frv_ifcvt_load_value (addr, insn); - - else - return NULL_RTX; - - if (addr == NULL_RTX) - return NULL_RTX; - - else if (XEXP (mem, 0) != addr) - return change_address (mem, mode, addr); - } - - return mem; -} - - -/* Given a PATTERN, return a SET expression if this PATTERN has only a single - SET, possibly conditionally executed. It may also have CLOBBERs, USEs. */ - -static rtx -single_set_pattern (pattern) - rtx pattern; -{ - rtx set; - int i; - - if (GET_CODE (pattern) == COND_EXEC) - pattern = COND_EXEC_CODE (pattern); - - if (GET_CODE (pattern) == SET) - return pattern; - - else if (GET_CODE (pattern) == PARALLEL) - { - for (i = 0, set = 0; i < XVECLEN (pattern, 0); i++) - { - rtx sub = XVECEXP (pattern, 0, i); - - switch (GET_CODE (sub)) - { - case USE: - case CLOBBER: - break; - - case SET: - if (set) - return 0; - else - set = sub; - break; - - default: - return 0; - } - } - return set; - } - - return 0; -} - - -/* A C expression to modify the code described by the conditional if - information CE_INFO with the new PATTERN in INSN. If PATTERN is a null - pointer after the IFCVT_MODIFY_INSN macro executes, it is assumed that that - insn cannot be converted to be executed conditionally. */ - -rtx -frv_ifcvt_modify_insn (ce_info, pattern, insn) - ce_if_block_t *ce_info ATTRIBUTE_UNUSED; - rtx pattern; - rtx insn; -{ - rtx orig_ce_pattern = pattern; - rtx set; - rtx op0; - rtx op1; - rtx test; - - if (GET_CODE (pattern) != COND_EXEC) - abort (); - - test = COND_EXEC_TEST (pattern); - if (GET_CODE (test) == AND) - { - rtx cr = frv_ifcvt.cr_reg; - rtx test_reg; - - op0 = XEXP (test, 0); - if (! rtx_equal_p (cr, XEXP (op0, 0))) - goto fail; - - op1 = XEXP (test, 1); - test_reg = XEXP (op1, 0); - if (GET_CODE (test_reg) != REG) - goto fail; - - /* Is this the first nested if block in this sequence? If so, generate - an andcr or andncr. */ - if (! frv_ifcvt.last_nested_if_cr) - { - rtx and_op; - - frv_ifcvt.last_nested_if_cr = test_reg; - if (GET_CODE (op0) == NE) - and_op = gen_andcr (test_reg, cr, test_reg); - else - and_op = gen_andncr (test_reg, cr, test_reg); - - frv_ifcvt_add_insn (and_op, insn, TRUE); - } - - /* If this isn't the first statement in the nested if sequence, see if we - are dealing with the same register. */ - else if (! rtx_equal_p (test_reg, frv_ifcvt.last_nested_if_cr)) - goto fail; - - COND_EXEC_TEST (pattern) = test = op1; - } - - /* If this isn't a nested if, reset state variables. */ - else - { - frv_ifcvt.last_nested_if_cr = NULL_RTX; - } - - set = single_set_pattern (pattern); - if (set) - { - rtx dest = SET_DEST (set); - rtx src = SET_SRC (set); - enum machine_mode mode = GET_MODE (dest); - - /* Check for normal binary operators */ - if (mode == SImode - && (GET_RTX_CLASS (GET_CODE (src)) == '2' - || GET_RTX_CLASS (GET_CODE (src)) == 'c')) - { - op0 = XEXP (src, 0); - op1 = XEXP (src, 1); - - /* Special case load of small data address which looks like: - r16+symbol_ref */ - if (GET_CODE (src) == PLUS && plus_small_data_p (op0, op1)) - { - src = frv_ifcvt_load_value (src, insn); - if (src) - COND_EXEC_CODE (pattern) = gen_rtx_SET (VOIDmode, dest, src); - else - goto fail; - } - - else if (integer_register_operand (op0, SImode) && CONSTANT_P (op1)) - { - op1 = frv_ifcvt_load_value (op1, insn); - if (op1) - COND_EXEC_CODE (pattern) - = gen_rtx_SET (VOIDmode, dest, gen_rtx_fmt_ee (GET_CODE (src), - GET_MODE (src), - op0, op1)); - else - goto fail; - } - } - - /* For multiply by a constant, we need to handle the sign extending - correctly. Add a USE of the value after the multiply to prevent flow - from cratering because only one register out of the two were used. */ - else if (mode == DImode && GET_CODE (src) == MULT) - { - op0 = XEXP (src, 0); - op1 = XEXP (src, 1); - if (GET_CODE (op0) == SIGN_EXTEND && GET_CODE (op1) == CONST_INT) - { - op1 = frv_ifcvt_load_value (op1, insn); - if (op1) - { - op1 = gen_rtx_SIGN_EXTEND (DImode, op1); - COND_EXEC_CODE (pattern) - = gen_rtx_SET (VOIDmode, dest, - gen_rtx_MULT (DImode, op0, op1)); - } - else - goto fail; - } - - frv_ifcvt_add_insn (gen_rtx_USE (VOIDmode, dest), insn, FALSE); - } - - /* If we are just loading a constant created for a nested conditional - execution statement, just load the constant without any conditional - execution, since we know that the constant will not interfere with any - other registers. */ - else if (frv_ifcvt.scratch_insns_bitmap - && bitmap_bit_p (frv_ifcvt.scratch_insns_bitmap, - INSN_UID (insn))) - pattern = set; - - else if (mode == QImode || mode == HImode || mode == SImode - || mode == SFmode) - { - int changed_p = FALSE; - - /* Check for just loading up a constant */ - if (CONSTANT_P (src) && integer_register_operand (dest, mode)) - { - src = frv_ifcvt_load_value (src, insn); - if (!src) - goto fail; - - changed_p = TRUE; - } - - /* See if we need to fix up stores */ - if (GET_CODE (dest) == MEM) - { - rtx new_mem = frv_ifcvt_rewrite_mem (dest, mode, insn); - - if (!new_mem) - goto fail; - - else if (new_mem != dest) - { - changed_p = TRUE; - dest = new_mem; - } - } - - /* See if we need to fix up loads */ - if (GET_CODE (src) == MEM) - { - rtx new_mem = frv_ifcvt_rewrite_mem (src, mode, insn); - - if (!new_mem) - goto fail; - - else if (new_mem != src) - { - changed_p = TRUE; - src = new_mem; - } - } - - /* If either src or destination changed, redo SET. */ - if (changed_p) - COND_EXEC_CODE (pattern) = gen_rtx_SET (VOIDmode, dest, src); - } - - /* Rewrite a nested set cccr in terms of IF_THEN_ELSE. Also deal with - rewriting the CC register to be the same as the paired CC/CR register - for nested ifs. */ - else if (mode == CC_CCRmode && GET_RTX_CLASS (GET_CODE (src)) == '<') - { - int regno = REGNO (XEXP (src, 0)); - rtx if_else; - - if (ce_info->pass > 1 - && regno != (int)REGNO (frv_ifcvt.nested_cc_reg) - && TEST_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, regno)) - { - src = gen_rtx_fmt_ee (GET_CODE (src), - CC_CCRmode, - frv_ifcvt.nested_cc_reg, - XEXP (src, 1)); - } - - if_else = gen_rtx_IF_THEN_ELSE (CC_CCRmode, test, src, const0_rtx); - pattern = gen_rtx_SET (VOIDmode, dest, if_else); - } - - /* Remap a nested compare instruction to use the paired CC/CR reg. */ - else if (ce_info->pass > 1 - && GET_CODE (dest) == REG - && CC_P (REGNO (dest)) - && REGNO (dest) != REGNO (frv_ifcvt.nested_cc_reg) - && TEST_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, - REGNO (dest)) - && GET_CODE (src) == COMPARE) - { - PUT_MODE (frv_ifcvt.nested_cc_reg, GET_MODE (dest)); - COND_EXEC_CODE (pattern) - = gen_rtx_SET (VOIDmode, frv_ifcvt.nested_cc_reg, copy_rtx (src)); - } - } - - if (TARGET_DEBUG_COND_EXEC) - { - rtx orig_pattern = PATTERN (insn); - - PATTERN (insn) = pattern; - fprintf (stderr, - "\n:::::::::: frv_ifcvt_modify_insn: pass = %d, insn after modification:\n", - ce_info->pass); - - debug_rtx (insn); - PATTERN (insn) = orig_pattern; - } - - return pattern; - - fail: - if (TARGET_DEBUG_COND_EXEC) - { - rtx orig_pattern = PATTERN (insn); - - PATTERN (insn) = orig_ce_pattern; - fprintf (stderr, - "\n:::::::::: frv_ifcvt_modify_insn: pass = %d, insn could not be modified:\n", - ce_info->pass); - - debug_rtx (insn); - PATTERN (insn) = orig_pattern; - } - - return NULL_RTX; -} - - -/* A C expression to perform any final machine dependent modifications in - converting code to conditional execution in the code described by the - conditional if information CE_INFO. */ - -void -frv_ifcvt_modify_final (ce_info) - ce_if_block_t *ce_info ATTRIBUTE_UNUSED; -{ - rtx existing_insn; - rtx check_insn; - rtx p = frv_ifcvt.added_insns_list; - int i; - - /* Loop inserting the check insns. The last check insn is the first test, - and is the appropriate place to insert constants. */ - if (! p) - abort (); - - do - { - rtx check_and_insert_insns = XEXP (p, 0); - rtx old_p = p; - - check_insn = XEXP (check_and_insert_insns, 0); - existing_insn = XEXP (check_and_insert_insns, 1); - p = XEXP (p, 1); - - /* The jump bit is used to say that the new insn is to be inserted BEFORE - the existing insn, otherwise it is to be inserted AFTER. */ - if (check_and_insert_insns->jump) - { - emit_insn_before (check_insn, existing_insn); - check_and_insert_insns->jump = 0; - } - else - emit_insn_after (check_insn, existing_insn); - - free_EXPR_LIST_node (check_and_insert_insns); - free_EXPR_LIST_node (old_p); - } - while (p != NULL_RTX); - - /* Load up any constants needed into temp gprs */ - for (i = 0; i < frv_ifcvt.cur_scratch_regs; i++) - { - rtx insn = emit_insn_before (frv_ifcvt.scratch_regs[i], existing_insn); - if (! frv_ifcvt.scratch_insns_bitmap) - frv_ifcvt.scratch_insns_bitmap = BITMAP_XMALLOC (); - bitmap_set_bit (frv_ifcvt.scratch_insns_bitmap, INSN_UID (insn)); - frv_ifcvt.scratch_regs[i] = NULL_RTX; - } - - frv_ifcvt.added_insns_list = NULL_RTX; - frv_ifcvt.cur_scratch_regs = 0; -} - - -/* A C expression to cancel any machine dependent modifications in converting - code to conditional execution in the code described by the conditional if - information CE_INFO. */ - -void -frv_ifcvt_modify_cancel (ce_info) - ce_if_block_t *ce_info ATTRIBUTE_UNUSED; -{ - int i; - rtx p = frv_ifcvt.added_insns_list; - - /* Loop freeing up the EXPR_LIST's allocated. */ - while (p != NULL_RTX) - { - rtx check_and_jump = XEXP (p, 0); - rtx old_p = p; - - p = XEXP (p, 1); - free_EXPR_LIST_node (check_and_jump); - free_EXPR_LIST_node (old_p); - } - - /* Release any temporary gprs allocated. */ - for (i = 0; i < frv_ifcvt.cur_scratch_regs; i++) - frv_ifcvt.scratch_regs[i] = NULL_RTX; - - frv_ifcvt.added_insns_list = NULL_RTX; - frv_ifcvt.cur_scratch_regs = 0; - return; -} - -/* A C expression for the size in bytes of the trampoline, as an integer. - The template is: - - setlo #0, - setlo #0, - sethi #0, - sethi #0, - jmpl @(gr0,) */ - -int -frv_trampoline_size () -{ - return 5 /* instructions */ * 4 /* instruction size */; -} - - -/* 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. - - The template is: - - setlo #0, - setlo #0, - sethi #0, - sethi #0, - jmpl @(gr0,) */ - -void -frv_initialize_trampoline (addr, fnaddr, static_chain) - rtx addr; - rtx fnaddr; - rtx static_chain; -{ - rtx sc_reg = force_reg (Pmode, static_chain); - - emit_library_call (gen_rtx_SYMBOL_REF (SImode, "__trampoline_setup"), - FALSE, VOIDmode, 4, - addr, Pmode, - GEN_INT (frv_trampoline_size ()), SImode, - fnaddr, Pmode, - sc_reg, Pmode); -} - - -/* 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. */ - -enum reg_class -frv_secondary_reload_class (class, mode, x, in_p) - enum reg_class class; - enum machine_mode mode ATTRIBUTE_UNUSED; - rtx x; - int in_p ATTRIBUTE_UNUSED; -{ - enum reg_class ret; - - switch (class) - { - default: - ret = NO_REGS; - break; - - /* Accumulators/Accumulator guard registers need to go through floating - point registers. */ - case QUAD_REGS: - case EVEN_REGS: - case GPR_REGS: - ret = NO_REGS; - if (x && GET_CODE (x) == REG) - { - int regno = REGNO (x); - - if (ACC_P (regno) || ACCG_P (regno)) - ret = FPR_REGS; - } - break; - - /* Non-zero constants should be loaded into an FPR through a GPR. */ - case QUAD_FPR_REGS: - case FEVEN_REGS: - case FPR_REGS: - if (x && CONSTANT_P (x) && !ZERO_P (x)) - ret = GPR_REGS; - else - ret = NO_REGS; - break; - - /* All of these types need gpr registers. */ - case ICC_REGS: - case FCC_REGS: - case CC_REGS: - case ICR_REGS: - case FCR_REGS: - case CR_REGS: - case LCR_REG: - case LR_REG: - ret = GPR_REGS; - break; - - /* The accumulators need fpr registers */ - case ACC_REGS: - case EVEN_ACC_REGS: - case QUAD_ACC_REGS: - case ACCG_REGS: - ret = FPR_REGS; - break; - } - - return ret; -} - - -/* 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. */ - -int -frv_class_likely_spilled_p (class) - enum reg_class class; -{ - switch (class) - { - default: - break; - - case ICC_REGS: - case FCC_REGS: - case CC_REGS: - case ICR_REGS: - case FCR_REGS: - case CR_REGS: - case LCR_REG: - case LR_REG: - case SPR_REGS: - case QUAD_ACC_REGS: - case EVEN_ACC_REGS: - case ACC_REGS: - case ACCG_REGS: - return TRUE; - } - - return FALSE; -} - - -/* 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. */ - -/* The definition type of the bit field data is either char, short, long or - long long. The maximum bit size is the number of bits of its own type. - - The bit field data is assigned to a storage unit that has an adequate size - for bit field data retention and is located at the smallest address. - - Consecutive bit field data are packed at consecutive bits having the same - storage unit, with regard to the type, beginning with the MSB and continuing - toward the LSB. - - If a field to be assigned lies over a bit field type boundary, its - assignment is completed by aligning it with a boundary suitable for the - type. - - When a bit field having a bit length of 0 is declared, it is forcibly - assigned to the next storage unit. - - e.g) - struct { - int a:2; - int b:6; - char c:4; - int d:10; - int :0; - int f:2; - } x; - - +0 +1 +2 +3 - &x 00000000 00000000 00000000 00000000 - MLM----L - a b - &x+4 00000000 00000000 00000000 00000000 - M--L - c - &x+8 00000000 00000000 00000000 00000000 - M----------L - d - &x+12 00000000 00000000 00000000 00000000 - ML - f -*/ - -int -frv_adjust_field_align (field, computed) - tree field; - int computed; -{ - /* C++ provides a null DECL_CONTEXT if the bit field is wider than its - type. */ - if (DECL_BIT_FIELD (field) && DECL_CONTEXT (field)) - { - tree parent = DECL_CONTEXT (field); - tree prev = NULL_TREE; - tree cur; - - /* Loop finding the previous field to the current one */ - for (cur = TYPE_FIELDS (parent); cur && cur != field; cur = TREE_CHAIN (cur)) - { - if (TREE_CODE (cur) != FIELD_DECL) - continue; - - prev = cur; - } - - if (!cur) - abort (); - - /* If this isn't a :0 field and if the previous element is a bitfield - also, see if the type is different, if so, we will need to align the - bitfield to the next boundary */ - if (prev - && ! DECL_PACKED (field) - && ! integer_zerop (DECL_SIZE (field)) - && DECL_BIT_FIELD_TYPE (field) != DECL_BIT_FIELD_TYPE (prev)) - { - int prev_align = TYPE_ALIGN (TREE_TYPE (prev)); - int cur_align = TYPE_ALIGN (TREE_TYPE (field)); - computed = (prev_align > cur_align) ? prev_align : cur_align; - } - } - - return computed; -} - - -/* 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. */ - -int -frv_hard_regno_mode_ok (regno, mode) - int regno; - enum machine_mode mode; -{ - int base; - int mask; - - switch (mode) - { - case CCmode: - case CC_UNSmode: - return ICC_P (regno) || GPR_P (regno); - - case CC_CCRmode: - return CR_P (regno) || GPR_P (regno); - - case CC_FPmode: - return FCC_P (regno) || GPR_P (regno); - - default: - break; - } - - /* Set BASE to the first register in REGNO's class. Set MASK to the - bits that must be clear in (REGNO - BASE) for the register to be - well-aligned. */ - if (INTEGRAL_MODE_P (mode) || FLOAT_MODE_P (mode) || VECTOR_MODE_P (mode)) - { - if (ACCG_P (regno)) - { - /* ACCGs store one byte. Two-byte quantities must start in - even-numbered registers, four-byte ones in registers whose - numbers are divisible by four, and so on. */ - base = ACCG_FIRST; - mask = GET_MODE_SIZE (mode) - 1; - } - else - { - /* The other registers store one word. */ - if (GPR_P (regno)) - base = GPR_FIRST; - - else if (FPR_P (regno)) - base = FPR_FIRST; - - else if (ACC_P (regno)) - base = ACC_FIRST; - - else - return 0; - - /* Anything smaller than an SI is OK in any word-sized register. */ - if (GET_MODE_SIZE (mode) < 4) - return 1; - - mask = (GET_MODE_SIZE (mode) / 4) - 1; - } - return (((regno - base) & mask) == 0); - } - - return 0; -} - - -/* 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)) */ - -/* On the FRV, make the CC_FP mode take 3 words in the integer registers, so - that we can build the appropriate instructions to properly reload the - values. Also, make the byte-sized accumulator guards use one guard - for each byte. */ - -int -frv_hard_regno_nregs (regno, mode) - int regno; - enum machine_mode mode; -{ - if (ACCG_P (regno)) - return GET_MODE_SIZE (mode); - else - return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; -} - - -/* 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. - - This declaration is required. */ - -int -frv_class_max_nregs (class, mode) - enum reg_class class; - enum machine_mode mode; -{ - if (class == ACCG_REGS) - /* An N-byte value requires N accumulator guards. */ - return GET_MODE_SIZE (mode); - else - return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; -} - - -/* 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. */ - -int -frv_legitimate_constant_p (x) - rtx x; -{ - enum machine_mode mode = GET_MODE (x); - - /* All of the integer constants are ok */ - if (GET_CODE (x) != CONST_DOUBLE) - return TRUE; - - /* double integer constants are ok */ - if (mode == VOIDmode || mode == DImode) - return TRUE; - - /* 0 is always ok */ - if (x == CONST0_RTX (mode)) - return TRUE; - - /* If floating point is just emulated, allow any constant, since it will be - constructed in the GPRs */ - if (!TARGET_HAS_FPRS) - return TRUE; - - if (mode == DFmode && !TARGET_DOUBLE) - return TRUE; - - /* Otherwise store the constant away and do a load. */ - return FALSE; -} - -/* 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 HIGH_COST 40 -#define MEDIUM_COST 3 -#define LOW_COST 1 - -int -frv_register_move_cost (from, to) - enum reg_class from; - enum reg_class to; -{ - switch (from) - { - default: - break; - - case QUAD_REGS: - case EVEN_REGS: - case GPR_REGS: - switch (to) - { - default: - break; - - case QUAD_REGS: - case EVEN_REGS: - case GPR_REGS: - return LOW_COST; - - case FEVEN_REGS: - case FPR_REGS: - return LOW_COST; - - case LCR_REG: - case LR_REG: - case SPR_REGS: - return LOW_COST; - } - - case FEVEN_REGS: - case FPR_REGS: - switch (to) - { - default: - break; - - case QUAD_REGS: - case EVEN_REGS: - case GPR_REGS: - case ACC_REGS: - case EVEN_ACC_REGS: - case QUAD_ACC_REGS: - case ACCG_REGS: - return MEDIUM_COST; - - case FEVEN_REGS: - case FPR_REGS: - return LOW_COST; - } - - case LCR_REG: - case LR_REG: - case SPR_REGS: - switch (to) - { - default: - break; - - case QUAD_REGS: - case EVEN_REGS: - case GPR_REGS: - return MEDIUM_COST; - } - - case ACC_REGS: - case EVEN_ACC_REGS: - case QUAD_ACC_REGS: - case ACCG_REGS: - switch (to) - { - default: - break; - - case FEVEN_REGS: - case FPR_REGS: - return MEDIUM_COST; - - } - } - - return HIGH_COST; -} - -/* Implementation of TARGET_ASM_INTEGER. In the FRV case we need to - use ".picptr" to generate safe relocations for PIC code. We also - need a fixup entry for aligned (non-debugging) code. */ - -static bool -frv_assemble_integer (value, size, aligned_p) - rtx value; - unsigned int size; - int aligned_p; -{ - if (flag_pic && size == UNITS_PER_WORD) - { - if (GET_CODE (value) == CONST - || GET_CODE (value) == SYMBOL_REF - || GET_CODE (value) == LABEL_REF) - { - if (aligned_p) - { - static int label_num = 0; - char buf[256]; - const char *p; - - ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", label_num++); - p = (* targetm.strip_name_encoding) (buf); - - fprintf (asm_out_file, "%s:\n", p); - fprintf (asm_out_file, "%s\n", FIXUP_SECTION_ASM_OP); - fprintf (asm_out_file, "\t.picptr\t%s\n", p); - fprintf (asm_out_file, "\t.previous\n"); - } - assemble_integer_with_op ("\t.picptr\t", value); - return true; - } - if (!aligned_p) - { - /* We've set the unaligned SI op to NULL, so we always have to - handle the unaligned case here. */ - assemble_integer_with_op ("\t.4byte\t", value); - return true; - } - } - return default_assemble_integer (value, size, aligned_p); -} - -/* Function to set up the backend function structure. */ - -static struct machine_function * -frv_init_machine_status () -{ - return ggc_alloc_cleared (sizeof (struct machine_function)); -} - - -/* Update the register state information, to know about which registers are set - or clobbered. */ - -static void -frv_registers_update (x, reg_state, modified, p_num_mod, flag) - rtx x; - unsigned char reg_state[]; - int modified[]; - int *p_num_mod; - int flag; -{ - int regno, reg_max; - rtx reg; - rtx cond; - const char *format; - int length; - int j; - - switch (GET_CODE (x)) - { - default: - break; - - /* Clobber just modifies a register, it doesn't make it live. */ - case CLOBBER: - frv_registers_update (XEXP (x, 0), reg_state, modified, p_num_mod, - flag | REGSTATE_MODIFIED); - return; - - /* Pre modify updates the first argument, just references the second. */ - case PRE_MODIFY: - case SET: - frv_registers_update (XEXP (x, 0), reg_state, modified, p_num_mod, - flag | REGSTATE_MODIFIED | REGSTATE_LIVE); - frv_registers_update (XEXP (x, 1), reg_state, modified, p_num_mod, flag); - return; - - /* For COND_EXEC, pass the appropriate flag to evaluate the conditional - statement, but just to be sure, make sure it is the type of cond_exec - we expect. */ - case COND_EXEC: - cond = XEXP (x, 0); - if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE) - && GET_CODE (XEXP (cond, 0)) == REG - && CR_P (REGNO (XEXP (cond, 0))) - && GET_CODE (XEXP (cond, 1)) == CONST_INT - && INTVAL (XEXP (cond, 1)) == 0 - && (flag & (REGSTATE_MODIFIED | REGSTATE_IF_EITHER)) == 0) - { - frv_registers_update (cond, reg_state, modified, p_num_mod, flag); - flag |= ((REGNO (XEXP (cond, 0)) - CR_FIRST) - | ((GET_CODE (cond) == NE) - ? REGSTATE_IF_TRUE - : REGSTATE_IF_FALSE)); - - frv_registers_update (XEXP (x, 1), reg_state, modified, p_num_mod, - flag); - return; - } - else - fatal_insn ("frv_registers_update", x); - - /* MEM resets the modification bits. */ - case MEM: - flag &= ~REGSTATE_MODIFIED; - break; - - /* See if we need to set the modified flag. */ - case SUBREG: - reg = SUBREG_REG (x); - if (GET_CODE (reg) == REG) - { - regno = subreg_regno (x); - reg_max = REGNO (reg) + HARD_REGNO_NREGS (regno, GET_MODE (reg)); - goto reg_common; - } - break; - - case REG: - regno = REGNO (x); - reg_max = regno + HARD_REGNO_NREGS (regno, GET_MODE (x)); - /* fall through */ - - reg_common: - if (flag & REGSTATE_MODIFIED) - { - flag &= REGSTATE_MASK; - while (regno < reg_max) - { - int rs = reg_state[regno]; - - if (flag != rs) - { - if ((rs & REGSTATE_MODIFIED) == 0) - { - modified[ *p_num_mod ] = regno; - (*p_num_mod)++; - } - - /* If the previous register state had the register as - modified, possibly in some conditional execution context, - and the current insn modifies in some other context, or - outside of conditional execution, just mark the variable - as modified. */ - else - flag &= ~(REGSTATE_IF_EITHER | REGSTATE_CC_MASK); - - reg_state[regno] = (rs | flag); - } - regno++; - } - } - return; - } - - - length = GET_RTX_LENGTH (GET_CODE (x)); - format = GET_RTX_FORMAT (GET_CODE (x)); - - for (j = 0; j < length; ++j) - { - switch (format[j]) - { - case 'e': - frv_registers_update (XEXP (x, j), reg_state, modified, p_num_mod, - flag); - break; - - case 'V': - case 'E': - if (XVEC (x, j) != 0) - { - int k; - for (k = 0; k < XVECLEN (x, j); ++k) - frv_registers_update (XVECEXP (x, j, k), reg_state, modified, - p_num_mod, flag); - } - break; - - default: - /* Nothing to do. */ - break; - } - } - - return; -} - - -/* Return if any registers in a hard register set were used an insn. */ - -static int -frv_registers_used_p (x, reg_state, flag) - rtx x; - unsigned char reg_state[]; - int flag; -{ - int regno, reg_max; - rtx reg; - rtx cond; - rtx dest; - const char *format; - int result; - int length; - int j; - - switch (GET_CODE (x)) - { - default: - break; - - /* Skip clobber, that doesn't use the previous value */ - case CLOBBER: - return FALSE; - - /* For SET, if a conditional jump has occurred in the same insn, only - allow a set of a CR register if that register is not currently live. - This is because on the FR-V, B0/B1 instructions are always last. - Otherwise, don't look at the result, except within a MEM, but do look - at the source. */ - case SET: - dest = SET_DEST (x); - if (flag & REGSTATE_CONDJUMP - && GET_CODE (dest) == REG && CR_P (REGNO (dest)) - && (reg_state[ REGNO (dest) ] & REGSTATE_LIVE) != 0) - return TRUE; - - if (GET_CODE (dest) == MEM) - { - result = frv_registers_used_p (XEXP (dest, 0), reg_state, flag); - if (result) - return result; - } - - return frv_registers_used_p (SET_SRC (x), reg_state, flag); - - /* For COND_EXEC, pass the appropriate flag to evaluate the conditional - statement, but just to be sure, make sure it is the type of cond_exec - we expect. */ - case COND_EXEC: - cond = XEXP (x, 0); - if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE) - && GET_CODE (XEXP (cond, 0)) == REG - && CR_P (REGNO (XEXP (cond, 0))) - && GET_CODE (XEXP (cond, 1)) == CONST_INT - && INTVAL (XEXP (cond, 1)) == 0 - && (flag & (REGSTATE_MODIFIED | REGSTATE_IF_EITHER)) == 0) - { - result = frv_registers_used_p (cond, reg_state, flag); - if (result) - return result; - - flag |= ((REGNO (XEXP (cond, 0)) - CR_FIRST) - | ((GET_CODE (cond) == NE) - ? REGSTATE_IF_TRUE - : REGSTATE_IF_FALSE)); - - return frv_registers_used_p (XEXP (x, 1), reg_state, flag); - } - else - fatal_insn ("frv_registers_used_p", x); - - /* See if a register or subreg was modified in the same VLIW insn. */ - case SUBREG: - reg = SUBREG_REG (x); - if (GET_CODE (reg) == REG) - { - regno = subreg_regno (x); - reg_max = REGNO (reg) + HARD_REGNO_NREGS (regno, GET_MODE (reg)); - goto reg_common; - } - break; - - case REG: - regno = REGNO (x); - reg_max = regno + HARD_REGNO_NREGS (regno, GET_MODE (x)); - /* fall through */ - - reg_common: - while (regno < reg_max) - { - int rs = reg_state[regno]; - - if (rs & REGSTATE_MODIFIED) - { - int rs_if = rs & REGSTATE_IF_EITHER; - int flag_if = flag & REGSTATE_IF_EITHER; - - /* Simple modification, no conditional execution */ - if ((rs & REGSTATE_IF_EITHER) == 0) - return TRUE; - - /* See if the variable is only modified in a conditional - execution expression opposite to the conditional execution - expression that governs this expression (ie, true vs. false - for the same CC register). If this isn't two halves of the - same conditional expression, consider the register - modified. */ - if (((rs_if == REGSTATE_IF_TRUE && flag_if == REGSTATE_IF_FALSE) - || (rs_if == REGSTATE_IF_FALSE && flag_if == REGSTATE_IF_TRUE)) - && ((rs & REGSTATE_CC_MASK) == (flag & REGSTATE_CC_MASK))) - ; - else - return TRUE; - } - - regno++; - } - return FALSE; - } - - - length = GET_RTX_LENGTH (GET_CODE (x)); - format = GET_RTX_FORMAT (GET_CODE (x)); - - for (j = 0; j < length; ++j) - { - switch (format[j]) - { - case 'e': - result = frv_registers_used_p (XEXP (x, j), reg_state, flag); - if (result != 0) - return result; - break; - - case 'V': - case 'E': - if (XVEC (x, j) != 0) - { - int k; - for (k = 0; k < XVECLEN (x, j); ++k) - { - result = frv_registers_used_p (XVECEXP (x, j, k), reg_state, - flag); - if (result != 0) - return result; - } - } - break; - - default: - /* Nothing to do. */ - break; - } - } - - return 0; -} - -/* Return if any registers in a hard register set were set in an insn. */ - -static int -frv_registers_set_p (x, reg_state, modify_p) - rtx x; - unsigned char reg_state[]; - int modify_p; -{ - int regno, reg_max; - rtx reg; - rtx cond; - const char *format; - int length; - int j; - - switch (GET_CODE (x)) - { - default: - break; - - case CLOBBER: - return frv_registers_set_p (XEXP (x, 0), reg_state, TRUE); - - case PRE_MODIFY: - case SET: - return (frv_registers_set_p (XEXP (x, 0), reg_state, TRUE) - || frv_registers_set_p (XEXP (x, 1), reg_state, FALSE)); - - case COND_EXEC: - cond = XEXP (x, 0); - /* just to be sure, make sure it is the type of cond_exec we - expect. */ - if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE) - && GET_CODE (XEXP (cond, 0)) == REG - && CR_P (REGNO (XEXP (cond, 0))) - && GET_CODE (XEXP (cond, 1)) == CONST_INT - && INTVAL (XEXP (cond, 1)) == 0 - && !modify_p) - return frv_registers_set_p (XEXP (x, 1), reg_state, modify_p); - else - fatal_insn ("frv_registers_set_p", x); - - /* MEM resets the modification bits. */ - case MEM: - modify_p = FALSE; - break; - - /* See if we need to set the modified modify_p. */ - case SUBREG: - reg = SUBREG_REG (x); - if (GET_CODE (reg) == REG) - { - regno = subreg_regno (x); - reg_max = REGNO (reg) + HARD_REGNO_NREGS (regno, GET_MODE (reg)); - goto reg_common; - } - break; - - case REG: - regno = REGNO (x); - reg_max = regno + HARD_REGNO_NREGS (regno, GET_MODE (x)); - /* fall through */ - - reg_common: - if (modify_p) - while (regno < reg_max) - { - int rs = reg_state[regno]; - - if (rs & REGSTATE_MODIFIED) - return TRUE; - regno++; - } - return FALSE; - } - - - length = GET_RTX_LENGTH (GET_CODE (x)); - format = GET_RTX_FORMAT (GET_CODE (x)); - - for (j = 0; j < length; ++j) - { - switch (format[j]) - { - case 'e': - if (frv_registers_set_p (XEXP (x, j), reg_state, modify_p)) - return TRUE; - break; - - case 'V': - case 'E': - if (XVEC (x, j) != 0) - { - int k; - for (k = 0; k < XVECLEN (x, j); ++k) - if (frv_registers_set_p (XVECEXP (x, j, k), reg_state, - modify_p)) - return TRUE; - } - break; - - default: - /* Nothing to do. */ - break; - } - } - - return FALSE; -} - - -/* 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. */ - -/* On the FR-V, this pass is used to rescan the insn chain, and pack - conditional branches/calls/jumps, etc. with previous insns where it can. It - does not reorder the instructions. We assume the scheduler left the flow - information in a reasonable state. */ - -static void -frv_pack_insns () -{ - state_t frv_state; /* frv state machine */ - int cur_start_vliw_p; /* current insn starts a VLIW insn */ - int next_start_vliw_p; /* next insn starts a VLIW insn */ - int cur_condjump_p; /* flag if current insn is a cond jump*/ - int next_condjump_p; /* flag if next insn is a cond jump */ - rtx insn; - rtx link; - int j; - int num_mod = 0; /* # of modified registers */ - int modified[FIRST_PSEUDO_REGISTER]; /* registers modified in current VLIW */ - /* register state information */ - unsigned char reg_state[FIRST_PSEUDO_REGISTER]; - - /* If we weren't going to pack the insns, don't bother with this pass. */ - if (!optimize || !flag_schedule_insns_after_reload || TARGET_NO_VLIW_BRANCH) - return; - - switch (frv_cpu_type) - { - default: - case FRV_CPU_FR300: /* FR300/simple are single issue */ - case FRV_CPU_SIMPLE: - return; - - case FRV_CPU_GENERIC: /* FR-V and FR500 are multi-issue */ - case FRV_CPU_FR400: - case FRV_CPU_FR500: - case FRV_CPU_TOMCAT: - break; - } - - /* Set up the instruction and register states. */ - dfa_start (); - frv_state = (state_t) xmalloc (state_size ()); - memset ((PTR) reg_state, REGSTATE_DEAD, sizeof (reg_state)); - - /* Go through the insns, and repack the insns. */ - state_reset (frv_state); - cur_start_vliw_p = FALSE; - next_start_vliw_p = TRUE; - cur_condjump_p = 0; - next_condjump_p = 0; - - for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn)) - { - enum rtx_code code = GET_CODE (insn); - enum rtx_code pattern_code; - - /* For basic block begin notes redo the live information, and skip other - notes. */ - if (code == NOTE) - { - if (NOTE_LINE_NUMBER (insn) == (int)NOTE_INSN_BASIC_BLOCK) - { - regset live; - - for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) - reg_state[j] &= ~ REGSTATE_LIVE; - - live = NOTE_BASIC_BLOCK (insn)->global_live_at_start; - EXECUTE_IF_SET_IN_REG_SET(live, 0, j, - { - reg_state[j] |= REGSTATE_LIVE; - }); - } - - continue; - } - - /* things like labels reset everything. */ - if (GET_RTX_CLASS (code) != 'i') - { - next_start_vliw_p = TRUE; - continue; - } - - /* Clear the VLIW start flag on random USE and CLOBBER insns, which is - set on the USE insn that preceeds the return, and potentially on - CLOBBERs for setting multiword variables. Also skip the ADDR_VEC - holding the case table labels. */ - pattern_code = GET_CODE (PATTERN (insn)); - if (pattern_code == USE || pattern_code == CLOBBER - || pattern_code == ADDR_VEC || pattern_code == ADDR_DIFF_VEC) - { - CLEAR_VLIW_START (insn); - continue; - } - - cur_start_vliw_p = next_start_vliw_p; - next_start_vliw_p = FALSE; - - cur_condjump_p |= next_condjump_p; - next_condjump_p = 0; - - /* Unconditional branches and calls end the current VLIW insn. */ - if (code == CALL_INSN) - { - next_start_vliw_p = TRUE; - - /* On a TOMCAT, calls must be alone in the VLIW insns. */ - if (frv_cpu_type == FRV_CPU_TOMCAT) - cur_start_vliw_p = TRUE; - } - else if (code == JUMP_INSN) - { - if (any_condjump_p (insn)) - next_condjump_p = REGSTATE_CONDJUMP; - else - next_start_vliw_p = TRUE; - } - - /* Only allow setting a CCR register after a conditional branch. */ - else if (((cur_condjump_p & REGSTATE_CONDJUMP) != 0) - && get_attr_type (insn) != TYPE_CCR) - cur_start_vliw_p = TRUE; - - /* Determine if we need to start a new VLIW instruction. */ - if (cur_start_vliw_p - /* Do not check for register conflicts in a setlo instruction - because any output or true dependencies will be with the - partnering sethi instruction, with which it can be packed. - - Although output dependencies are rare they are still - possible. So check output dependencies in VLIW insn. */ - || (get_attr_type (insn) != TYPE_SETLO - && (frv_registers_used_p (PATTERN (insn), - reg_state, - cur_condjump_p) - || frv_registers_set_p (PATTERN (insn), reg_state, FALSE))) - || state_transition (frv_state, insn) >= 0) - { - SET_VLIW_START (insn); - state_reset (frv_state); - state_transition (frv_state, insn); - cur_condjump_p = 0; - - /* Update the modified registers. */ - for (j = 0; j < num_mod; j++) - reg_state[ modified[j] ] &= ~(REGSTATE_CC_MASK - | REGSTATE_IF_EITHER - | REGSTATE_MODIFIED); - - num_mod = 0; - } - else - CLEAR_VLIW_START (insn); - - /* Record which registers are modified. */ - frv_registers_update (PATTERN (insn), reg_state, modified, &num_mod, 0); - - /* Process the death notices */ - for (link = REG_NOTES (insn); - link != NULL_RTX; - link = XEXP (link, 1)) - { - rtx reg = XEXP (link, 0); - - if (REG_NOTE_KIND (link) == REG_DEAD && GET_CODE (reg) == REG) - { - int regno = REGNO (reg); - int n = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg)); - for (; regno < n; regno++) - reg_state[regno] &= ~REGSTATE_LIVE; - } - } - } - - free ((PTR) frv_state); - dfa_finish (); - return; -} - - -#define def_builtin(name, type, code) \ - builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL) - -struct builtin_description -{ - enum insn_code icode; - const char *name; - enum frv_builtins code; - enum rtx_code comparison; - unsigned int flag; -}; - -/* Media intrinsics that take a single, constant argument. */ - -static struct builtin_description bdesc_set[] = -{ - { CODE_FOR_mhdsets, "__MHDSETS", FRV_BUILTIN_MHDSETS, 0, 0 } -}; - -/* Media intrinsics that take just one argument. */ - -static struct builtin_description bdesc_1arg[] = -{ - { CODE_FOR_mnot, "__MNOT", FRV_BUILTIN_MNOT, 0, 0 }, - { CODE_FOR_munpackh, "__MUNPACKH", FRV_BUILTIN_MUNPACKH, 0, 0 }, - { CODE_FOR_mbtoh, "__MBTOH", FRV_BUILTIN_MBTOH, 0, 0 }, - { CODE_FOR_mhtob, "__MHTOB", FRV_BUILTIN_MHTOB, 0, 0 }, - { CODE_FOR_mabshs, "__MABSHS", FRV_BUILTIN_MABSHS, 0, 0 } -}; - -/* Media intrinsics that take two arguments. */ - -static struct builtin_description bdesc_2arg[] = -{ - { CODE_FOR_mand, "__MAND", FRV_BUILTIN_MAND, 0, 0 }, - { CODE_FOR_mor, "__MOR", FRV_BUILTIN_MOR, 0, 0 }, - { CODE_FOR_mxor, "__MXOR", FRV_BUILTIN_MXOR, 0, 0 }, - { CODE_FOR_maveh, "__MAVEH", FRV_BUILTIN_MAVEH, 0, 0 }, - { CODE_FOR_msaths, "__MSATHS", FRV_BUILTIN_MSATHS, 0, 0 }, - { CODE_FOR_msathu, "__MSATHU", FRV_BUILTIN_MSATHU, 0, 0 }, - { CODE_FOR_maddhss, "__MADDHSS", FRV_BUILTIN_MADDHSS, 0, 0 }, - { CODE_FOR_maddhus, "__MADDHUS", FRV_BUILTIN_MADDHUS, 0, 0 }, - { CODE_FOR_msubhss, "__MSUBHSS", FRV_BUILTIN_MSUBHSS, 0, 0 }, - { CODE_FOR_msubhus, "__MSUBHUS", FRV_BUILTIN_MSUBHUS, 0, 0 }, - { CODE_FOR_mqaddhss, "__MQADDHSS", FRV_BUILTIN_MQADDHSS, 0, 0 }, - { CODE_FOR_mqaddhus, "__MQADDHUS", FRV_BUILTIN_MQADDHUS, 0, 0 }, - { CODE_FOR_mqsubhss, "__MQSUBHSS", FRV_BUILTIN_MQSUBHSS, 0, 0 }, - { CODE_FOR_mqsubhus, "__MQSUBHUS", FRV_BUILTIN_MQSUBHUS, 0, 0 }, - { CODE_FOR_mpackh, "__MPACKH", FRV_BUILTIN_MPACKH, 0, 0 }, - { CODE_FOR_mdpackh, "__MDPACKH", FRV_BUILTIN_MDPACKH, 0, 0 }, - { CODE_FOR_mcop1, "__Mcop1", FRV_BUILTIN_MCOP1, 0, 0 }, - { CODE_FOR_mcop2, "__Mcop2", FRV_BUILTIN_MCOP2, 0, 0 }, - { CODE_FOR_mwcut, "__MWCUT", FRV_BUILTIN_MWCUT, 0, 0 }, - { CODE_FOR_mqsaths, "__MQSATHS", FRV_BUILTIN_MQSATHS, 0, 0 } -}; - -/* Media intrinsics that take two arguments, the first being an ACC number. */ - -static struct builtin_description bdesc_cut[] = -{ - { CODE_FOR_mcut, "__MCUT", FRV_BUILTIN_MCUT, 0, 0 }, - { CODE_FOR_mcutss, "__MCUTSS", FRV_BUILTIN_MCUTSS, 0, 0 }, - { CODE_FOR_mdcutssi, "__MDCUTSSI", FRV_BUILTIN_MDCUTSSI, 0, 0 } -}; - -/* Two-argument media intrinsics with an immediate second argument. */ - -static struct builtin_description bdesc_2argimm[] = -{ - { CODE_FOR_mrotli, "__MROTLI", FRV_BUILTIN_MROTLI, 0, 0 }, - { CODE_FOR_mrotri, "__MROTRI", FRV_BUILTIN_MROTRI, 0, 0 }, - { CODE_FOR_msllhi, "__MSLLHI", FRV_BUILTIN_MSLLHI, 0, 0 }, - { CODE_FOR_msrlhi, "__MSRLHI", FRV_BUILTIN_MSRLHI, 0, 0 }, - { CODE_FOR_msrahi, "__MSRAHI", FRV_BUILTIN_MSRAHI, 0, 0 }, - { CODE_FOR_mexpdhw, "__MEXPDHW", FRV_BUILTIN_MEXPDHW, 0, 0 }, - { CODE_FOR_mexpdhd, "__MEXPDHD", FRV_BUILTIN_MEXPDHD, 0, 0 }, - { CODE_FOR_mdrotli, "__MDROTLI", FRV_BUILTIN_MDROTLI, 0, 0 }, - { CODE_FOR_mcplhi, "__MCPLHI", FRV_BUILTIN_MCPLHI, 0, 0 }, - { CODE_FOR_mcpli, "__MCPLI", FRV_BUILTIN_MCPLI, 0, 0 }, - { CODE_FOR_mhsetlos, "__MHSETLOS", FRV_BUILTIN_MHSETLOS, 0, 0 }, - { CODE_FOR_mhsetloh, "__MHSETLOH", FRV_BUILTIN_MHSETLOH, 0, 0 }, - { CODE_FOR_mhsethis, "__MHSETHIS", FRV_BUILTIN_MHSETHIS, 0, 0 }, - { CODE_FOR_mhsethih, "__MHSETHIH", FRV_BUILTIN_MHSETHIH, 0, 0 }, - { CODE_FOR_mhdseth, "__MHDSETH", FRV_BUILTIN_MHDSETH, 0, 0 } -}; - -/* Media intrinsics that take two arguments and return void, the first argument - being a pointer to 4 words in memory. */ - -static struct builtin_description bdesc_void2arg[] = -{ - { CODE_FOR_mdunpackh, "__MDUNPACKH", FRV_BUILTIN_MDUNPACKH, 0, 0 }, - { CODE_FOR_mbtohe, "__MBTOHE", FRV_BUILTIN_MBTOHE, 0, 0 }, -}; - -/* Media intrinsics that take three arguments, the first being a const_int that - denotes an accumulator, and that return void. */ - -static struct builtin_description bdesc_void3arg[] = -{ - { CODE_FOR_mcpxrs, "__MCPXRS", FRV_BUILTIN_MCPXRS, 0, 0 }, - { CODE_FOR_mcpxru, "__MCPXRU", FRV_BUILTIN_MCPXRU, 0, 0 }, - { CODE_FOR_mcpxis, "__MCPXIS", FRV_BUILTIN_MCPXIS, 0, 0 }, - { CODE_FOR_mcpxiu, "__MCPXIU", FRV_BUILTIN_MCPXIU, 0, 0 }, - { CODE_FOR_mmulhs, "__MMULHS", FRV_BUILTIN_MMULHS, 0, 0 }, - { CODE_FOR_mmulhu, "__MMULHU", FRV_BUILTIN_MMULHU, 0, 0 }, - { CODE_FOR_mmulxhs, "__MMULXHS", FRV_BUILTIN_MMULXHS, 0, 0 }, - { CODE_FOR_mmulxhu, "__MMULXHU", FRV_BUILTIN_MMULXHU, 0, 0 }, - { CODE_FOR_mmachs, "__MMACHS", FRV_BUILTIN_MMACHS, 0, 0 }, - { CODE_FOR_mmachu, "__MMACHU", FRV_BUILTIN_MMACHU, 0, 0 }, - { CODE_FOR_mmrdhs, "__MMRDHS", FRV_BUILTIN_MMRDHS, 0, 0 }, - { CODE_FOR_mmrdhu, "__MMRDHU", FRV_BUILTIN_MMRDHU, 0, 0 }, - { CODE_FOR_mqcpxrs, "__MQCPXRS", FRV_BUILTIN_MQCPXRS, 0, 0 }, - { CODE_FOR_mqcpxru, "__MQCPXRU", FRV_BUILTIN_MQCPXRU, 0, 0 }, - { CODE_FOR_mqcpxis, "__MQCPXIS", FRV_BUILTIN_MQCPXIS, 0, 0 }, - { CODE_FOR_mqcpxiu, "__MQCPXIU", FRV_BUILTIN_MQCPXIU, 0, 0 }, - { CODE_FOR_mqmulhs, "__MQMULHS", FRV_BUILTIN_MQMULHS, 0, 0 }, - { CODE_FOR_mqmulhu, "__MQMULHU", FRV_BUILTIN_MQMULHU, 0, 0 }, - { CODE_FOR_mqmulxhs, "__MQMULXHS", FRV_BUILTIN_MQMULXHS, 0, 0 }, - { CODE_FOR_mqmulxhu, "__MQMULXHU", FRV_BUILTIN_MQMULXHU, 0, 0 }, - { CODE_FOR_mqmachs, "__MQMACHS", FRV_BUILTIN_MQMACHS, 0, 0 }, - { CODE_FOR_mqmachu, "__MQMACHU", FRV_BUILTIN_MQMACHU, 0, 0 }, - { CODE_FOR_mqxmachs, "__MQXMACHS", FRV_BUILTIN_MQXMACHS, 0, 0 }, - { CODE_FOR_mqxmacxhs, "__MQXMACXHS", FRV_BUILTIN_MQXMACXHS, 0, 0 }, - { CODE_FOR_mqmacxhs, "__MQMACXHS", FRV_BUILTIN_MQMACXHS, 0, 0 } -}; - -/* Media intrinsics that take two accumulator numbers as argument and - return void. */ - -static struct builtin_description bdesc_voidacc[] = -{ - { CODE_FOR_maddaccs, "__MADDACCS", FRV_BUILTIN_MADDACCS, 0, 0 }, - { CODE_FOR_msubaccs, "__MSUBACCS", FRV_BUILTIN_MSUBACCS, 0, 0 }, - { CODE_FOR_masaccs, "__MASACCS", FRV_BUILTIN_MASACCS, 0, 0 }, - { CODE_FOR_mdaddaccs, "__MDADDACCS", FRV_BUILTIN_MDADDACCS, 0, 0 }, - { CODE_FOR_mdsubaccs, "__MDSUBACCS", FRV_BUILTIN_MDSUBACCS, 0, 0 }, - { CODE_FOR_mdasaccs, "__MDASACCS", FRV_BUILTIN_MDASACCS, 0, 0 } -}; - -/* Initialize media builtins. */ - -static void -frv_init_builtins () -{ - tree endlink = void_list_node; - tree accumulator = integer_type_node; - tree integer = integer_type_node; - tree voidt = void_type_node; - tree uhalf = short_unsigned_type_node; - tree sword1 = long_integer_type_node; - tree uword1 = long_unsigned_type_node; - tree sword2 = long_long_integer_type_node; - tree uword2 = long_long_unsigned_type_node; - tree uword4 = build_pointer_type (uword1); - -#define UNARY(RET, T1) \ - build_function_type (RET, tree_cons (NULL_TREE, T1, endlink)) - -#define BINARY(RET, T1, T2) \ - build_function_type (RET, tree_cons (NULL_TREE, T1, \ - tree_cons (NULL_TREE, T2, endlink))) - -#define TRINARY(RET, T1, T2, T3) \ - build_function_type (RET, tree_cons (NULL_TREE, T1, \ - tree_cons (NULL_TREE, T2, \ - tree_cons (NULL_TREE, T3, endlink)))) - - tree void_ftype_void = build_function_type (voidt, endlink); - - tree void_ftype_acc = UNARY (voidt, accumulator); - tree void_ftype_uw4_uw1 = BINARY (voidt, uword4, uword1); - tree void_ftype_uw4_uw2 = BINARY (voidt, uword4, uword2); - tree void_ftype_acc_uw1 = BINARY (voidt, accumulator, uword1); - tree void_ftype_acc_acc = BINARY (voidt, accumulator, accumulator); - tree void_ftype_acc_uw1_uw1 = TRINARY (voidt, accumulator, uword1, uword1); - tree void_ftype_acc_sw1_sw1 = TRINARY (voidt, accumulator, sword1, sword1); - tree void_ftype_acc_uw2_uw2 = TRINARY (voidt, accumulator, uword2, uword2); - tree void_ftype_acc_sw2_sw2 = TRINARY (voidt, accumulator, sword2, sword2); - - tree uw1_ftype_uw1 = UNARY (uword1, uword1); - tree uw1_ftype_sw1 = UNARY (uword1, sword1); - tree uw1_ftype_uw2 = UNARY (uword1, uword2); - tree uw1_ftype_acc = UNARY (uword1, accumulator); - tree uw1_ftype_uh_uh = BINARY (uword1, uhalf, uhalf); - tree uw1_ftype_uw1_uw1 = BINARY (uword1, uword1, uword1); - tree uw1_ftype_uw1_int = BINARY (uword1, uword1, integer); - tree uw1_ftype_acc_uw1 = BINARY (uword1, accumulator, uword1); - tree uw1_ftype_acc_sw1 = BINARY (uword1, accumulator, sword1); - tree uw1_ftype_uw2_uw1 = BINARY (uword1, uword2, uword1); - tree uw1_ftype_uw2_int = BINARY (uword1, uword2, integer); - - tree sw1_ftype_int = UNARY (sword1, integer); - tree sw1_ftype_sw1_sw1 = BINARY (sword1, sword1, sword1); - tree sw1_ftype_sw1_int = BINARY (sword1, sword1, integer); - - tree uw2_ftype_uw1 = UNARY (uword2, uword1); - tree uw2_ftype_uw1_int = BINARY (uword2, uword1, integer); - tree uw2_ftype_uw2_uw2 = BINARY (uword2, uword2, uword2); - tree uw2_ftype_uw2_int = BINARY (uword2, uword2, integer); - tree uw2_ftype_acc_int = BINARY (uword2, accumulator, integer); - - tree sw2_ftype_sw2_sw2 = BINARY (sword2, sword2, sword2); - - def_builtin ("__MAND", uw1_ftype_uw1_uw1, FRV_BUILTIN_MAND); - def_builtin ("__MOR", uw1_ftype_uw1_uw1, FRV_BUILTIN_MOR); - def_builtin ("__MXOR", uw1_ftype_uw1_uw1, FRV_BUILTIN_MXOR); - def_builtin ("__MNOT", uw1_ftype_uw1, FRV_BUILTIN_MNOT); - def_builtin ("__MROTLI", uw1_ftype_uw1_int, FRV_BUILTIN_MROTLI); - def_builtin ("__MROTRI", uw1_ftype_uw1_int, FRV_BUILTIN_MROTRI); - def_builtin ("__MWCUT", uw1_ftype_uw2_uw1, FRV_BUILTIN_MWCUT); - def_builtin ("__MAVEH", uw1_ftype_uw1_uw1, FRV_BUILTIN_MAVEH); - def_builtin ("__MSLLHI", uw1_ftype_uw1_int, FRV_BUILTIN_MSLLHI); - def_builtin ("__MSRLHI", uw1_ftype_uw1_int, FRV_BUILTIN_MSRLHI); - def_builtin ("__MSRAHI", sw1_ftype_sw1_int, FRV_BUILTIN_MSRAHI); - def_builtin ("__MSATHS", sw1_ftype_sw1_sw1, FRV_BUILTIN_MSATHS); - def_builtin ("__MSATHU", uw1_ftype_uw1_uw1, FRV_BUILTIN_MSATHU); - def_builtin ("__MADDHSS", sw1_ftype_sw1_sw1, FRV_BUILTIN_MADDHSS); - def_builtin ("__MADDHUS", uw1_ftype_uw1_uw1, FRV_BUILTIN_MADDHUS); - def_builtin ("__MSUBHSS", sw1_ftype_sw1_sw1, FRV_BUILTIN_MSUBHSS); - def_builtin ("__MSUBHUS", uw1_ftype_uw1_uw1, FRV_BUILTIN_MSUBHUS); - def_builtin ("__MMULHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMULHS); - def_builtin ("__MMULHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMULHU); - def_builtin ("__MMULXHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMULXHS); - def_builtin ("__MMULXHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMULXHU); - def_builtin ("__MMACHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMACHS); - def_builtin ("__MMACHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMACHU); - def_builtin ("__MMRDHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMRDHS); - def_builtin ("__MMRDHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMRDHU); - def_builtin ("__MQADDHSS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQADDHSS); - def_builtin ("__MQADDHUS", uw2_ftype_uw2_uw2, FRV_BUILTIN_MQADDHUS); - def_builtin ("__MQSUBHSS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQSUBHSS); - def_builtin ("__MQSUBHUS", uw2_ftype_uw2_uw2, FRV_BUILTIN_MQSUBHUS); - def_builtin ("__MQMULHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMULHS); - def_builtin ("__MQMULHU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQMULHU); - def_builtin ("__MQMULXHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMULXHS); - def_builtin ("__MQMULXHU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQMULXHU); - def_builtin ("__MQMACHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMACHS); - def_builtin ("__MQMACHU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQMACHU); - def_builtin ("__MCPXRS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MCPXRS); - def_builtin ("__MCPXRU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MCPXRU); - def_builtin ("__MCPXIS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MCPXIS); - def_builtin ("__MCPXIU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MCPXIU); - def_builtin ("__MQCPXRS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQCPXRS); - def_builtin ("__MQCPXRU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQCPXRU); - def_builtin ("__MQCPXIS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQCPXIS); - def_builtin ("__MQCPXIU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQCPXIU); - def_builtin ("__MCUT", uw1_ftype_acc_uw1, FRV_BUILTIN_MCUT); - def_builtin ("__MCUTSS", uw1_ftype_acc_sw1, FRV_BUILTIN_MCUTSS); - def_builtin ("__MEXPDHW", uw1_ftype_uw1_int, FRV_BUILTIN_MEXPDHW); - def_builtin ("__MEXPDHD", uw2_ftype_uw1_int, FRV_BUILTIN_MEXPDHD); - def_builtin ("__MPACKH", uw1_ftype_uh_uh, FRV_BUILTIN_MPACKH); - def_builtin ("__MUNPACKH", uw2_ftype_uw1, FRV_BUILTIN_MUNPACKH); - def_builtin ("__MDPACKH", uw2_ftype_uw2_uw2, FRV_BUILTIN_MDPACKH); - def_builtin ("__MDUNPACKH", void_ftype_uw4_uw2, FRV_BUILTIN_MDUNPACKH); - def_builtin ("__MBTOH", uw2_ftype_uw1, FRV_BUILTIN_MBTOH); - def_builtin ("__MHTOB", uw1_ftype_uw2, FRV_BUILTIN_MHTOB); - def_builtin ("__MBTOHE", void_ftype_uw4_uw1, FRV_BUILTIN_MBTOHE); - def_builtin ("__MCLRACC", void_ftype_acc, FRV_BUILTIN_MCLRACC); - def_builtin ("__MCLRACCA", void_ftype_void, FRV_BUILTIN_MCLRACCA); - def_builtin ("__MRDACC", uw1_ftype_acc, FRV_BUILTIN_MRDACC); - def_builtin ("__MRDACCG", uw1_ftype_acc, FRV_BUILTIN_MRDACCG); - def_builtin ("__MWTACC", void_ftype_acc_uw1, FRV_BUILTIN_MWTACC); - def_builtin ("__MWTACCG", void_ftype_acc_uw1, FRV_BUILTIN_MWTACCG); - def_builtin ("__Mcop1", uw1_ftype_uw1_uw1, FRV_BUILTIN_MCOP1); - def_builtin ("__Mcop2", uw1_ftype_uw1_uw1, FRV_BUILTIN_MCOP2); - def_builtin ("__MTRAP", void_ftype_void, FRV_BUILTIN_MTRAP); - def_builtin ("__MQXMACHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQXMACHS); - def_builtin ("__MQXMACXHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQXMACXHS); - def_builtin ("__MQMACXHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMACXHS); - def_builtin ("__MADDACCS", void_ftype_acc_acc, FRV_BUILTIN_MADDACCS); - def_builtin ("__MSUBACCS", void_ftype_acc_acc, FRV_BUILTIN_MSUBACCS); - def_builtin ("__MASACCS", void_ftype_acc_acc, FRV_BUILTIN_MASACCS); - def_builtin ("__MDADDACCS", void_ftype_acc_acc, FRV_BUILTIN_MDADDACCS); - def_builtin ("__MDSUBACCS", void_ftype_acc_acc, FRV_BUILTIN_MDSUBACCS); - def_builtin ("__MDASACCS", void_ftype_acc_acc, FRV_BUILTIN_MDASACCS); - def_builtin ("__MABSHS", uw1_ftype_sw1, FRV_BUILTIN_MABSHS); - def_builtin ("__MDROTLI", uw2_ftype_uw2_int, FRV_BUILTIN_MDROTLI); - def_builtin ("__MCPLHI", uw1_ftype_uw2_int, FRV_BUILTIN_MCPLHI); - def_builtin ("__MCPLI", uw1_ftype_uw2_int, FRV_BUILTIN_MCPLI); - def_builtin ("__MDCUTSSI", uw2_ftype_acc_int, FRV_BUILTIN_MDCUTSSI); - def_builtin ("__MQSATHS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQSATHS); - def_builtin ("__MHSETLOS", sw1_ftype_sw1_int, FRV_BUILTIN_MHSETLOS); - def_builtin ("__MHSETHIS", sw1_ftype_sw1_int, FRV_BUILTIN_MHSETHIS); - def_builtin ("__MHDSETS", sw1_ftype_int, FRV_BUILTIN_MHDSETS); - def_builtin ("__MHSETLOH", uw1_ftype_uw1_int, FRV_BUILTIN_MHSETLOH); - def_builtin ("__MHSETHIH", uw1_ftype_uw1_int, FRV_BUILTIN_MHSETHIH); - def_builtin ("__MHDSETH", uw1_ftype_uw1_int, FRV_BUILTIN_MHDSETH); - -#undef UNARY -#undef BINARY -#undef TRINARY -} - -/* Convert an integer constant to an accumulator register. ICODE is the - code of the target instruction, OPNUM is the number of the - accumulator operand and OPVAL is the constant integer. Try both - ACC and ACCG registers; only report an error if neither fit the - instruction. */ - -static rtx -frv_int_to_acc (icode, opnum, opval) - enum insn_code icode; - int opnum; - rtx opval; -{ - rtx reg; - - if (GET_CODE (opval) != CONST_INT) - { - error ("accumulator is not a constant integer"); - return NULL_RTX; - } - if (! IN_RANGE_P (INTVAL (opval), 0, NUM_ACCS - 1)) - { - error ("accumulator number is out of bounds"); - return NULL_RTX; - } - - reg = gen_rtx_REG (insn_data[icode].operand[opnum].mode, - ACC_FIRST + INTVAL (opval)); - if (! (*insn_data[icode].operand[opnum].predicate) (reg, VOIDmode)) - REGNO (reg) = ACCG_FIRST + INTVAL (opval); - - if (! (*insn_data[icode].operand[opnum].predicate) (reg, VOIDmode)) - { - error ("inappropriate accumulator for `%s'", insn_data[icode].name); - return NULL_RTX; - } - return reg; -} - -/* If an ACC rtx has mode MODE, return the mode that the matching ACCG - should have. */ - -static enum machine_mode -frv_matching_accg_mode (mode) - enum machine_mode mode; -{ - switch (mode) - { - case V4SImode: - return V4QImode; - - case DImode: - return HImode; - - case SImode: - return QImode; - - default: - abort (); - } -} - -/* Return the accumulator guard that should be paired with accumulator - register ACC. The mode of the returned register is in the same - class as ACC, but is four times smaller. */ - -rtx -frv_matching_accg_for_acc (acc) - rtx acc; -{ - return gen_rtx_REG (frv_matching_accg_mode (GET_MODE (acc)), - REGNO (acc) - ACC_FIRST + ACCG_FIRST); -} - -/* Read a value from the head of the tree list pointed to by ARGLISTPTR. - Return the value as an rtx and replace *ARGLISTPTR with the tail of the - list. */ - -static rtx -frv_read_argument (arglistptr) - tree *arglistptr; -{ - tree next = TREE_VALUE (*arglistptr); - *arglistptr = TREE_CHAIN (*arglistptr); - return expand_expr (next, NULL_RTX, VOIDmode, 0); -} - -/* Return true if OPVAL can be used for operand OPNUM of instruction ICODE. - The instruction should require a constant operand of some sort. The - function prints an error if OPVAL is not valid. */ - -static int -frv_check_constant_argument (icode, opnum, opval) - enum insn_code icode; - int opnum; - rtx opval; -{ - if (GET_CODE (opval) != CONST_INT) - { - error ("`%s' expects a constant argument", insn_data[icode].name); - return FALSE; - } - if (! (*insn_data[icode].operand[opnum].predicate) (opval, VOIDmode)) - { - error ("constant argument out of range for `%s'", insn_data[icode].name); - return FALSE; - } - return TRUE; -} - -/* Return a legitimate rtx for instruction ICODE's return value. Use TARGET - if it's not null, has the right mode, and satisfies operand 0's - predicate. */ - -static rtx -frv_legitimize_target (icode, target) - enum insn_code icode; - rtx target; -{ - enum machine_mode mode = insn_data[icode].operand[0].mode; - - if (! target - || GET_MODE (target) != mode - || ! (*insn_data[icode].operand[0].predicate) (target, mode)) - return gen_reg_rtx (mode); - else - return target; -} - -/* Given that ARG is being passed as operand OPNUM to instruction ICODE, - check whether ARG satisfies the operand's contraints. If it doesn't, - copy ARG to a temporary register and return that. Otherwise return ARG - itself. */ - -static rtx -frv_legitimize_argument (icode, opnum, arg) - enum insn_code icode; - int opnum; - rtx arg; -{ - enum machine_mode mode = insn_data[icode].operand[opnum].mode; - - if ((*insn_data[icode].operand[opnum].predicate) (arg, mode)) - return arg; - else - return copy_to_mode_reg (mode, arg); -} - -/* Expand builtins that take a single, constant argument. At the moment, - only MHDSETS falls into this category. */ - -static rtx -frv_expand_set_builtin (icode, arglist, target) - enum insn_code icode; - tree arglist; - rtx target; -{ - rtx pat; - rtx op0 = frv_read_argument (&arglist); - - if (! frv_check_constant_argument (icode, 1, op0)) - return NULL_RTX; - - target = frv_legitimize_target (icode, target); - pat = GEN_FCN (icode) (target, op0); - if (! pat) - return NULL_RTX; - - emit_insn (pat); - return target; -} - -/* Expand builtins that take one operand. */ - -static rtx -frv_expand_unop_builtin (icode, arglist, target) - enum insn_code icode; - tree arglist; - rtx target; -{ - rtx pat; - rtx op0 = frv_read_argument (&arglist); - - target = frv_legitimize_target (icode, target); - op0 = frv_legitimize_argument (icode, 1, op0); - pat = GEN_FCN (icode) (target, op0); - if (! pat) - return NULL_RTX; - - emit_insn (pat); - return target; -} - -/* Expand builtins that take two operands. */ - -static rtx -frv_expand_binop_builtin (icode, arglist, target) - enum insn_code icode; - tree arglist; - rtx target; -{ - rtx pat; - rtx op0 = frv_read_argument (&arglist); - rtx op1 = frv_read_argument (&arglist); - - target = frv_legitimize_target (icode, target); - op0 = frv_legitimize_argument (icode, 1, op0); - op1 = frv_legitimize_argument (icode, 2, op1); - pat = GEN_FCN (icode) (target, op0, op1); - if (! pat) - return NULL_RTX; - - emit_insn (pat); - return target; -} - -/* Expand cut-style builtins, which take two operands and an implicit ACCG - one. */ - -static rtx -frv_expand_cut_builtin (icode, arglist, target) - enum insn_code icode; - tree arglist; - rtx target; -{ - rtx pat; - rtx op0 = frv_read_argument (&arglist); - rtx op1 = frv_read_argument (&arglist); - rtx op2; - - target = frv_legitimize_target (icode, target); - op0 = frv_int_to_acc (icode, 1, op0); - if (! op0) - return NULL_RTX; - - if (icode == CODE_FOR_mdcutssi || GET_CODE (op1) == CONST_INT) - { - if (! frv_check_constant_argument (icode, 2, op1)) - return NULL_RTX; - } - else - op1 = frv_legitimize_argument (icode, 2, op1); - - op2 = frv_matching_accg_for_acc (op0); - pat = GEN_FCN (icode) (target, op0, op1, op2); - if (! pat) - return NULL_RTX; - - emit_insn (pat); - return target; -} - -/* Expand builtins that take two operands and the second is immediate. */ - -static rtx -frv_expand_binopimm_builtin (icode, arglist, target) - enum insn_code icode; - tree arglist; - rtx target; -{ - rtx pat; - rtx op0 = frv_read_argument (&arglist); - rtx op1 = frv_read_argument (&arglist); - - if (! frv_check_constant_argument (icode, 2, op1)) - return NULL_RTX; - - target = frv_legitimize_target (icode, target); - op0 = frv_legitimize_argument (icode, 1, op0); - pat = GEN_FCN (icode) (target, op0, op1); - if (! pat) - return NULL_RTX; - - emit_insn (pat); - return target; -} - -/* Expand builtins that take two operands, the first operand being a pointer to - ints and return void. */ - -static rtx -frv_expand_voidbinop_builtin (icode, arglist) - enum insn_code icode; - tree arglist; -{ - rtx pat; - rtx op0 = frv_read_argument (&arglist); - rtx op1 = frv_read_argument (&arglist); - enum machine_mode mode0 = insn_data[icode].operand[0].mode; - rtx addr; - - if (GET_CODE (op0) != MEM) - { - rtx reg = op0; - - if (! offsettable_address_p (0, mode0, op0)) - { - reg = gen_reg_rtx (Pmode); - emit_insn (gen_rtx_SET (VOIDmode, reg, op0)); - } - - op0 = gen_rtx_MEM (SImode, reg); - } - - addr = XEXP (op0, 0); - if (! offsettable_address_p (0, mode0, addr)) - addr = copy_to_mode_reg (Pmode, op0); - - op0 = change_address (op0, V4SImode, addr); - op1 = frv_legitimize_argument (icode, 1, op1); - pat = GEN_FCN (icode) (op0, op1); - if (! pat) - return 0; - - emit_insn (pat); - return 0; -} - -/* Expand builtins that take three operands and return void. The first - argument must be a constant that describes a pair or quad accumulators. A - fourth argument is created that is the accumulator guard register that - corresponds to the accumulator. */ - -static rtx -frv_expand_voidtriop_builtin (icode, arglist) - enum insn_code icode; - tree arglist; -{ - rtx pat; - rtx op0 = frv_read_argument (&arglist); - rtx op1 = frv_read_argument (&arglist); - rtx op2 = frv_read_argument (&arglist); - rtx op3; - - op0 = frv_int_to_acc (icode, 0, op0); - if (! op0) - return NULL_RTX; - - op1 = frv_legitimize_argument (icode, 1, op1); - op2 = frv_legitimize_argument (icode, 2, op2); - op3 = frv_matching_accg_for_acc (op0); - pat = GEN_FCN (icode) (op0, op1, op2, op3); - if (! pat) - return NULL_RTX; - - emit_insn (pat); - return NULL_RTX; -} - -/* Expand builtins that perform accumulator-to-accumulator operations. - These builtins take two accumulator numbers as argument and return - void. */ - -static rtx -frv_expand_voidaccop_builtin (icode, arglist) - enum insn_code icode; - tree arglist; -{ - rtx pat; - rtx op0 = frv_read_argument (&arglist); - rtx op1 = frv_read_argument (&arglist); - rtx op2; - rtx op3; - - op0 = frv_int_to_acc (icode, 0, op0); - if (! op0) - return NULL_RTX; - - op1 = frv_int_to_acc (icode, 1, op1); - if (! op1) - return NULL_RTX; - - op2 = frv_matching_accg_for_acc (op0); - op3 = frv_matching_accg_for_acc (op1); - pat = GEN_FCN (icode) (op0, op1, op2, op3); - if (! pat) - return NULL_RTX; - - emit_insn (pat); - return NULL_RTX; -} - -/* Expand the MCLRACC builtin. This builtin takes a single accumulator - number as argument. */ - -static rtx -frv_expand_mclracc_builtin (arglist) - tree arglist; -{ - enum insn_code icode = CODE_FOR_mclracc; - rtx pat; - rtx op0 = frv_read_argument (&arglist); - - op0 = frv_int_to_acc (icode, 0, op0); - if (! op0) - return NULL_RTX; - - pat = GEN_FCN (icode) (op0); - if (pat) - emit_insn (pat); - - return NULL_RTX; -} - -/* Expand builtins that take no arguments. */ - -static rtx -frv_expand_noargs_builtin (icode) - enum insn_code icode; -{ - rtx pat = GEN_FCN (icode) (GEN_INT (0)); - if (pat) - emit_insn (pat); - - return NULL_RTX; -} - -/* Expand MRDACC and MRDACCG. These builtins take a single accumulator - number or accumulator guard number as argument and return an SI integer. */ - -static rtx -frv_expand_mrdacc_builtin (icode, arglist) - enum insn_code icode; - tree arglist; -{ - rtx pat; - rtx target = gen_reg_rtx (SImode); - rtx op0 = frv_read_argument (&arglist); - - op0 = frv_int_to_acc (icode, 1, op0); - if (! op0) - return NULL_RTX; - - pat = GEN_FCN (icode) (target, op0); - if (! pat) - return NULL_RTX; - - emit_insn (pat); - return target; -} - -/* Expand MWTACC and MWTACCG. These builtins take an accumulator or - accumulator guard as their first argument and an SImode value as their - second. */ - -static rtx -frv_expand_mwtacc_builtin (icode, arglist) - enum insn_code icode; - tree arglist; -{ - rtx pat; - rtx op0 = frv_read_argument (&arglist); - rtx op1 = frv_read_argument (&arglist); - - op0 = frv_int_to_acc (icode, 0, op0); - if (! op0) - return NULL_RTX; - - op1 = frv_legitimize_argument (icode, 1, op1); - pat = GEN_FCN (icode) (op0, op1); - if (pat) - emit_insn (pat); - - return NULL_RTX; -} - -/* Expand builtins. */ - -static rtx -frv_expand_builtin (exp, target, subtarget, mode, ignore) - tree exp; - rtx target; - rtx subtarget ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; - int ignore ATTRIBUTE_UNUSED; -{ - tree arglist = TREE_OPERAND (exp, 1); - tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); - unsigned fcode = (unsigned)DECL_FUNCTION_CODE (fndecl); - unsigned i; - struct builtin_description *d; - - if (! TARGET_MEDIA) - { - error ("media functions are not available unless -mmedia is used"); - return NULL_RTX; - } - - switch (fcode) - { - case FRV_BUILTIN_MCOP1: - case FRV_BUILTIN_MCOP2: - case FRV_BUILTIN_MDUNPACKH: - case FRV_BUILTIN_MBTOHE: - if (! TARGET_MEDIA_REV1) - { - error ("this media function is only available on the fr500"); - return NULL_RTX; - } - break; - - case FRV_BUILTIN_MQXMACHS: - case FRV_BUILTIN_MQXMACXHS: - case FRV_BUILTIN_MQMACXHS: - case FRV_BUILTIN_MADDACCS: - case FRV_BUILTIN_MSUBACCS: - case FRV_BUILTIN_MASACCS: - case FRV_BUILTIN_MDADDACCS: - case FRV_BUILTIN_MDSUBACCS: - case FRV_BUILTIN_MDASACCS: - case FRV_BUILTIN_MABSHS: - case FRV_BUILTIN_MDROTLI: - case FRV_BUILTIN_MCPLHI: - case FRV_BUILTIN_MCPLI: - case FRV_BUILTIN_MDCUTSSI: - case FRV_BUILTIN_MQSATHS: - case FRV_BUILTIN_MHSETLOS: - case FRV_BUILTIN_MHSETLOH: - case FRV_BUILTIN_MHSETHIS: - case FRV_BUILTIN_MHSETHIH: - case FRV_BUILTIN_MHDSETS: - case FRV_BUILTIN_MHDSETH: - if (! TARGET_MEDIA_REV2) - { - error ("this media function is only available on the fr400"); - return NULL_RTX; - } - break; - - default: - break; - } - - /* Expand unique builtins. */ - - switch (fcode) - { - case FRV_BUILTIN_MTRAP: - return frv_expand_noargs_builtin (CODE_FOR_mtrap); - - case FRV_BUILTIN_MCLRACC: - return frv_expand_mclracc_builtin (arglist); - - case FRV_BUILTIN_MCLRACCA: - if (TARGET_ACC_8) - return frv_expand_noargs_builtin (CODE_FOR_mclracca8); - else - return frv_expand_noargs_builtin (CODE_FOR_mclracca4); - - case FRV_BUILTIN_MRDACC: - return frv_expand_mrdacc_builtin (CODE_FOR_mrdacc, arglist); - - case FRV_BUILTIN_MRDACCG: - return frv_expand_mrdacc_builtin (CODE_FOR_mrdaccg, arglist); - - case FRV_BUILTIN_MWTACC: - return frv_expand_mwtacc_builtin (CODE_FOR_mwtacc, arglist); - - case FRV_BUILTIN_MWTACCG: - return frv_expand_mwtacc_builtin (CODE_FOR_mwtaccg, arglist); - - default: - break; - } - - /* Expand groups of builtins. */ - - for (i = 0, d = bdesc_set; i < sizeof (bdesc_set) / sizeof *d; i++, d++) - if (d->code == fcode) - return frv_expand_set_builtin (d->icode, arglist, target); - - for (i = 0, d = bdesc_1arg; i < sizeof (bdesc_1arg) / sizeof *d; i++, d++) - if (d->code == fcode) - return frv_expand_unop_builtin (d->icode, arglist, target); - - for (i = 0, d = bdesc_2arg; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++) - if (d->code == fcode) - return frv_expand_binop_builtin (d->icode, arglist, target); - - for (i = 0, d = bdesc_cut; i < sizeof (bdesc_cut) / sizeof *d; i++, d++) - if (d->code == fcode) - return frv_expand_cut_builtin (d->icode, arglist, target); - - for (i = 0, d = bdesc_2argimm; - i < sizeof (bdesc_2argimm) / sizeof *d; - i++, d++) - { - if (d->code == fcode) - return frv_expand_binopimm_builtin (d->icode, arglist, target); - } - - for (i = 0, d = bdesc_void2arg; - i < sizeof (bdesc_void2arg) / sizeof *d; - i++, d++) - { - if (d->code == fcode) - return frv_expand_voidbinop_builtin (d->icode, arglist); - } - - for (i = 0, d = bdesc_void3arg; - i < sizeof (bdesc_void3arg) / sizeof *d; - i++, d++) - { - if (d->code == fcode) - return frv_expand_voidtriop_builtin (d->icode, arglist); - } - - for (i = 0, d = bdesc_voidacc; - i < sizeof (bdesc_voidacc) / sizeof *d; - i++, d++) - { - if (d->code == fcode) - return frv_expand_voidaccop_builtin (d->icode, arglist); - } - return 0; -} - -static const char * -frv_strip_name_encoding (str) - const char *str; -{ - while (*str == '*' || *str == SDATA_FLAG_CHAR) - str++; - return str; -} - -static bool -frv_in_small_data_p (decl) - tree decl; -{ - HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl)); - - return symbol_ref_small_data_p (XEXP (DECL_RTL (decl), 0)) - && size > 0 && size <= g_switch_value; -} diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h deleted file mode 100644 index a663c03b4d3..00000000000 --- a/gcc/config/frv/frv.h +++ /dev/null @@ -1,3660 +0,0 @@ -/* Target macros for the FRV port of GCC. - Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - Contributed by Red Hat Inc. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your - option) any later version. - - GCC is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#ifndef __FRV_H__ -#define __FRV_H__ - -/* Set up System V.4 (aka ELF) defaults. */ -#include "svr4.h" - - -/* Frv general purpose macros. */ -/* Align an address. */ -#define ADDR_ALIGN(addr,align) (((addr) + (align) - 1) & ~((align) - 1)) - -/* Return true if a value is inside a range. */ -#define IN_RANGE_P(VALUE, LOW, HIGH) \ - ( (((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW)) \ - && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH)))) - - -/* 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 -#define SWITCH_TAKES_ARG(CHAR) \ - (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G') - -/* 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 - -/* 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 "\ -%{G*} %{v} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \ -%{mtomcat-stats} \ -%{!mno-eflags: \ - %{mcpu=*} \ - %{mgpr-*} %{mfpr-*} \ - %{msoft-float} %{mhard-float} \ - %{mdword} %{mno-dword} \ - %{mdouble} %{mno-double} \ - %{mmedia} %{mno-media} \ - %{mmuladd} %{mno-muladd} \ - %{mpack} %{mno-pack} \ - %{fpic: -mpic} %{fPIC: -mPIC} %{mlibrary-pic}}" - -/* 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 frvbegin%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 "frvend%O%s" - -/* 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. */ - -/* The idea here is to use the -mcpu option to define macros based on the - processor's features, using the features of the default processor if - no -mcpu option is given. These macros can then be overridden by - other -m options. */ -#define CPP_SPEC "\ -%{mcpu=frv: %(cpp_frv)} \ -%{mcpu=fr500: %(cpp_fr500)} \ -%{mcpu=fr400: %(cpp_fr400)} \ -%{mcpu=fr300: %(cpp_simple)} \ -%{mcpu=tomcat: %(cpp_fr500)} \ -%{mcpu=simple: %(cpp_simple)} \ -%{!mcpu*: %(cpp_cpu_default)} \ -%{mno-media: -D__FRV_ACC__=0 %{msoft-float: -D__FRV_FPR__=0}} \ -%{mhard-float: -D__FRV_HARD_FLOAT__} \ -%{msoft-float: -U__FRV_HARD_FLOAT__} \ -%{mgpr-32: -U__FRV_GPR__ -D__FRV_GPR__=32} \ -%{mgpr-64: -U__FRV_GPR__ -D__FRV_GPR__=64} \ -%{mfpr-32: -U__FRV_FPR__ -D__FRV_FPR__=32} \ -%{mfpr-64: -U__FRV_FPR__ -D__FRV_FPR__=64} \ -%{macc-4: -U__FRV_ACC__ -D__FRV_ACC__=4} \ -%{macc-8: -U__FRV_ACC__ -D__FRV_ACC__=8} \ -%{mdword: -D__FRV_DWORD__} \ -%{mno-dword: -U__FRV_DWORD__} \ -%{mno-pack: -U__FRV_VLIW__} \ -%{fleading-underscore: -D__FRV_UNDERSCORE__}" - -/* CPU defaults. Each CPU has its own CPP spec that defines the default - macros for that CPU. Each CPU also has its own default target mask. - - CPU GPRs FPRs ACCs FPU MulAdd ldd/std Issue rate - --- ---- ---- ---- --- ------ ------- ---------- - FRV 64 64 8 double yes yes 4 - FR500 64 64 8 single no yes 4 - FR400 32 32 4 none no yes 2 - Simple 32 0 0 none no no 1 */ - - -#define CPP_FRV_SPEC "\ --D__FRV_GPR__=64 \ --D__FRV_FPR__=64 \ --D__FRV_ACC__=8 \ --D__FRV_HARD_FLOAT__ \ --D__FRV_DWORD__ \ --D__FRV_VLIW__=4" - -#define CPP_FR500_SPEC "\ --D__FRV_GPR__=64 \ --D__FRV_FPR__=64 \ --D__FRV_ACC__=8 \ --D__FRV_HARD_FLOAT__ \ --D__FRV_DWORD__ \ --D__FRV_VLIW__=4" - -#define CPP_FR400_SPEC "\ --D__FRV_GPR__=32 \ --D__FRV_FPR__=32 \ --D__FRV_ACC__=4 \ --D__FRV_DWORD__ \ --D__FRV_VLIW__=2" - -#define CPP_SIMPLE_SPEC "\ --D__FRV_GPR__=32 \ --D__FRV_FPR__=0 \ --D__FRV_ACC__=0 \ -%{mmedia: -D__FRV_ACC__=8} \ -%{mhard-float|mmedia: -D__FRV_FPR__=64}" - -#define MASK_DEFAULT_FRV \ - (MASK_MEDIA \ - | MASK_DOUBLE \ - | MASK_MULADD \ - | MASK_DWORD \ - | MASK_PACK) - -#define MASK_DEFAULT_FR500 \ - (MASK_MEDIA | MASK_DWORD | MASK_PACK) - -#define MASK_DEFAULT_FR400 \ - (MASK_GPR_32 \ - | MASK_FPR_32 \ - | MASK_MEDIA \ - | MASK_ACC_4 \ - | MASK_SOFT_FLOAT \ - | MASK_DWORD \ - | MASK_PACK) - -#define MASK_DEFAULT_SIMPLE \ - (MASK_GPR_32 | MASK_SOFT_FLOAT) - -/* 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. */ -/* For ABI compliance, we need to put bss data into the normal data section. */ -#define CC1_SPEC "%{G*}" - -/* 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. */ -/* Override the svr4.h version with one that dispenses without the svr4 - shared library options, notably -G. */ -#undef LINK_SPEC -#define LINK_SPEC "\ -%{h*} %{v:-V} \ -%{b} %{Wl,*:%*} \ -%{static:-dn -Bstatic} \ -%{shared:-Bdynamic} \ -%{symbolic:-Bsymbolic} \ -%{G*} \ -%{YP,*} \ -%{Qy:} %{!Qn:-Qy}" - -/* 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 -lc -lsim --end-group" - -/* 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_frv", CPP_FRV_SPEC }, \ - { "cpp_fr500", CPP_FR500_SPEC }, \ - { "cpp_fr400", CPP_FR400_SPEC }, \ - { "cpp_simple", CPP_SIMPLE_SPEC }, \ - { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \ - SUBTARGET_EXTRA_SPECS - -#ifndef CPP_CPU_DEFAULT_SPEC -#define CPP_CPU_DEFAULT_SPEC CPP_FR500_SPEC -#define CPU_TYPE FRV_CPU_FR500 -#endif - -/* Allow us to easily change the default for -malloc-cc. */ -#ifndef DEFAULT_NO_ALLOC_CC -#define MASK_DEFAULT_ALLOC_CC MASK_ALLOC_CC -#else -#define MASK_DEFAULT_ALLOC_CC 0 -#endif - -/* 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__frv__ -Amachine(frv)" - - -/* 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_GPR_32 0x00000001 /* Limit gprs to 32 registers */ -#define MASK_FPR_32 0x00000002 /* Limit fprs to 32 registers */ -#define MASK_SOFT_FLOAT 0x00000004 /* Use software floating point */ -#define MASK_ALLOC_CC 0x00000008 /* Dynamically allocate icc/fcc's */ -#define MASK_DWORD 0x00000010 /* Change ABi to allow dbl word insns*/ -#define MASK_DOUBLE 0x00000020 /* Use double precision instructions */ -#define MASK_MEDIA 0x00000040 /* Use media instructions */ -#define MASK_MULADD 0x00000080 /* Use multiply add/subtract insns */ -#define MASK_LIBPIC 0x00000100 /* -fpic that can be linked w/o pic */ -#define MASK_ACC_4 0x00000200 /* Only use four media accumulators */ -#define MASK_PACK 0x00000400 /* Set to enable packed output */ - - /* put debug masks up high */ -#define MASK_DEBUG_ARG 0x40000000 /* debug argument handling */ -#define MASK_DEBUG_ADDR 0x20000000 /* debug go_if_legitimate_address */ -#define MASK_DEBUG_STACK 0x10000000 /* debug stack frame */ -#define MASK_DEBUG 0x08000000 /* general debugging switch */ -#define MASK_DEBUG_LOC 0x04000000 /* optimize line # table */ -#define MASK_DEBUG_COND_EXEC 0x02000000 /* debug cond exec code */ -#define MASK_NO_COND_MOVE 0x01000000 /* disable conditional moves */ -#define MASK_NO_SCC 0x00800000 /* disable set conditional codes */ -#define MASK_NO_COND_EXEC 0x00400000 /* disable conditional execution */ -#define MASK_NO_VLIW_BRANCH 0x00200000 /* disable repacking branches */ -#define MASK_NO_MULTI_CE 0x00100000 /* disable multi-level cond exec */ -#define MASK_NO_NESTED_CE 0x00080000 /* disable nested cond exec */ - -#define MASK_DEFAULT MASK_DEFAULT_ALLOC_CC - -#define TARGET_GPR_32 ((target_flags & MASK_GPR_32) != 0) -#define TARGET_FPR_32 ((target_flags & MASK_FPR_32) != 0) -#define TARGET_SOFT_FLOAT ((target_flags & MASK_SOFT_FLOAT) != 0) -#define TARGET_ALLOC_CC ((target_flags & MASK_ALLOC_CC) != 0) -#define TARGET_DWORD ((target_flags & MASK_DWORD) != 0) -#define TARGET_DOUBLE ((target_flags & MASK_DOUBLE) != 0) -#define TARGET_MEDIA ((target_flags & MASK_MEDIA) != 0) -#define TARGET_MULADD ((target_flags & MASK_MULADD) != 0) -#define TARGET_LIBPIC ((target_flags & MASK_LIBPIC) != 0) -#define TARGET_ACC_4 ((target_flags & MASK_ACC_4) != 0) -#define TARGET_DEBUG_ARG ((target_flags & MASK_DEBUG_ARG) != 0) -#define TARGET_DEBUG_ADDR ((target_flags & MASK_DEBUG_ADDR) != 0) -#define TARGET_DEBUG_STACK ((target_flags & MASK_DEBUG_STACK) != 0) -#define TARGET_DEBUG ((target_flags & MASK_DEBUG) != 0) -#define TARGET_DEBUG_LOC ((target_flags & MASK_DEBUG_LOC) != 0) -#define TARGET_DEBUG_COND_EXEC ((target_flags & MASK_DEBUG_COND_EXEC) != 0) -#define TARGET_NO_COND_MOVE ((target_flags & MASK_NO_COND_MOVE) != 0) -#define TARGET_NO_SCC ((target_flags & MASK_NO_SCC) != 0) -#define TARGET_NO_COND_EXEC ((target_flags & MASK_NO_COND_EXEC) != 0) -#define TARGET_NO_VLIW_BRANCH ((target_flags & MASK_NO_VLIW_BRANCH) != 0) -#define TARGET_NO_MULTI_CE ((target_flags & MASK_NO_MULTI_CE) != 0) -#define TARGET_NO_NESTED_CE ((target_flags & MASK_NO_NESTED_CE) != 0) -#define TARGET_PACK ((target_flags & MASK_PACK) != 0) - -#define TARGET_GPR_64 (! TARGET_GPR_32) -#define TARGET_FPR_64 (! TARGET_FPR_32) -#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT) -#define TARGET_FIXED_CC (! TARGET_ALLOC_CC) -#define TARGET_COND_MOVE (! TARGET_NO_COND_MOVE) -#define TARGET_SCC (! TARGET_NO_SCC) -#define TARGET_COND_EXEC (! TARGET_NO_COND_EXEC) -#define TARGET_VLIW_BRANCH (! TARGET_NO_VLIW_BRANCH) -#define TARGET_MULTI_CE (! TARGET_NO_MULTI_CE) -#define TARGET_NESTED_CE (! TARGET_NO_NESTED_CE) -#define TARGET_ACC_8 (! TARGET_ACC_4) - -#define TARGET_HAS_FPRS (TARGET_HARD_FLOAT || TARGET_MEDIA) - -#define NUM_GPRS (TARGET_GPR_32? 32 : 64) -#define NUM_FPRS (!TARGET_HAS_FPRS? 0 : TARGET_FPR_32? 32 : 64) -#define NUM_ACCS (!TARGET_MEDIA? 0 : TARGET_ACC_4? 4 : 8) - -/* Macros to identify the blend of media instructions available. Revision 1 - is the one found on the FR500. Revision 2 includes the changes made for - the FR400. - - Treat the generic processor as a revision 1 machine for now, for - compatibility with earlier releases. */ - -#define TARGET_MEDIA_REV1 \ - (TARGET_MEDIA \ - && (frv_cpu_type == FRV_CPU_GENERIC \ - || frv_cpu_type == FRV_CPU_FR500)) - -#define TARGET_MEDIA_REV2 \ - (TARGET_MEDIA && frv_cpu_type == FRV_CPU_FR400) - -/* 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, - a number, which contains the bits to set in `target_flags', and an optional - second string which is the textual description that will be displayed when - the user passes --help on the command line. If the number entry is negative - then the specified bits will be cleared instead of being set. If the second - string entry is present but empty, then no help information will be displayed - for that option, but it will not count as an undocumented option. The actual - option name, asseen on the command line 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, "Compile for the m68000"}, \ - { "", 1, }} - - This declaration must be present. */ - -#define TARGET_SWITCHES \ -{{ "gpr-32", MASK_GPR_32, "Only use 32 gprs"}, \ - { "gpr-64", -MASK_GPR_32, "Use 64 gprs"}, \ - { "fpr-32", MASK_FPR_32, "Only use 32 fprs"}, \ - { "fpr-64", -MASK_FPR_32, "Use 64 fprs"}, \ - { "hard-float", -MASK_SOFT_FLOAT, "Use hardware floating point" },\ - { "soft-float", MASK_SOFT_FLOAT, "Use software floating point" },\ - { "alloc-cc", MASK_ALLOC_CC, "Dynamically allocate cc's" }, \ - { "fixed-cc", -MASK_ALLOC_CC, "Just use icc0/fcc0" }, \ - { "dword", MASK_DWORD, "Change ABI to allow double word insns" }, \ - { "no-dword", -MASK_DWORD, "Do not use double word insns" }, \ - { "double", MASK_DOUBLE, "Use fp double instructions" }, \ - { "no-double", -MASK_DOUBLE, "Do not use fp double insns" }, \ - { "media", MASK_MEDIA, "Use media instructions" }, \ - { "no-media", -MASK_MEDIA, "Do not use media insns" }, \ - { "muladd", MASK_MULADD, "Use multiply add/subtract instructions" }, \ - { "no-muladd", -MASK_MULADD, "Do not use multiply add/subtract insns" }, \ - { "library-pic", MASK_LIBPIC, "PIC support for building libraries" }, \ - { "acc-4", MASK_ACC_4, "Use 4 media accumulators" }, \ - { "acc-8", -MASK_ACC_4, "Use 8 media accumulators" }, \ - { "pack", MASK_PACK, "Pack VLIW instructions" }, \ - { "no-pack", -MASK_PACK, "Do not pack VLIW instructions" }, \ - { "no-eflags", 0, "Do not mark ABI switches in e_flags" }, \ - { "debug-arg", MASK_DEBUG_ARG, "Internal debug switch" }, \ - { "debug-addr", MASK_DEBUG_ADDR, "Internal debug switch" }, \ - { "debug-stack", MASK_DEBUG_STACK, "Internal debug switch" }, \ - { "debug", MASK_DEBUG, "Internal debug switch" }, \ - { "debug-cond-exec", MASK_DEBUG_COND_EXEC, "Internal debug switch" }, \ - { "debug-loc", MASK_DEBUG_LOC, "Internal debug switch" }, \ - { "cond-move", -MASK_NO_COND_MOVE, "Enable conditional moves" }, \ - { "no-cond-move", MASK_NO_COND_MOVE, "Disable conditional moves" }, \ - { "scc", -MASK_NO_SCC, "Enable setting gprs to the result of comparisons" }, \ - { "no-scc", MASK_NO_SCC, "Disable setting gprs to the result of comparisons" }, \ - { "cond-exec", -MASK_NO_COND_EXEC, "Enable conditional execution other than moves/scc" }, \ - { "no-cond-exec", MASK_NO_COND_EXEC, "Disable conditional execution other than moves/scc" }, \ - { "vliw-branch", -MASK_NO_VLIW_BRANCH, "Run pass to pack branches into VLIW insns" }, \ - { "no-vliw-branch", MASK_NO_VLIW_BRANCH, "Do not run pass to pack branches into VLIW insns" }, \ - { "multi-cond-exec", -MASK_NO_MULTI_CE, "Disable optimizing &&/|| in conditional execution" }, \ - { "no-multi-cond-exec", MASK_NO_MULTI_CE, "Enable optimizing &&/|| in conditional execution" }, \ - { "nested-cond-exec", -MASK_NO_NESTED_CE, "Enable nested conditional execution optimizations" }, \ - { "no-nested-cond-exec" ,MASK_NO_NESTED_CE, "Disable nested conditional execution optimizations" }, \ - { "tomcat-stats", 0, "Cause gas to print tomcat statistics" }, \ - { "", MASK_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, the address of a variable, and an optional description string. - The variable, of type `char *', is set to the text following the fixed part of - the option as it is specified on the command line. 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, \ - "Specify the size of the short data section" } } - - This declaration is optional. */ -#define TARGET_OPTIONS \ -{ \ - { "cpu=", &frv_cpu_string, "Set cpu type" }, \ - { "branch-cost=", &frv_branch_cost_string, "Internal debug switch" }, \ - { "cond-exec-insns=", &frv_condexec_insns_str, "Internal debug switch" }, \ - { "cond-exec-temps=", &frv_condexec_temps_str, "Internal debug switch" }, \ - { "sched-lookahead=", &frv_sched_lookahead_str,"Internal debug switch" }, \ -} - -/* 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, _(" (frv)")) - -/* 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 frv_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) frv_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. */ -/* Frv needs a specific frame layout that includes the frame pointer */ - -#define CAN_DEBUG_WITHOUT_FP - - -/* Small Data Area Support. */ -/* Maximum size of variables that go in .sdata/.sbss. - The -msdata=foo switch also controls how small variables are handled. */ -#ifndef SDATA_DEFAULT_SIZE -#define SDATA_DEFAULT_SIZE 8 -#endif - -extern int g_switch_value; /* value of the -G xx switch */ -extern int g_switch_set; /* whether -G xx was passed. */ - - -/* 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 - -/* Number of storage units in a word; normally 4. */ -#define UNITS_PER_WORD 4 - -/* 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 64 - -/* Alignment required for a function entry point, in bits. */ -#define FUNCTION_BOUNDARY 128 - -/* Biggest alignment that any data type can require on this machine, - in bits. */ -#define BIGGEST_ALIGNMENT 64 - -/* @@@ A hack, needed because libobjc wants to use ADJUST_FIELD_ALIGN for - some reason. */ -#ifdef IN_TARGET_LIBS -#define BIGGEST_FIELD_ALIGNMENT 64 -#else -/* An expression for the alignment of a structure field FIELD if the - alignment computed in the usual way is COMPUTED. 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) \ - frv_adjust_field_align (FIELD, COMPUTED) -#endif - -/* If defined, a C expression to compute the alignment for a static variable. - TYPE is the data type, and ALIGN is the alignment that the object - would ordinarily have. The value of this macro is used instead of that - alignment to align the object. - - If this macro is not defined, then ALIGN is used. - - 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)) - -/* 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 - - -/* 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_FP (GPR_FIRST + 2) /* Frame pointer */ -#define GPR_SP (GPR_FIRST + 1) /* Stack pointer */ - /* small data register */ -#define SDA_BASE_REG ((unsigned)(flag_pic ? PIC_REGNO : (GPR_FIRST+16))) -#define PIC_REGNO (GPR_FIRST + 17) /* PIC register */ - -#define FPR_FIRST 64 /* First FP reg */ -#define FPR_LAST 127 /* Last FP reg */ - -#define DEFAULT_CONDEXEC_TEMPS 4 /* reserve 4 regs by default */ -#define GPR_TEMP_NUM frv_condexec_temps /* # gprs to reserve for temps */ - -/* We reserve the last CR and CCR in each category to be used as a reload - register to reload the CR/CCR registers. This is a kludge. */ -#define CC_FIRST 128 /* First ICC/FCC reg */ -#define CC_LAST 135 /* Last ICC/FCC reg */ -#define ICC_FIRST (CC_FIRST + 4) /* First ICC reg */ -#define ICC_LAST (CC_FIRST + 7) /* Last ICC reg */ -#define ICC_TEMP (CC_FIRST + 7) /* Temporary ICC reg */ -#define FCC_FIRST (CC_FIRST) /* First FCC reg */ -#define FCC_LAST (CC_FIRST + 3) /* Last FCC reg */ - -/* Amount to shift a value to locate a ICC or FCC register in the CCR - register and shift it to the bottom 4 bits. */ -#define CC_SHIFT_RIGHT(REGNO) (((REGNO) - CC_FIRST) << 2) - -/* Mask to isolate a single ICC/FCC value. */ -#define CC_MASK 0xf - -/* Masks to isolate the various bits in an ICC field. */ -#define ICC_MASK_N 0x8 /* negative */ -#define ICC_MASK_Z 0x4 /* zero */ -#define ICC_MASK_V 0x2 /* overflow */ -#define ICC_MASK_C 0x1 /* carry */ - -/* Mask to isolate the N/Z flags in an ICC. */ -#define ICC_MASK_NZ (ICC_MASK_N | ICC_MASK_Z) - -/* Mask to isolate the Z/C flags in an ICC. */ -#define ICC_MASK_ZC (ICC_MASK_Z | ICC_MASK_C) - -/* Masks to isolate the various bits in a FCC field. */ -#define FCC_MASK_E 0x8 /* equal */ -#define FCC_MASK_L 0x4 /* less than */ -#define FCC_MASK_G 0x2 /* greater than */ -#define FCC_MASK_U 0x1 /* unordered */ - -/* For CCR registers, the machine wants CR4..CR7 to be used for integer - code and CR0..CR3 to be used for floating point. */ -#define CR_FIRST 136 /* First CCR */ -#define CR_LAST 143 /* Last CCR */ -#define CR_NUM (CR_LAST-CR_FIRST+1) /* # of CCRs (8) */ -#define ICR_FIRST (CR_FIRST + 4) /* First integer CCR */ -#define ICR_LAST (CR_FIRST + 7) /* Last integer CCR */ -#define ICR_TEMP ICR_LAST /* Temp integer CCR */ -#define FCR_FIRST (CR_FIRST + 0) /* First float CCR */ -#define FCR_LAST (CR_FIRST + 3) /* Last float CCR */ - -/* Amount to shift a value to locate a CR register in the CCCR special purpose - register and shift it to the bottom 2 bits. */ -#define CR_SHIFT_RIGHT(REGNO) (((REGNO) - CR_FIRST) << 1) - -/* Mask to isolate a single CR value. */ -#define CR_MASK 0x3 - -#define ACC_FIRST 144 /* First acc register */ -#define ACC_LAST 151 /* Last acc register */ - -#define ACCG_FIRST 152 /* First accg register */ -#define ACCG_LAST 159 /* Last accg register */ - -#define AP_FIRST 160 /* fake argument pointer */ - -#define SPR_FIRST 161 -#define SPR_LAST 162 -#define LR_REGNO (SPR_FIRST) -#define LCR_REGNO (SPR_FIRST + 1) - -#define GPR_P(R) IN_RANGE_P (R, GPR_FIRST, GPR_LAST) -#define GPR_OR_AP_P(R) (GPR_P (R) || (R) == ARG_POINTER_REGNUM) -#define FPR_P(R) IN_RANGE_P (R, FPR_FIRST, FPR_LAST) -#define CC_P(R) IN_RANGE_P (R, CC_FIRST, CC_LAST) -#define ICC_P(R) IN_RANGE_P (R, ICC_FIRST, ICC_LAST) -#define FCC_P(R) IN_RANGE_P (R, FCC_FIRST, FCC_LAST) -#define CR_P(R) IN_RANGE_P (R, CR_FIRST, CR_LAST) -#define ICR_P(R) IN_RANGE_P (R, ICR_FIRST, ICR_LAST) -#define FCR_P(R) IN_RANGE_P (R, FCR_FIRST, FCR_LAST) -#define ACC_P(R) IN_RANGE_P (R, ACC_FIRST, ACC_LAST) -#define ACCG_P(R) IN_RANGE_P (R, ACCG_FIRST, ACCG_LAST) -#define SPR_P(R) IN_RANGE_P (R, SPR_FIRST, SPR_LAST) - -#define GPR_OR_PSEUDO_P(R) (GPR_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define FPR_OR_PSEUDO_P(R) (FPR_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define GPR_AP_OR_PSEUDO_P(R) (GPR_OR_AP_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define CC_OR_PSEUDO_P(R) (CC_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define ICC_OR_PSEUDO_P(R) (ICC_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define FCC_OR_PSEUDO_P(R) (FCC_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define CR_OR_PSEUDO_P(R) (CR_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define ICR_OR_PSEUDO_P(R) (ICR_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define FCR_OR_PSEUDO_P(R) (FCR_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define ACC_OR_PSEUDO_P(R) (ACC_P (R) || (R) >= FIRST_PSEUDO_REGISTER) -#define ACCG_OR_PSEUDO_P(R) (ACCG_P (R) || (R) >= FIRST_PSEUDO_REGISTER) - -#define MAX_STACK_IMMEDIATE_OFFSET 2047 - - -/* 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 (SPR_LAST + 1) - -/* The first/last register that can contain the arguments to a function. */ -#define FIRST_ARG_REGNUM (GPR_FIRST + 8) -#define LAST_ARG_REGNUM (FIRST_ARG_REGNUM + FRV_NUM_ARG_REGS - 1) - -/* Registers used by the exception handling functions. These should be - registers that are not otherwised used by the calling sequence. */ -#define FIRST_EH_REGNUM 14 -#define LAST_EH_REGNUM 15 - -/* Scratch registers used in the prologue, epilogue and thunks. - OFFSET_REGNO is for loading constant addends that are too big for a - single instruction. TEMP_REGNO is used for transferring SPRs to and from - the stack, and various other activities. */ -#define OFFSET_REGNO 4 -#define TEMP_REGNO 5 - -/* Registers used in the prologue. OLD_SP_REGNO is the old stack pointer, - which is sometimes used to set up the frame pointer. */ -#define OLD_SP_REGNO 6 - -/* Registers used in the epilogue. STACKADJ_REGNO stores the exception - handler's stack adjustment. */ -#define STACKADJ_REGNO 6 - -/* Registers used in thunks. JMP_REGNO is used for loading the target - address. */ -#define JUMP_REGNO 6 - -#define EH_RETURN_DATA_REGNO(N) ((N) <= (LAST_EH_REGNUM - FIRST_EH_REGNUM)? \ - (N) + FIRST_EH_REGNUM : INVALID_REGNUM) -#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (SImode, STACKADJ_REGNO) -#define EH_RETURN_HANDLER_RTX RETURN_ADDR_RTX (0, frame_pointer_rtx) - -/* 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'. */ - -/* gr0 -- Hard Zero - gr1 -- Stack Pointer - gr2 -- Frame Pointer - gr3 -- Hidden Parameter - gr16 -- Small Data reserved - gr17 -- Pic reserved - gr28 -- OS reserved - gr29 -- OS reserved - gr30 -- OS reserved - gr31 -- OS reserved - cr3 -- reserved to reload FCC registers. - cr7 -- reserved to reload ICC registers. */ -#define FIXED_REGISTERS \ -{ /* Integer Registers */ \ - 1, 1, 1, 1, 0, 0, 0, 0, /* 000-007, gr0 - gr7 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 008-015, gr8 - gr15 */ \ - 1, 1, 0, 0, 0, 0, 0, 0, /* 016-023, gr16 - gr23 */ \ - 0, 0, 0, 0, 1, 1, 1, 1, /* 024-031, gr24 - gr31 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 032-039, gr32 - gr39 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 040-040, gr48 - gr47 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 048-055, gr48 - gr55 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 056-063, gr56 - gr63 */ \ - /* Float Registers */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 064-071, fr0 - fr7 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 072-079, fr8 - fr15 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 080-087, fr16 - fr23 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 088-095, fr24 - fr31 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 096-103, fr32 - fr39 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 104-111, fr48 - fr47 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 112-119, fr48 - fr55 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 120-127, fr56 - fr63 */ \ - /* Condition Code Registers */ \ - 0, 0, 0, 0, /* 128-131, fcc0 - fcc3 */ \ - 0, 0, 0, 1, /* 132-135, icc0 - icc3 */ \ - /* Conditional execution Registers (CCR) */ \ - 0, 0, 0, 0, 0, 0, 0, 1, /* 136-143, cr0 - cr7 */ \ - /* Accumulators */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 144-151, acc0 - acc7 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 152-159, accg0 - accg7 */ \ - /* Other registers */ \ - 1, /* 160, AP - fake arg ptr */ \ - 0, /* 161, LR - Link register*/ \ - 0, /* 162, LCR - Loop count reg*/ \ -} - -/* 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 \ -{ /* Integer Registers */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 000-007, gr0 - gr7 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 008-015, gr8 - gr15 */ \ - 1, 1, 0, 0, 0, 0, 0, 0, /* 016-023, gr16 - gr23 */ \ - 0, 0, 0, 0, 1, 1, 1, 1, /* 024-031, gr24 - gr31 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 032-039, gr32 - gr39 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 040-040, gr48 - gr47 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 048-055, gr48 - gr55 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 056-063, gr56 - gr63 */ \ - /* Float Registers */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 064-071, fr0 - fr7 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 072-079, fr8 - fr15 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 080-087, fr16 - fr23 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 088-095, fr24 - fr31 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 096-103, fr32 - fr39 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 104-111, fr48 - fr47 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 112-119, fr48 - fr55 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 120-127, fr56 - fr63 */ \ - /* Condition Code Registers */ \ - 1, 1, 1, 1, /* 128-131, fcc0 - fcc3 */ \ - 1, 1, 1, 1, /* 132-135, icc0 - icc3 */ \ - /* Conditional execution Registers (CCR) */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 136-143, cr0 - cr7 */ \ - /* Accumulators */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 144-151, acc0 - acc7 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* 152-159, accg0 - accg7 */ \ - /* Other registers */ \ - 1, /* 160, AP - fake arg ptr */ \ - 1, /* 161, LR - Link register*/ \ - 1, /* 162, LCR - Loop count reg */ \ -} - -/* 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 frv_conditional_register_usage () - - -/* 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. */ - -/* On the FRV, allocate GR16 and GR17 after other saved registers so that we - have a better chance of allocating 2 registers at a time and can use the - double word load/store instructions in the prologue. */ -#define REG_ALLOC_ORDER \ -{ \ - /* volatile registers */ \ - 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 + 32, GPR_FIRST + 33, 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, \ - \ - FPR_FIRST + 0, FPR_FIRST + 1, FPR_FIRST + 2, FPR_FIRST + 3, \ - FPR_FIRST + 4, FPR_FIRST + 5, FPR_FIRST + 6, FPR_FIRST + 7, \ - FPR_FIRST + 8, FPR_FIRST + 9, FPR_FIRST + 10, FPR_FIRST + 11, \ - FPR_FIRST + 12, FPR_FIRST + 13, FPR_FIRST + 14, FPR_FIRST + 15, \ - FPR_FIRST + 32, FPR_FIRST + 33, FPR_FIRST + 34, FPR_FIRST + 35, \ - FPR_FIRST + 36, FPR_FIRST + 37, FPR_FIRST + 38, FPR_FIRST + 39, \ - FPR_FIRST + 40, FPR_FIRST + 41, FPR_FIRST + 42, FPR_FIRST + 43, \ - FPR_FIRST + 44, FPR_FIRST + 45, FPR_FIRST + 46, FPR_FIRST + 47, \ - \ - ICC_FIRST + 0, ICC_FIRST + 1, ICC_FIRST + 2, ICC_FIRST + 3, \ - FCC_FIRST + 0, FCC_FIRST + 1, FCC_FIRST + 2, FCC_FIRST + 3, \ - CR_FIRST + 0, CR_FIRST + 1, CR_FIRST + 2, CR_FIRST + 3, \ - CR_FIRST + 4, CR_FIRST + 5, CR_FIRST + 6, CR_FIRST + 7, \ - \ - /* saved registers */ \ - 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 + 26, GPR_FIRST + 27, \ - 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, GPR_FIRST + 63, \ - GPR_FIRST + 16, GPR_FIRST + 17, \ - \ - FPR_FIRST + 16, FPR_FIRST + 17, FPR_FIRST + 18, FPR_FIRST + 19, \ - FPR_FIRST + 20, FPR_FIRST + 21, FPR_FIRST + 22, FPR_FIRST + 23, \ - FPR_FIRST + 24, FPR_FIRST + 25, FPR_FIRST + 26, FPR_FIRST + 27, \ - FPR_FIRST + 28, FPR_FIRST + 29, FPR_FIRST + 30, FPR_FIRST + 31, \ - FPR_FIRST + 48, FPR_FIRST + 49, FPR_FIRST + 50, FPR_FIRST + 51, \ - FPR_FIRST + 52, FPR_FIRST + 53, FPR_FIRST + 54, FPR_FIRST + 55, \ - FPR_FIRST + 56, FPR_FIRST + 57, FPR_FIRST + 58, FPR_FIRST + 59, \ - FPR_FIRST + 60, FPR_FIRST + 61, FPR_FIRST + 62, FPR_FIRST + 63, \ - \ - /* special or fixed registers */ \ - GPR_FIRST + 0, GPR_FIRST + 1, GPR_FIRST + 2, GPR_FIRST + 3, \ - GPR_FIRST + 28, GPR_FIRST + 29, GPR_FIRST + 30, GPR_FIRST + 31, \ - ACC_FIRST + 0, ACC_FIRST + 1, ACC_FIRST + 2, ACC_FIRST + 3, \ - ACC_FIRST + 4, ACC_FIRST + 5, ACC_FIRST + 6, ACC_FIRST + 7, \ - ACCG_FIRST + 0, ACCG_FIRST + 1, ACCG_FIRST + 2, ACCG_FIRST + 3, \ - ACCG_FIRST + 4, ACCG_FIRST + 5, ACCG_FIRST + 6, ACCG_FIRST + 7, \ - AP_FIRST, LR_REGNO, LCR_REGNO \ -} - - -/* 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)) */ - -/* On the FRV, make the CC modes take 3 words in the integer registers, so that - we can build the appropriate instructions to properly reload the values. */ -#define HARD_REGNO_NREGS(REGNO, MODE) frv_hard_regno_nregs (REGNO, MODE) - -/* 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. */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) frv_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. - - 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) (MODE1 == 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. */ -#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, - ICC_REGS, - FCC_REGS, - CC_REGS, - ICR_REGS, - FCR_REGS, - CR_REGS, - LCR_REG, - LR_REG, - SPR_REGS, - QUAD_ACC_REGS, - EVEN_ACC_REGS, - ACC_REGS, - ACCG_REGS, - QUAD_FPR_REGS, - FEVEN_REGS, - FPR_REGS, - QUAD_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", \ - "ICC_REGS", \ - "FCC_REGS", \ - "CC_REGS", \ - "ICR_REGS", \ - "FCR_REGS", \ - "CR_REGS", \ - "LCR_REG", \ - "LR_REG", \ - "SPR_REGS", \ - "QUAD_ACC_REGS", \ - "EVEN_ACC_REGS", \ - "ACC_REGS", \ - "ACCG_REGS", \ - "QUAD_FPR_REGS", \ - "FEVEN_REGS", \ - "FPR_REGS", \ - "QUAD_REGS", \ - "EVEN_REGS", \ - "GPR_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 \ -{ /* gr0-gr31 gr32-gr63 fr0-fr31 fr32-fr-63 cc/ccr/acc ap/spr */ \ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* NO_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x000000f0,0x0}, /* ICC_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x0000000f,0x0}, /* FCC_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x000000ff,0x0}, /* CC_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x0000f000,0x0}, /* ICR_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000f00,0x0}, /* FCR_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x0000ff00,0x0}, /* CR_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x4}, /* LCR_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x2}, /* LR_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x6}, /* SPR_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x00ff0000,0x0}, /* QUAD_ACC */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x00ff0000,0x0}, /* EVEN_ACC */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0x00ff0000,0x0}, /* ACC_REGS */\ - { 0x00000000,0x00000000,0x00000000,0x00000000,0xff000000,0x0}, /* ACCG_REGS*/\ - { 0x00000000,0x00000000,0xffffffff,0xffffffff,0x00000000,0x0}, /* QUAD_FPR */\ - { 0x00000000,0x00000000,0xffffffff,0xffffffff,0x00000000,0x0}, /* FEVEN_REG*/\ - { 0x00000000,0x00000000,0xffffffff,0xffffffff,0x00000000,0x0}, /* FPR_REGS */\ - { 0x0ffffffc,0xffffffff,0x00000000,0x00000000,0x00000000,0x0}, /* QUAD_REGS*/\ - { 0xfffffffc,0xffffffff,0x00000000,0x00000000,0x00000000,0x0}, /* EVEN_REGS*/\ - { 0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000,0x1}, /* GPR_REGS */\ - { 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0x7}, /* 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 [(unsigned char)(CHAR)] - -/* A C expression which is nonzero if register number NUM is suitable for use - as a base register in operand addresses. It may be either a suitable hard - register or a pseudo register that has been allocated such a hard register. */ -#define REGNO_OK_FOR_BASE_P(NUM) \ - ((NUM) < FIRST_PSEUDO_REGISTER \ - ? GPR_P (NUM) \ - : (reg_renumber [NUM] >= 0 && GPR_P (reg_renumber [NUM]))) - -/* A C expression which is nonzero if register number NUM is suitable for use - as an index register in operand addresses. It may be either a suitable hard - register or a pseudo register that has been allocated such a hard register. - - The difference between an index register and a base register is that the - index register may be scaled. If an address involves the sum of two - registers, neither one of them scaled, then either one may be labeled the - "base" and the other the "index"; but whichever labeling is used must fit - the machine's constraints of which registers may serve in each capacity. - The compiler will try both labelings, looking for one that is valid, and - will reload one or both registers only if neither labeling works. */ -#define REGNO_OK_FOR_INDEX_P(NUM) \ - ((NUM) < FIRST_PSEUDO_REGISTER \ - ? GPR_P (NUM) \ - : (reg_renumber [NUM] >= 0 && GPR_P (reg_renumber [NUM]))) - -/* A C expression that places additional restrictions on the register class to - use when it is necessary to copy value X into a register in class CLASS. - The value is a register class; perhaps CLASS, or perhaps another, smaller - class. On many machines, the following definition is safe: - - #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS - - Sometimes returning a more restrictive class makes better code. For - example, on the 68000, when X is an integer constant that is in range for a - `moveq' instruction, the value of this macro is always `DATA_REGS' as long - as CLASS includes the data registers. Requiring a data register guarantees - that a `moveq' will be used. - - If X is a `const_double', by returning `NO_REGS' you can force X into a - memory constant. This is useful on certain machines where immediate - floating values cannot be loaded into certain kinds of registers. - - This declaration must be present. */ -#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS - -#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ - frv_secondary_reload_class (CLASS, MODE, X, TRUE) - -#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ - frv_secondary_reload_class (CLASS, MODE, X, FALSE) - -/* 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) frv_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. - - This declaration is required. */ -#define CLASS_MAX_NREGS(CLASS, MODE) frv_class_max_nregs (CLASS, MODE) - -#define ZERO_P(x) (x == CONST0_RTX (GET_MODE (x))) - -/* 6 bit signed immediate. */ -#define CONST_OK_FOR_I(VALUE) IN_RANGE_P(VALUE, -32, 31) -/* 10 bit signed immediate. */ -#define CONST_OK_FOR_J(VALUE) IN_RANGE_P(VALUE, -512, 511) -/* Unused */ -#define CONST_OK_FOR_K(VALUE) 0 -/* 16 bit signed immediate. */ -#define CONST_OK_FOR_L(VALUE) IN_RANGE_P(VALUE, -32768, 32767) -/* 16 bit unsigned immediate. */ -#define CONST_OK_FOR_M(VALUE) IN_RANGE_P (VALUE, 0, 65535) -/* 12 bit signed immediate that is negative. */ -#define CONST_OK_FOR_N(VALUE) IN_RANGE_P(VALUE, -2048, -1) -/* Zero */ -#define CONST_OK_FOR_O(VALUE) ((VALUE) == 0) -/* 12 bit signed immediate that is negative. */ -#define CONST_OK_FOR_P(VALUE) IN_RANGE_P(VALUE, 1, 2047) - -/* 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' ? CONST_OK_FOR_I (VALUE) \ - : (C) == 'J' ? CONST_OK_FOR_J (VALUE) \ - : (C) == 'K' ? CONST_OK_FOR_K (VALUE) \ - : (C) == 'L' ? CONST_OK_FOR_L (VALUE) \ - : (C) == 'M' ? CONST_OK_FOR_M (VALUE) \ - : (C) == 'N' ? CONST_OK_FOR_N (VALUE) \ - : (C) == 'O' ? CONST_OK_FOR_O (VALUE) \ - : (C) == 'P' ? CONST_OK_FOR_P (VALUE) \ - : 0) - - -/* 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_G(VALUE) \ - ((GET_MODE (VALUE) == VOIDmode \ - && CONST_DOUBLE_LOW (VALUE) == 0 \ - && CONST_DOUBLE_HIGH (VALUE) == 0) \ - || ((GET_MODE (VALUE) == SFmode \ - || GET_MODE (VALUE) == DFmode) \ - && (VALUE) == CONST0_RTX (GET_MODE (VALUE)))) - -#define CONST_DOUBLE_OK_FOR_H(VALUE) 0 - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ( (C) == 'G' ? CONST_DOUBLE_OK_FOR_G (VALUE) \ - : (C) == 'H' ? CONST_DOUBLE_OK_FOR_H (VALUE) \ - : 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. */ - -/* Small data references */ -#define EXTRA_CONSTRAINT_FOR_Q(VALUE) \ - (small_data_symbolic_operand (VALUE, GET_MODE (VALUE))) - -/* Double word memory ops that take one instruction. */ -#define EXTRA_CONSTRAINT_FOR_R(VALUE) \ - (dbl_memory_one_insn_operand (VALUE, GET_MODE (VALUE))) - -/* SYMBOL_REF */ -#define EXTRA_CONSTRAINT_FOR_S(VALUE) (GET_CODE (VALUE) == SYMBOL_REF) - -/* Double word memory ops that take two instructions. */ -#define EXTRA_CONSTRAINT_FOR_T(VALUE) \ - (dbl_memory_two_insn_operand (VALUE, GET_MODE (VALUE))) - -/* Memory operand for conditional execution. */ -#define EXTRA_CONSTRAINT_FOR_U(VALUE) \ - (condexec_memory_operand (VALUE, GET_MODE (VALUE))) - -#define EXTRA_CONSTRAINT(VALUE, C) \ - ( (C) == 'Q' ? EXTRA_CONSTRAINT_FOR_Q (VALUE) \ - : (C) == 'R' ? EXTRA_CONSTRAINT_FOR_R (VALUE) \ - : (C) == 'S' ? EXTRA_CONSTRAINT_FOR_S (VALUE) \ - : (C) == 'T' ? EXTRA_CONSTRAINT_FOR_T (VALUE) \ - : (C) == 'U' ? EXTRA_CONSTRAINT_FOR_U (VALUE) \ - : 0) - - -/* Basic Stack Layout. */ - -/* Structure to describe information about a saved range of registers */ - -typedef struct frv_stack_regs { - const char * name; /* name of the register ranges */ - int first; /* first register in the range */ - int last; /* last register in the range */ - int size_1word; /* # of bytes to be stored via 1 word stores */ - int size_2words; /* # of bytes to be stored via 2 word stores */ - unsigned char field_p; /* true if the registers are a single SPR */ - unsigned char dword_p; /* true if we can do dword stores */ - unsigned char special_p; /* true if the regs have a fixed save loc. */ -} frv_stack_regs_t; - -/* Register ranges to look into saving. */ -#define STACK_REGS_GPR 0 /* Gprs (normally gr16..gr31, gr48..gr63) */ -#define STACK_REGS_FPR 1 /* Fprs (normally fr16..fr31, fr48..fr63) */ -#define STACK_REGS_LR 2 /* LR register */ -#define STACK_REGS_CC 3 /* CCrs (normally not saved) */ -#define STACK_REGS_LCR 5 /* lcr register */ -#define STACK_REGS_STDARG 6 /* stdarg registers */ -#define STACK_REGS_STRUCT 7 /* structure return (gr3) */ -#define STACK_REGS_FP 8 /* FP register */ -#define STACK_REGS_MAX 9 /* # of register ranges */ - -/* Values for save_p field. */ -#define REG_SAVE_NO_SAVE 0 /* register not saved */ -#define REG_SAVE_1WORD 1 /* save the register */ -#define REG_SAVE_2WORDS 2 /* save register and register+1 */ - -/* Structure used to define the frv stack. */ - -typedef struct frv_stack { - int total_size; /* total bytes allocated for stack */ - int vars_size; /* variable save area size */ - int parameter_size; /* outgoing parameter size */ - int stdarg_size; /* size of regs needed to be saved for stdarg */ - int regs_size; /* size of the saved registers */ - int regs_size_1word; /* # of bytes to be stored via 1 word stores */ - int regs_size_2words; /* # of bytes to be stored via 2 word stores */ - int header_size; /* size of the old FP, struct ret., LR save */ - int pretend_size; /* size of pretend args */ - int vars_offset; /* offset to save local variables from new SP*/ - int regs_offset; /* offset to save registers from new SP */ - /* register range information */ - frv_stack_regs_t regs[STACK_REGS_MAX]; - /* offset to store each register */ - int reg_offset[FIRST_PSEUDO_REGISTER]; - /* whether to save register (& reg+1) */ - unsigned char save_p[FIRST_PSEUDO_REGISTER]; -} frv_stack_t; - -/* 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 - -/* 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 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 - -/* 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) frv_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) frv_return_addr_rtx (COUNT, FRAMEADDR) - -/* This function contains machine specific function data. */ -struct machine_function GTY(()) -{ - /* True if we have created an rtx that relies on the stack frame. */ - int frame_needed; -}; - -#define RETURN_POINTER_REGNUM LR_REGNO - -/* 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) - - -/* 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_FIRST + 1) - -/* 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 + 2) - -/* 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. */ - -/* On frv this is a fake register that is eliminated in - terms of either the frame pointer or stack pointer. */ -#define ARG_POINTER_REGNUM AP_FIRST - -/* 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 + 7) -#define STATIC_CHAIN_INCOMING_REGNUM (GPR_FIRST + 7) - - -/* 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 frv_frame_pointer_required () - -/* 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) \ - ((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) \ - (OFFSET) = frv_initial_elimination_offset (FROM, TO) - - -/* Passing Function Arguments on the Stack. */ - -/* If defined, the maximum amount of space required for outgoing arguments will - be computed and placed into the variable - `current_function_outgoing_args_size'. No space will be pushed onto the - stack for each call; instead, the function prologue should increase the - stack frame size by this amount. - - Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not - proper. */ -#define ACCUMULATE_OUTGOING_ARGS 1 - -/* A C expression that should indicate the number of bytes of its own arguments - that a function pops on returning, or 0 if the function pops no arguments - and the caller must therefore pop them all after the function returns. - - FUNDECL is a C variable whose value is a tree node that describes the - function in question. Normally it is a node of type `FUNCTION_DECL' that - describes the declaration of the function. From this it is possible to - obtain the DECL_ATTRIBUTES of the function. - - FUNTYPE is a C variable whose value is a tree node that describes the - function in question. Normally it is a node of type `FUNCTION_TYPE' that - describes the data type of the function. From this it is possible to obtain - the data types of the value and arguments (if known). - - When a call to a library function is being considered, FUNTYPE will contain - an identifier node for the library function. Thus, if you need to - distinguish among various library functions, you can do so by their names. - Note that "library function" in this context means a function used to - perform arithmetic, whose name is known specially in the compiler and was - not mentioned in the C code being compiled. - - STACK-SIZE is the number of bytes of arguments passed on the stack. If a - variable number of bytes is passed, it is zero, and argument popping will - always be the responsibility of the calling function. - - On the Vax, all functions always pop their arguments, so the definition of - this macro is STACK-SIZE. On the 68000, using the standard calling - convention, no functions pop their arguments, so the value of the macro is - always 0 in this case. But an alternative calling convention is available - in which functions that take a fixed number of arguments pop them but other - functions (such as `printf') pop nothing (the caller pops all). When this - convention is in use, FUNTYPE is examined to determine whether a function - takes a fixed number of arguments. */ -#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 - - -/* 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 FRV_NUM_ARG_REGS 6 - -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way - defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous - arguments so far passed in registers; 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) \ - frv_function_arg (&CUM, 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) \ - frv_function_arg (&CUM, 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) \ - frv_function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED) - -/* extern int frv_function_arg_partial_nregs PARAMS ((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) \ - frv_function_arg_pass_by_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) \ - frv_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) \ - frv_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'. */ -#define CUMULATIVE_ARGS int - -/* A C statement (sans semicolon) for initializing the variable CUM for the - state at the beginning of the argument list. The variable has type - `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node for the data type - of the function which will receive the args, or 0 if the args are to a - compiler support library function. The value of INDIRECT is nonzero when - processing an indirect call, for example a call through a function pointer. - The value of INDIRECT is zero for a call to an explicitly named function, a - library function call, or when `INIT_CUMULATIVE_ARGS' is used to find - arguments for the function being compiled. - - When processing a call to a compiler support library function, LIBNAME - identifies which one. It is a `symbol_ref' rtx which contains the name of - the function, as a string. LIBNAME is 0 when an ordinary C function call is - being processed. Thus, each time this macro is called, either LIBNAME or - FNTYPE is nonzero, but never both of them at once. */ - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ - frv_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) \ - frv_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) \ - frv_function_arg_advance (&CUM, MODE, TYPE, NAMED) - -/* If defined, a C expression that gives the alignment boundary, in bits, of an - argument with the specified mode and type. If it is not defined, - `PARM_BOUNDARY' is used for all arguments. */ - -#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ - frv_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) <= LAST_ARG_REGNUM)) - - -/* How Scalar Function Values are Returned. */ - -/* The number of the hard register that is used to return a scalar value from a - function call. */ -#define RETURN_VALUE_REGNUM (GPR_FIRST + 8) - -/* 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. - - 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. - - 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) == RETURN) - - 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_VALUE_REGNUM) - - -/* How Large Values are Returned. */ - -/* If the structure value address is passed in a register, then - `STRUCT_VALUE_REGNUM' should be the number of that register. */ -#define STRUCT_VALUE_REGNUM (GPR_FIRST + 3) - - -/* Function Entry and Exit. */ - -/* 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 1 - -/* 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) \ -frv_asm_output_mi_thunk (FILE, THUNK_FNDECL, (long)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. - - This declaration must be present, but it can be an abort if profiling is - not implemented. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) abort () - - -/* Implementing the Varargs Macros. */ - -/* If defined, is a C expression that produces the machine-specific code for a - call to `__builtin_saveregs'. This code will be moved to the very beginning - of the function, before any parameter access are made. The return value of - this function should be an RTX that contains the value to use as the return - of `__builtin_saveregs'. - - If this macro is not defined, the compiler will output an ordinary call to - the library function `__builtin_saveregs'. */ - -#define EXPAND_BUILTIN_SAVEREGS() frv_expand_builtin_saveregs () - -/* This macro offers an alternative to using `__builtin_saveregs' and defining - the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register - arguments into the stack so that all the arguments appear to have been - passed consecutively on the stack. Once this is done, you can use the - standard implementation of varargs that works for machines that pass all - their arguments on the stack. - - The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, containing - the values that obtain after processing of the named arguments. The - arguments MODE and TYPE describe the last named argument--its machine mode - and its data type as a tree node. - - The macro implementation should do two things: first, push onto the stack - all the argument registers *not* used for the named arguments, and second, - store the size of the data thus pushed into the `int'-valued variable whose - name is supplied as the argument PRETEND_ARGS_SIZE. The value that you - store here will serve as additional offset for setting up the stack frame. - - Because you must generate code to push the anonymous arguments at compile - time without knowing their data types, `SETUP_INCOMING_VARARGS' is only - useful on machines that have just a single category of argument register and - use it uniformly for all data types. - - If the argument SECOND_TIME is nonzero, it means that the arguments of the - function are being analyzed for the second time. This happens for an inline - function, which is not actually compiled until the end of the source file. - The macro `SETUP_INCOMING_VARARGS' should not generate any instructions in - this case. */ -#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_ARGS_SIZE, SECOND_TIME) \ - frv_setup_incoming_varargs (& ARGS_SO_FAR, (int) MODE, TYPE, \ - & PRETEND_ARGS_SIZE, SECOND_TIME) - -/* Implement the stdarg/varargs va_start macro. STDARG_P is non-zero if this - is stdarg.h instead of varargs.h. VALIST is the tree of the va_list - variable to initialize. NEXTARG is the machine independent notion of the - 'next' argument after the variable arguments. If not defined, a standard - implementation will be defined that works for arguments passed on the stack. */ - -#define EXPAND_BUILTIN_VA_START(VALIST, NEXTARG) \ - (frv_expand_builtin_va_start(VALIST, NEXTARG)) - -/* Implement the stdarg/varargs va_arg macro. VALIST is the variable of type - va_list as a tree, TYPE is the type passed to va_arg. */ - -#define EXPAND_BUILTIN_VA_ARG(VALIST, TYPE) \ - (frv_expand_builtin_va_arg (VALIST, TYPE)) - - -/* Trampolines for Nested Functions. */ - -/* A C expression for the size in bytes of the trampoline, as an integer. */ -#define TRAMPOLINE_SIZE frv_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 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) \ - frv_initialize_trampoline (ADDR, FNADDR, STATIC_CHAIN) - -/* 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. */ - -#ifdef __FRV_UNDERSCORE__ -#define TRAMPOLINE_TEMPLATE_NAME "___trampoline_template" -#else -#define TRAMPOLINE_TEMPLATE_NAME "__trampoline_template" -#endif - -#define TRANSFER_FROM_TRAMPOLINE \ -extern int _write (int, const void *, unsigned); \ - \ -void \ -__trampoline_setup (addr, size, fnaddr, sc) \ - short * addr; \ - int size; \ - int fnaddr; \ - int sc; \ -{ \ - extern short __trampoline_template[]; \ - short * to = addr; \ - short * from = &__trampoline_template[0]; \ - int i; \ - \ - if (size < 20) \ - { \ - _write (2, "__trampoline_setup bad size\n", \ - sizeof ("__trampoline_setup bad size\n") - 1); \ - exit (-1); \ - } \ - \ - to[0] = from[0]; \ - to[1] = (short)(fnaddr); \ - to[2] = from[2]; \ - to[3] = (short)(sc); \ - to[4] = from[4]; \ - to[5] = (short)(fnaddr >> 16); \ - to[6] = from[6]; \ - to[7] = (short)(sc >> 16); \ - to[8] = from[8]; \ - to[9] = from[9]; \ - \ - for (i = 0; i < 20; i++) \ - __asm__ volatile ("dcf @(%0,%1)\n\tici @(%0,%1)" :: "r" (to), "r" (i)); \ -} \ - \ -__asm__("\n" \ - "\t.globl " TRAMPOLINE_TEMPLATE_NAME "\n" \ - "\t.text\n" \ - TRAMPOLINE_TEMPLATE_NAME ":\n" \ - "\tsetlos #0, gr6\n" /* jump register */ \ - "\tsetlos #0, gr7\n" /* static chain */ \ - "\tsethi #0, gr6\n" \ - "\tsethi #0, gr7\n" \ - "\tjmpl @(gr0,gr6)\n"); - - -/* Implicit Calls to Library Routines. */ - -/* 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 "__modi" - -/* 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 "__umodi" - -/* 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 "__mulll" - -/* 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 "__divll" - -/* 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 "__udivll" - -/* 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 "__modll" - -/* 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 "__umodll" - -/* 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 \ - do \ - { \ - add_optab->handlers [(int) DImode].libfunc \ - = init_one_libfunc ("__addll"); \ - sub_optab->handlers [(int) DImode].libfunc \ - = init_one_libfunc ("__subll"); \ - and_optab->handlers [(int) DImode].libfunc \ - = init_one_libfunc ("__andll"); \ - ior_optab->handlers [(int) DImode].libfunc \ - = init_one_libfunc ("__orll"); \ - xor_optab->handlers [(int) DImode].libfunc \ - = init_one_libfunc ("__xorll"); \ - one_cmpl_optab->handlers [(int) DImode].libfunc \ - = init_one_libfunc ("__notll"); \ - add_optab->handlers [(int) SFmode].libfunc \ - = init_one_libfunc ("__addf"); \ - sub_optab->handlers [(int) SFmode].libfunc \ - = init_one_libfunc ("__subf"); \ - smul_optab->handlers [(int) SFmode].libfunc \ - = init_one_libfunc ("__mulf"); \ - sdiv_optab->handlers [(int) SFmode].libfunc \ - = init_one_libfunc ("__divf"); \ - add_optab->handlers [(int) DFmode].libfunc \ - = init_one_libfunc ("__addd"); \ - sub_optab->handlers [(int) DFmode].libfunc \ - = init_one_libfunc ("__subd"); \ - smul_optab->handlers [(int) DFmode].libfunc \ - = init_one_libfunc ("__muld"); \ - sdiv_optab->handlers [(int) DFmode].libfunc \ - = init_one_libfunc ("__divd"); \ - fixsfsi_libfunc = init_one_libfunc ("__ftoi"); \ - fixunssfsi_libfunc = init_one_libfunc ("__ftoui"); \ - fixsfdi_libfunc = init_one_libfunc ("__ftoll"); \ - fixunssfdi_libfunc = init_one_libfunc ("__ftoull"); \ - fixdfsi_libfunc = init_one_libfunc ("__dtoi"); \ - fixunsdfsi_libfunc = init_one_libfunc ("__dtoui"); \ - fixdfdi_libfunc = init_one_libfunc ("__dtoll"); \ - fixunsdfdi_libfunc = init_one_libfunc ("__dtoull"); \ - floatsisf_libfunc = init_one_libfunc ("__itof"); \ - floatdisf_libfunc = init_one_libfunc ("__lltof"); \ - floatsidf_libfunc = init_one_libfunc ("__itod"); \ - floatdidf_libfunc = init_one_libfunc ("__lltod"); \ - extendsfdf2_libfunc = init_one_libfunc ("__ftod"); \ - truncdfsf2_libfunc = init_one_libfunc ("__dtof"); \ - } \ - while (0) - - -/* Addressing Modes. */ - -/* 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. - - 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 - `(* targetm.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, LABEL) \ - do \ - { \ - if (frv_legitimate_address_p (MODE, X, REG_OK_STRICT_P, FALSE)) \ - goto LABEL; \ - } \ - 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_AP_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. */ - -/* On the FRV, we use it to convert small data and pic references into using - the appropriate pointer in the address. */ -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ - do \ - { \ - rtx newx = frv_legitimize_address (X, OLDX, MODE); \ - \ - if (newx) \ - { \ - (X) = newx; \ - goto WIN; \ - } \ - } \ - while (0) - -/* A C statement or compound statement with a conditional `goto LABEL;' - executed if memory address X (an RTX) can have different meanings depending - on the machine mode of the memory reference it is used for 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) frv_legitimate_constant_p (X) - -/* The load-and-update commands allow pre-modification in addresses. - The index has to be in a register. */ -#define HAVE_PRE_MODIFY_REG 1 - - -/* 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) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - ? CC_FPmode \ - : (((OP) == LEU || (OP) == GTU || (OP) == LTU || (OP) == GEU) \ - ? CC_UNSmode \ - : CCmode)) - -/* 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) */ - -/* On frv, don't consider floating point comparisons to be reversible. In - theory, fp equality comparisons can be reversible */ -#define REVERSIBLE_CC_MODE(MODE) ((MODE) == CCmode || (MODE) == CC_UNSmode) - -/* Frv CCR_MODE's are not reversible. */ -#define REVERSE_CONDEXEC_PREDICATES_P(x,y) 0 - - -/* 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) \ - case CONST: \ - case LABEL_REF: \ - case SYMBOL_REF: \ - case CONST_DOUBLE: \ - return COSTS_N_INSNS (2); \ - \ - case CONST_INT: \ - /* Make 12 bit integers really cheap */ \ - return IN_RANGE_P (INTVAL (X), -2048, 2047) ? 0 : 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. 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 PLUS: \ - case MINUS: \ - case AND: \ - case IOR: \ - case XOR: \ - case ASHIFT: \ - case ASHIFTRT: \ - case LSHIFTRT: \ - case NOT: \ - case NEG: \ - case COMPARE: \ - if (GET_MODE (X) == SImode) \ - return COSTS_N_INSNS (1); \ - else if (GET_MODE (X) == DImode) \ - return COSTS_N_INSNS (2); \ - else \ - return COSTS_N_INSNS (3); /* guess */ \ - \ - case MULT: \ - if (GET_MODE (X) == SImode) \ - return COSTS_N_INSNS (2); \ - else \ - return COSTS_N_INSNS (6); /* guess */ \ - \ - case DIV: \ - case UDIV: \ - return COSTS_N_INSNS (18); - -/* A C expression for the cost of moving data from a register in class FROM to - one in class TO. The classes are expressed using the enumeration values - such as `GENERAL_REGS'. A value of 4 is the default; other values are - interpreted relative to that. - - It is not required that the cost always equal 2 when FROM is the same as TO; - on some machines it is expensive to move between registers if they are not - general registers. - - If reload sees an insn consisting of a single `set' between two hard - registers, and if `REGISTER_MOVE_COST' applied to their classes returns a - value of 2, reload does not check to ensure that the constraints of the insn - are met. Setting a cost of other than 2 will allow reload to verify that - the constraints are met. You should do this if the `movM' pattern's - constraints do not allow such copying. */ -#define REGISTER_MOVE_COST(MODE, FROM, TO) frv_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) 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. */ - -/* 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. */ - -/* We used to default the branch cost to 2, but I changed it to 1, to avoid - generating SCC instructions and or/and-ing them together, and then doing the - branch on the result, which collectively generate much worse code. */ -#ifndef DEFAULT_BRANCH_COST -#define DEFAULT_BRANCH_COST 1 -#endif - -#define BRANCH_COST frv_branch_cost_int - -/* Define this macro as a C expression which is nonzero if accessing less than - a word of memory (i.e. a `char' or a `short') is no faster than accessing a - word of memory, i.e., if such access require more than one instruction or if - there is no difference in cost between byte and (aligned) word loads. - - When this macro is not defined, the compiler will access a field by finding - the smallest containing object; when it is defined, a fullword load will be - used if alignment permits. Unless bytes accesses are faster than word - accesses, using word accesses is preferable since it may eliminate - subsequent memory access if subsequent accesses occur to other fields in the - same word of the structure, but to different bytes. */ -#define SLOW_BYTE_ACCESS 1 - -/* Define this macro if it is as good or better to call a constant function - address than to call an address kept in a register. */ -#define NO_FUNCTION_CSE - -/* 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 - - -/* Dividing the output into sections. */ - -/* A C expression whose value is a string containing the assembler operation - that should precede instructions and read-only data. Normally `".text"' is - right. */ -#define TEXT_SECTION_ASM_OP "\t.text" - -/* A C expression whose value is a string containing the assembler operation to - identify the following data as writable initialized data. Normally - `".data"' is right. */ -#define DATA_SECTION_ASM_OP "\t.data" - -/* If defined, a C expression whose value is a string containing the - assembler operation to identify the following data as - uninitialized global data. If not defined, and neither - `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined, - uninitialized global data will be output in the data section if - `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be - used. */ -#define BSS_SECTION_ASM_OP "\t.section .bss,\"aw\"" - -/* Short Data Support */ -#define SDATA_SECTION_ASM_OP "\t.section .sdata,\"aw\"" -#define SBSS_SECTION_ASM_OP "\t.section .sbss,\"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. - - The standard System V.4 macros will work, but they look ugly in the - assembly output, so redefine them. */ - -#undef INIT_SECTION_ASM_OP -#undef FINI_SECTION_ASM_OP -#define INIT_SECTION_ASM_OP "\t.section .init,\"ax\"" -#define FINI_SECTION_ASM_OP "\t.section .fini,\"ax\"" - -/* A C expression whose value is a string containing the assembler operation to - switch to the fixup section that records all initialized pointers in a -fpic - program so they can be changed program startup time if the program is loaded - at a different address than linked for. */ -#define FIXUP_SECTION_ASM_OP "\t.section .rofixup,\"a\"" - -/* 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). */ -#undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_sdata, in_sbss, in_const, in_fixup - -/* 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'. */ -#undef EXTRA_SECTION_FUNCTIONS -#define EXTRA_SECTION_FUNCTIONS \ -SDATA_SECTION_FUNCTION \ -SBSS_SECTION_FUNCTION \ -FIXUP_SECTION_FUNCTION - - -#define SDATA_SECTION_FUNCTION \ -void \ -sdata_section () \ -{ \ - if (in_section != in_sdata) \ - { \ - fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \ - in_section = in_sdata; \ - } \ -} \ - -#define SBSS_SECTION_FUNCTION \ -void \ -sbss_section () \ -{ \ - if (in_section != in_sbss) \ - { \ - fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \ - in_section = in_sbss; \ - } \ -} \ - -#define FIXUP_SECTION_FUNCTION \ -void \ -fixup_section () \ -{ \ - if (in_section != in_fixup) \ - { \ - fprintf (asm_out_file, "%s\n", FIXUP_SECTION_ASM_OP); \ - in_section = in_fixup; \ - } \ -} \ - -#define SDATA_FLAG_CHAR '@' - -#define SDATA_NAME_P(NAME) (*(NAME) == SDATA_FLAG_CHAR) - -/* Position Independent Code. */ - -/* 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) \ - ( GET_CODE (X) == CONST_INT \ - || GET_CODE (X) == CONST_DOUBLE \ - || (GET_CODE (X) == HIGH && GET_CODE (XEXP (X, 0)) == CONST_INT) \ - || GET_CODE (X) == CONSTANT_P_RTX) - - -/* The Overall Framework of an Assembler File. */ - -/* A C string constant describing how to begin a comment in the target - assembler language. The compiler assumes that the comment will end at the - end of the line. */ -#define ASM_COMMENT_START ";" - -/* A C string constant for text to be output before each `asm' statement or - group of consecutive ones. Normally this is `"#APP"', which is a comment - that has no effect on most assemblers but tells the GNU assembler that it - must check the lines that follow for all valid assembler constructs. */ -#define ASM_APP_ON "#APP\n" - -/* A C string constant for text to be output after each `asm' statement or - group of consecutive ones. Normally this is `"#NO_APP"', which tells the - GNU assembler to resume making the time-saving assumptions that are valid - for ordinary compiler output. */ -#define ASM_APP_OFF "#NO_APP\n" - - -/* Output of Data. */ - -/* This is how to output a label to dwarf/dwarf2. */ -#define ASM_OUTPUT_DWARF_ADDR(STREAM, LABEL) \ -do { \ - fprintf (STREAM, "\t.picptr\t"); \ - assemble_name (STREAM, LABEL); \ -} while (0) - -/* Whether to emit the gas specific dwarf2 line number support. */ -#define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DEBUG_LOC) - -/* Output of Uninitialized Variables. */ - -/* 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. */ -#undef ASM_OUTPUT_LOCAL - -/* 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. */ -#undef ASM_OUTPUT_ALIGNED_LOCAL - -/* This is for final.c, because it is used by ASM_DECLARE_OBJECT_NAME. */ -extern int size_directive_output; - -/* 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. */ -#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL -#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGN) \ -do { \ - if (SDATA_NAME_P (NAME)) \ - sbss_section (); \ - else \ - bss_section (); \ - ASM_OUTPUT_ALIGN (STREAM, floor_log2 ((ALIGN) / BITS_PER_UNIT)); \ - ASM_DECLARE_OBJECT_NAME (STREAM, NAME, DECL); \ - ASM_OUTPUT_SKIP (STREAM, (SIZE) ? (SIZE) : 1); \ -} while (0) - - -/* 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) - -/* Globalizing directive for a label. */ -#define GLOBAL_ASM_OP "\t.globl " - -/* 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'. */ -#undef ASM_OUTPUT_LABELREF -#define ASM_OUTPUT_LABELREF(STREAM, NAME) \ -do { \ - const char *_name = (NAME); \ - while (*_name == '*' || *_name == SDATA_FLAG_CHAR) \ - _name++; \ - asm_fprintf (STREAM, "%U%s", _name); \ -} while (0) - -/* 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. */ -#undef ASM_GENERATE_INTERNAL_LABEL -#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ -do { \ - sprintf (LABEL, "*.%s%ld", PREFIX, (long)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) - - -/* 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. */ -#undef INIT_SECTION_ASM_OP - -/* 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 - -/* Output appropriate code tp call a static constructor. */ -#undef ASM_OUTPUT_CONSTRUCTOR -#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \ -do { \ - ctors_section (); \ - fprintf (STREAM, "\t.picptr\t"); \ - assemble_name (STREAM, NAME); \ - fprintf (STREAM, "\n"); \ -} while (0) - -/* Output appropriate code tp call a static destructor. */ -#undef ASM_OUTPUT_DESTRUCTOR -#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \ -do { \ - dtors_section (); \ - fprintf (STREAM, "\t.picptr\t"); \ - assemble_name (STREAM, NAME); \ - fprintf (STREAM, "\n"); \ -} while (0) - - -/* 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 \ -{ \ - "gr0", "sp", "fp", "gr3", "gr4", "gr5", "gr6", "gr7", \ - "gr8", "gr9", "gr10", "gr11", "gr12", "gr13", "gr14", "gr15", \ - "gr16", "gr17", "gr18", "gr19", "gr20", "gr21", "gr22", "gr23", \ - "gr24", "gr25", "gr26", "gr27", "gr28", "gr29", "gr30", "gr31", \ - "gr32", "gr33", "gr34", "gr35", "gr36", "gr37", "gr38", "gr39", \ - "gr40", "gr41", "gr42", "gr43", "gr44", "gr45", "gr46", "gr47", \ - "gr48", "gr49", "gr50", "gr51", "gr52", "gr53", "gr54", "gr55", \ - "gr56", "gr57", "gr58", "gr59", "gr60", "gr61", "gr62", "gr63", \ - \ - "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", \ - "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15", \ - "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23", \ - "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31", \ - "fr32", "fr33", "fr34", "fr35", "fr36", "fr37", "fr38", "fr39", \ - "fr40", "fr41", "fr42", "fr43", "fr44", "fr45", "fr46", "fr47", \ - "fr48", "fr49", "fr50", "fr51", "fr52", "fr53", "fr54", "fr55", \ - "fr56", "fr57", "fr58", "fr59", "fr60", "fr61", "fr62", "fr63", \ - \ - "fcc0", "fcc1", "fcc2", "fcc3", "icc0", "icc1", "icc2", "icc3", \ - "cc0", "cc1", "cc2", "cc3", "cc4", "cc5", "cc6", "cc7", \ - "acc0", "acc1", "acc2", "acc3", "acc4", "acc5", "acc6", "acc7", \ - "accg0","accg1","accg2","accg3","accg4","accg5","accg6","accg7", \ - "ap", "lr", "lcr" \ -} - -/* 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)\ - (PTR) = frv_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)\ - frv_final_prescan_insn (INSN, OPVEC, NOPERANDS) - - -/* 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) frv_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. */ -/* . == gr0 - # == hint operand -- always zero for now - @ == small data base register (gr16) - ~ == pic register (gr17) - * == temporary integer CCR register (cr3) - & == temporary integer ICC register (icc3) */ -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ -((CODE) == '.' || (CODE) == '#' || (CODE) == SDATA_FLAG_CHAR || (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. - - This declaration must be present. */ -#define PRINT_OPERAND_ADDRESS(STREAM, X) frv_print_operand_address (STREAM, X) - -/* If defined, C string expressions to be used for the `%R', `%L', `%U', and - `%I' options of `asm_fprintf' (see `final.c'). These are useful when a - single `md' file must support multiple assembler formats. In that case, the - various `tm.h' files can define these macros differently. - - USER_LABEL_PREFIX is defined in svr4.h. */ -#undef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "" -#define REGISTER_PREFIX "" -#define LOCAL_LABEL_PREFIX "." -#define IMMEDIATE_PREFIX "#" - - -/* 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. */ -/* When generating embedded PIC or mips16 code we want to put the jump - table in the .text section. In all other cases, we want to put the - jump table in the .rdata section. Unfortunately, we can't use - JUMP_TABLES_IN_TEXT_SECTION, because it is not conditional. - Instead, we use ASM_OUTPUT_CASE_LABEL to switch back to the .text - section if appropriate. */ - -#undef ASM_OUTPUT_CASE_LABEL -#define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, TABLE) \ -do { \ - if (flag_pic) \ - function_section (current_function_decl); \ - ASM_OUTPUT_INTERNAL_LABEL (STREAM, PREFIX, NUM); \ -} while (0) - -/* Define this to determine whether case statement labels are relative to - the start of the case statement or not. */ - -#define CASE_VECTOR_PC_RELATIVE (flag_pic) - - -/* Assembler Commands for Exception Regions. */ - -/* 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 1 - -#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LR_REGNO) - -/* Assembler Commands for Alignment. */ - -/* 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. */ -#undef ASM_OUTPUT_SKIP -#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \ - fprintf (STREAM, "\t.zero\t%u\n", (NBYTES)) - -/* 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. - - This declaration is required. */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* 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 - -/* 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 \ - { "integer_register_operand", { REG, SUBREG }}, \ - { "frv_load_operand", { REG, SUBREG, MEM }}, \ - { "gpr_no_subreg_operand", { REG }}, \ - { "gpr_or_fpr_operand", { REG, SUBREG }}, \ - { "gpr_or_int12_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_fpr_or_int12_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_int10_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_int_operand", { REG, SUBREG, CONST_INT }}, \ - { "move_source_operand", { REG, SUBREG, CONST_INT, MEM, \ - CONST_DOUBLE, CONST, \ - SYMBOL_REF, LABEL_REF }}, \ - { "move_destination_operand", { REG, SUBREG, MEM }}, \ - { "condexec_source_operand", { REG, SUBREG, CONST_INT, MEM, \ - CONST_DOUBLE }}, \ - { "condexec_dest_operand", { REG, SUBREG, MEM }}, \ - { "reg_or_0_operand", { REG, SUBREG, CONST_INT }}, \ - { "lr_operand", { REG }}, \ - { "gpr_or_memory_operand", { REG, SUBREG, MEM }}, \ - { "fpr_or_memory_operand", { REG, SUBREG, MEM }}, \ - { "int12_operand", { CONST_INT }}, \ - { "int_2word_operand", { CONST_INT, CONST_DOUBLE, \ - SYMBOL_REF, LABEL_REF, CONST }}, \ - { "pic_register_operand", { REG }}, \ - { "pic_symbolic_operand", { SYMBOL_REF, LABEL_REF, CONST }}, \ - { "small_data_register_operand", { REG }}, \ - { "small_data_symbolic_operand", { SYMBOL_REF, CONST }}, \ - { "icc_operand", { REG }}, \ - { "fcc_operand", { REG }}, \ - { "cc_operand", { REG }}, \ - { "icr_operand", { REG }}, \ - { "fcr_operand", { REG }}, \ - { "cr_operand", { REG }}, \ - { "fpr_operand", { REG, SUBREG }}, \ - { "even_reg_operand", { REG, SUBREG }}, \ - { "odd_reg_operand", { REG, SUBREG }}, \ - { "even_gpr_operand", { REG, SUBREG }}, \ - { "odd_gpr_operand", { REG, SUBREG }}, \ - { "quad_fpr_operand", { REG, SUBREG }}, \ - { "even_fpr_operand", { REG, SUBREG }}, \ - { "odd_fpr_operand", { REG, SUBREG }}, \ - { "dbl_memory_one_insn_operand", { MEM }}, \ - { "dbl_memory_two_insn_operand", { MEM }}, \ - { "call_operand", { REG, SUBREG, PLUS, CONST_INT, \ - SYMBOL_REF, LABEL_REF, CONST }}, \ - { "upper_int16_operand", { CONST_INT }}, \ - { "uint16_operand", { CONST_INT }}, \ - { "relational_operator", { EQ, NE, LE, LT, GE, GT, \ - LEU, LTU, GEU, GTU }}, \ - { "signed_relational_operator", { EQ, NE, LE, LT, GE, GT }}, \ - { "unsigned_relational_operator", { LEU, LTU, GEU, GTU }}, \ - { "float_relational_operator", { EQ, NE, LE, LT, GE, GT }}, \ - { "ccr_eqne_operator", { EQ, NE }}, \ - { "minmax_operator", { SMIN, SMAX, UMIN, UMAX }}, \ - { "condexec_si_binary_operator", { PLUS, MINUS, AND, IOR, XOR, \ - ASHIFT, ASHIFTRT, LSHIFTRT }}, \ - { "condexec_si_divide_operator", { DIV, UDIV }}, \ - { "condexec_si_unary_operator", { NOT, NEG }}, \ - { "condexec_sf_binary_operator", { PLUS, MINUS, MULT, DIV }}, \ - { "condexec_sf_unary_operator", { ABS, NEG, SQRT }}, \ - { "intop_compare_operator", { PLUS, MINUS, AND, IOR, XOR, \ - ASHIFT, ASHIFTRT, LSHIFTRT }}, \ - { "condexec_intop_cmp_operator", { PLUS, MINUS, AND, IOR, XOR, \ - ASHIFT, ASHIFTRT, LSHIFTRT }}, \ - { "fpr_or_int6_operand", { REG, SUBREG, CONST_INT }}, \ - { "int6_operand", { CONST_INT }}, \ - { "int5_operand", { CONST_INT }}, \ - { "uint5_operand", { CONST_INT }}, \ - { "uint4_operand", { CONST_INT }}, \ - { "uint1_operand", { CONST_INT }}, \ - { "acc_operand", { REG, SUBREG }}, \ - { "even_acc_operand", { REG, SUBREG }}, \ - { "quad_acc_operand", { REG, SUBREG }}, \ - { "accg_operand", { REG, SUBREG }}, - -/* An alias for a machine mode name. This is the machine mode that elements of - a jump-table should have. */ -#define CASE_VECTOR_MODE SImode - -/* Define this macro if operations between registers with integral mode smaller - than a word are always performed on the entire register. Most RISC machines - have this property and most CISC machines do not. */ -#define WORD_REGISTER_OPERATIONS - -/* Define this macro to be a C expression indicating when insns that read - memory in MODE, an integral mode narrower than a word, set the bits outside - of MODE to be either the sign-extension or the zero-extension of the data - read. Return `SIGN_EXTEND' for values of MODE for which the insn - sign-extends, `ZERO_EXTEND' for which it zero-extends, and `NIL' for other - modes. - - This macro is not called with MODE non-integral or with a width greater than - or equal to `BITS_PER_WORD', so you may return any value in this case. Do - not define this macro if it would always return `NIL'. On machines where - this macro is defined, you will normally define it as the constant - `SIGN_EXTEND' or `ZERO_EXTEND'. */ -#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND - -/* Define if loading short immediate values into registers sign extends. */ -#define SHORT_IMMEDIATES_SIGN_EXTEND - -/* The maximum number of bytes that a single instruction can move quickly from - memory to memory. */ -#define MOVE_MAX 8 - -/* A C expression which is nonzero if on this machine it is safe to "convert" - an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller - than INPREC) by merely operating on it as if it had only OUTPREC bits. - - On many machines, this expression can be 1. - - When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for - which `MODES_TIEABLE_P' is 0, suboptimal code can result. If this is the - case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve - things. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* An alias for the machine mode for pointers. On most machines, define this - to be the integer mode corresponding to the width of a hardware pointer; - `SImode' on 32-bit machine or `DImode' on 64-bit machines. On some machines - you must define this to be one of the partial integer modes, such as - `PSImode'. - - The width of `Pmode' must be at least as large as the value of - `POINTER_SIZE'. If it is not equal, you must define the macro - `POINTERS_EXTEND_UNSIGNED' to specify how pointers are extended to `Pmode'. */ -#define Pmode SImode - -/* An alias for the machine mode used for memory references to functions being - called, in `call' RTL expressions. On most machines this should be - `QImode'. */ -#define FUNCTION_MODE QImode - -/* Define this macro to handle System V style pragmas: #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 - -/* 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 frv_condexec_insns - -/* Default value of MAX_CONDITIONAL_EXECUTE if no -mcond-exec-insns= */ -#define DEFAULT_CONDEXEC_INSNS 8 - -/* A C expression to modify the code described by the conditional if - information CE_INFO, possibly updating the tests in TRUE_EXPR, and - FALSE_EXPR for converting if-then and if-then-else code to conditional - instructions. Set either TRUE_EXPR or FALSE_EXPR to a null pointer if the - tests cannot be converted. */ -#define IFCVT_MODIFY_TESTS(CE_INFO, TRUE_EXPR, FALSE_EXPR) \ -frv_ifcvt_modify_tests (CE_INFO, &TRUE_EXPR, &FALSE_EXPR) - -/* A C expression to modify the code described by the conditional if - information CE_INFO, for the basic block BB, possibly updating the tests in - TRUE_EXPR, and FALSE_EXPR for converting the && and || parts of if-then or - if-then-else code to conditional instructions. OLD_TRUE and OLD_FALSE are - the previous tests. Set either TRUE_EXPR or FALSE_EXPR to a null pointer if - the tests cannot be converted. */ -#define IFCVT_MODIFY_MULTIPLE_TESTS(CE_INFO, BB, TRUE_EXPR, FALSE_EXPR) \ -frv_ifcvt_modify_multiple_tests (CE_INFO, BB, &TRUE_EXPR, &FALSE_EXPR) - -/* A C expression to modify the code described by the conditional if - information CE_INFO with the new PATTERN in INSN. If PATTERN is a null - pointer after the IFCVT_MODIFY_INSN macro executes, it is assumed that that - insn cannot be converted to be executed conditionally. */ -#define IFCVT_MODIFY_INSN(CE_INFO, PATTERN, INSN) \ -(PATTERN) = frv_ifcvt_modify_insn (CE_INFO, PATTERN, INSN) - -/* A C expression to perform any final machine dependent modifications in - converting code to conditional execution in the code described by the - conditional if information CE_INFO. */ -#define IFCVT_MODIFY_FINAL(CE_INFO) frv_ifcvt_modify_final (CE_INFO) - -/* A C expression to cancel any machine dependent modifications in converting - code to conditional execution in the code described by the conditional if - information CE_INFO. */ -#define IFCVT_MODIFY_CANCEL(CE_INFO) frv_ifcvt_modify_cancel (CE_INFO) - -/* Initialize the extra fields provided by IFCVT_EXTRA_FIELDS. */ -#define IFCVT_INIT_EXTRA_FIELDS(CE_INFO) frv_ifcvt_init_extra_fields (CE_INFO) - -/* Indicate how many instructions can be issued at the same time. */ -#define ISSUE_RATE \ -(! TARGET_PACK ? 1 \ - : (frv_cpu_type == FRV_CPU_GENERIC \ - || frv_cpu_type == FRV_CPU_FR500 \ - || frv_cpu_type == FRV_CPU_TOMCAT) ? 4 \ - : frv_cpu_type == FRV_CPU_FR400 ? 2 : 1) - -/* Set and clear whether this insn begins a VLIW insn. */ -#define CLEAR_VLIW_START(INSN) PUT_MODE (INSN, VOIDmode) -#define SET_VLIW_START(INSN) PUT_MODE (INSN, TImode) - -/* The definition of the following macro results in that the 2nd jump - optimization (after the 2nd insn scheduling) is minimal. It is - necessary to define when start cycle marks of insns (TImode is used - for this) is used for VLIW insn packing. Some jump optimizations - make such marks invalid. These marks are corrected for some - (minimal) optimizations. ??? Probably the macro is temporary. - Final solution could making the 2nd jump optimizations before the - 2nd instruction scheduling or corrections of the marks for all jump - optimizations. Although some jump optimizations are actually - deoptimizations for VLIW (super-scalar) processors. */ - -#define MINIMAL_SECOND_JUMP_OPTIMIZATION - -/* Return true if parallel operations are expected to be emitted via the - packing flag. */ -#define PACKING_FLAG_USED_P() \ -(optimize && flag_schedule_insns_after_reload && ISSUE_RATE > 1) - -/* If the following macro is defined and non zero and deterministic - finite state automata are used for pipeline hazard recognition, the - code making resource-constrained software pipelining is on. */ -#define RCSP_SOFTWARE_PIPELINING 1 - -/* If the following macro is defined and non zero and deterministic - finite state automata are used for pipeline hazard recognition, we - will try to exchange insns in queue ready to improve the schedule. - The more macro value, the more tries will be made. */ -#define FIRST_CYCLE_MULTIPASS_SCHEDULING 1 - -/* The following macro is used only when value of - FIRST_CYCLE_MULTIPASS_SCHEDULING is nonzero. The more macro value, - the more tries will be made to choose better schedule. If the - macro value is zero or negative there will be no multi-pass - scheduling. */ -#define FIRST_CYCLE_MULTIPASS_SCHEDULING_LOOKAHEAD frv_sched_lookahead - -/* Return true if a function is ok to be called as a sibcall. */ -#define FUNCTION_OK_FOR_SIBCALL(DECL) 0 - -enum frv_builtins -{ - FRV_BUILTIN_MAND, - FRV_BUILTIN_MOR, - FRV_BUILTIN_MXOR, - FRV_BUILTIN_MNOT, - FRV_BUILTIN_MAVEH, - FRV_BUILTIN_MSATHS, - FRV_BUILTIN_MSATHU, - FRV_BUILTIN_MADDHSS, - FRV_BUILTIN_MADDHUS, - FRV_BUILTIN_MSUBHSS, - FRV_BUILTIN_MSUBHUS, - FRV_BUILTIN_MPACKH, - FRV_BUILTIN_MQADDHSS, - FRV_BUILTIN_MQADDHUS, - FRV_BUILTIN_MQSUBHSS, - FRV_BUILTIN_MQSUBHUS, - FRV_BUILTIN_MUNPACKH, - FRV_BUILTIN_MDPACKH, - FRV_BUILTIN_MBTOH, - FRV_BUILTIN_MHTOB, - FRV_BUILTIN_MCOP1, - FRV_BUILTIN_MCOP2, - FRV_BUILTIN_MROTLI, - FRV_BUILTIN_MROTRI, - FRV_BUILTIN_MWCUT, - FRV_BUILTIN_MSLLHI, - FRV_BUILTIN_MSRLHI, - FRV_BUILTIN_MSRAHI, - FRV_BUILTIN_MEXPDHW, - FRV_BUILTIN_MEXPDHD, - FRV_BUILTIN_MMULHS, - FRV_BUILTIN_MMULHU, - FRV_BUILTIN_MMULXHS, - FRV_BUILTIN_MMULXHU, - FRV_BUILTIN_MMACHS, - FRV_BUILTIN_MMACHU, - FRV_BUILTIN_MMRDHS, - FRV_BUILTIN_MMRDHU, - FRV_BUILTIN_MQMULHS, - FRV_BUILTIN_MQMULHU, - FRV_BUILTIN_MQMULXHU, - FRV_BUILTIN_MQMULXHS, - FRV_BUILTIN_MQMACHS, - FRV_BUILTIN_MQMACHU, - FRV_BUILTIN_MCPXRS, - FRV_BUILTIN_MCPXRU, - FRV_BUILTIN_MCPXIS, - FRV_BUILTIN_MCPXIU, - FRV_BUILTIN_MQCPXRS, - FRV_BUILTIN_MQCPXRU, - FRV_BUILTIN_MQCPXIS, - FRV_BUILTIN_MQCPXIU, - FRV_BUILTIN_MCUT, - FRV_BUILTIN_MCUTSS, - FRV_BUILTIN_MWTACC, - FRV_BUILTIN_MWTACCG, - FRV_BUILTIN_MRDACC, - FRV_BUILTIN_MRDACCG, - FRV_BUILTIN_MTRAP, - FRV_BUILTIN_MCLRACC, - FRV_BUILTIN_MCLRACCA, - FRV_BUILTIN_MDUNPACKH, - FRV_BUILTIN_MBTOHE, - FRV_BUILTIN_MQXMACHS, - FRV_BUILTIN_MQXMACXHS, - FRV_BUILTIN_MQMACXHS, - FRV_BUILTIN_MADDACCS, - FRV_BUILTIN_MSUBACCS, - FRV_BUILTIN_MASACCS, - FRV_BUILTIN_MDADDACCS, - FRV_BUILTIN_MDSUBACCS, - FRV_BUILTIN_MDASACCS, - FRV_BUILTIN_MABSHS, - FRV_BUILTIN_MDROTLI, - FRV_BUILTIN_MCPLHI, - FRV_BUILTIN_MCPLI, - FRV_BUILTIN_MDCUTSSI, - FRV_BUILTIN_MQSATHS, - FRV_BUILTIN_MHSETLOS, - FRV_BUILTIN_MHSETLOH, - FRV_BUILTIN_MHSETHIS, - FRV_BUILTIN_MHSETHIH, - FRV_BUILTIN_MHDSETS, - FRV_BUILTIN_MHDSETH -}; - -/* Enable prototypes on the call rtl functions. */ -#define MD_CALL_PROTOTYPES 1 - -extern GTY(()) rtx frv_compare_op0; /* operand save for */ -extern GTY(()) rtx frv_compare_op1; /* comparison generation */ - -#endif /* __FRV_H__ */ diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md deleted file mode 100644 index f1668045242..00000000000 --- a/gcc/config/frv/frv.md +++ /dev/null @@ -1,7441 +0,0 @@ -;; Frv Machine Description -;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. -;; Contributed by Red Hat, 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. - - -;; :::::::::::::::::::: -;; :: -;; :: Unspec's used -;; :: -;; :::::::::::::::::::: - -(define_constants - [(UNSPEC_BLOCKAGE 0) - (UNSPEC_CC_TO_GPR 1) - (UNSPEC_GPR_TO_CC 2) - (UNSPEC_PIC_PROLOGUE 3) - (UNSPEC_CR_LOGIC 4) - (UNSPEC_STACK_ADJUST 5) - (UNSPEC_EH_RETURN_EPILOGUE 6)]) - - - -;; :::::::::::::::::::: -;; :: -;; :: 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 (6 bit signed ints). -;; 'J' Second machine-dependent integer constant (10 bit signed ints). -;; 'K' Third machine-dependent integer constant (-2048). -;; 'L' Fourth machine-dependent integer constant (16 bit signed ints). -;; 'M' Fifth machine-dependent integer constant (16 bit unsigned ints). -;; 'N' Sixth machine-dependent integer constant (-2047..-1). -;; 'O' Seventh machine-dependent integer constant (zero). -;; 'P' Eighth machine-dependent integer constant (1..2047). -;; -;; 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. - - -;; :::::::::::::::::::: -;; :: -;; :: 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'. - -(define_attr "length" "" (const_int 4)) - -;; Processor type -- this attribute must exactly match the processor_type -;; enumeration in frv-protos.h. - -(define_attr "cpu" "generic,fr500,fr400,fr300,simple,tomcat" - (const (symbol_ref "frv_cpu_type"))) - -;; Attribute is "yes" for branches and jumps that span too great a distance -;; to be implemented in the most natural way. Such instructions will use -;; a call instruction in some way. - -(define_attr "far_jump" "yes,no" (const_string "no")) - -;; Instruction type - -;; The table below summarises the types of media instruction and their -;; scheduling classification. Headings are: - -;; Type: the name of the define_attr type -;; Conditions: "yes" if conditional variants are available -;; FR500: Fujitsu's categorisation for the FR500 -;; FR400: Fujitsu's categorisation for the FR400 (but see below). - -;; On the FR400, media instructions are divided into 2 broad categories. -;; Category 1 instructions can execute in either the M0 or M1 unit and can -;; execute in parallel with other category 1 instructions. Category 2 -;; instructions must use the M0 unit, and therefore cannot run in parallel -;; with other media instructions. - -;; The FR400 documentation also divides media instructions into one of seven -;; categories (m1 to m7). m1 to m4 contain both Category 1 and Category 2 -;; instructions, so we use a combination of the categories here. - -;; Type Conditional FR500 FR400 -;; ---- ---------- ----- ----- -;; mlogic yes m1 m1:1 -;; mrdacc no m2 m4:1 -;; mwtacc no m3 m5:1 -;; maveh no m1 m1:1 -;; msath no m1 m1:1 -;; maddh yes m1 m1:1 -;; mqaddh yes m1 m1:2 -;; mpackh no m2 m3:1 -;; munpackh no m2 m3:2 -;; mdpackh no m5 m3:2 -;; mbhconv yes m2 m3:2 -;; mrot no m2 m3:1 -;; mshift no m2 m3:1 -;; mexpdhw yes m2 m3:1 -;; mexpdhd yes m2 m3:2 -;; mwcut no m2 m3:2 -;; mmulh yes m4 m2:1 -;; mmulxh no m4 m2:1 -;; mmach yes m4 m2:1 -;; mmrdh no m4 m2:1 -;; mqmulh yes m4 m2:2 -;; mqmulxh no m4 m2:2 -;; mqmach yes m4 m2:2 -;; mcpx yes m4 m2:1 -;; mqcpx yes m4 m2:2 -;; mcut no m2 m4:1 -;; mclracc no m3 m4:1 -;; mclracca no m6 m4:2 -;; mdunpackh no m2 n/a -;; mbhconve no m2 n/a -;; maddacc no n/a m2:1 -;; mdaddacc no n/a m2:2 -;; mabsh no n/a m1:1 -;; mdrot no n/a m3:2 -;; mcpl no n/a m3:2 -;; mdcut no n/a m4:2 -;; mqsath no n/a m1:2 -;; mset no n/a m1:1 - -(define_attr "type" - "int,sethi,setlo,mul,div,gload,gstore,fload,fstore,movfg,movgf,branch,jump,jumpl,call,spr,trap,fsconv,fsadd,fsmul,fmas,fsdiv,sqrt_single,fdconv,fdadd,fdmul,fddiv,sqrt_double,mlogic,maveh,msath,maddh,mqaddh,mpackh,munpackh,mdpackh,mbhconv,mrot,mshift,mexpdhw,mexpdhd,mwcut,mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach,mcpx,mqcpx,mcut,mclracc,mclracca,mdunpackh,mbhconve,mrdacc,mwtacc,maddacc,mdaddacc,mabsh,mdrot,mcpl,mdcut,mqsath,mset,m7,ccr,multi,unknown" - (const_string "unknown")) - - - -/* This is description of pipeline hazards based on DFA. The - following constructions can be used for this: - - o define_cpu_unit string [string]) describes a cpu functional unit - (separated by comma). - - 1st operand: Names of cpu function units. - 2nd operand: Name of automaton (see comments for - DEFINE_AUTOMATON). - - All define_reservations and define_cpu_units should have unique - names which can not be "nothing". - - o (exclusion_set string string) means that each CPU function unit - in the first string can not be reserved simultaneously with each - unit whose name is in the second string and vise versa. CPU - units in the string are separated by commas. For example, it is - useful for description CPU with fully pipelined floating point - functional unit which can execute simultaneously only single - floating point insns or only double floating point insns. - - o (presence_set string string) means that each CPU function unit in - the first string can not be reserved unless at least one of units - whose names are in the second string is reserved. This is an - asymmetric relation. CPU units in the string are separated by - commas. For example, it is useful for description that slot1 is - reserved after slot0 reservation for a VLIW processor. - - o (absence_set string string) means that each CPU function unit in - the first string can not be reserved only if each unit whose name - is in the second string is not reserved. This is an asymmetric - relation (actually exclusion set is analogous to this one but it - is symmetric). CPU units in the string are separated by commas. - For example, it is useful for description that slot0 can not be - reserved after slot1 or slot2 reservation for a VLIW processor. - - o (define_bypass number out_insn_names in_insn_names) names bypass with - given latency (the first number) from insns given by the first - string (see define_insn_reservation) into insns given by the - second string. Insn names in the strings are separated by - commas. - - o (define_automaton string) describes names of an automaton - generated and used for pipeline hazards recognition. The names - are separated by comma. Actually it is possibly to generate the - single automaton but unfortunately it can be very large. If we - use more one automata, the summary size of the automata usually - is less than the single one. The automaton name is used in - define_cpu_unit. All automata should have unique names. - - o (define_reservation string string) names reservation (the first - string) of cpu functional units (the 2nd string). Sometimes unit - reservations for different insns contain common parts. In such - case, you describe common part and use one its name (the 1st - parameter) in regular expression in define_insn_reservation. All - define_reservations, define results and define_cpu_units should - have unique names which can not be "nothing". - - o (define_insn_reservation name default_latency condition regexpr) - describes reservation of cpu functional units (the 3nd operand) - for instruction which is selected by the condition (the 2nd - parameter). The first parameter is used for output of debugging - information. The reservations are described by a regular - expression according the following syntax: - - regexp = regexp "," oneof - | oneof - - oneof = oneof "|" allof - | allof - - allof = allof "+" repeat - | repeat - - repeat = element "*" number - | element - - element = cpu_function_name - | reservation_name - | result_name - | "nothing" - | "(" regexp ")" - - 1. "," is used for describing start of the next cycle in - reservation. - - 2. "|" is used for describing the reservation described by the - first regular expression *or* the reservation described by - the second regular expression *or* etc. - - 3. "+" is used for describing the reservation described by the - first regular expression *and* the reservation described by - the second regular expression *and* etc. - - 4. "*" is used for convinience and simply means sequence in - which the regular expression are repeated NUMBER times with - cycle advancing (see ","). - - 5. cpu function unit name which means reservation. - - 6. reservation name -- see define_reservation. - - 7. string "nothing" means no units reservation. - -*/ - -(define_automaton "nodiv, idiv, div") - -;; An FR500 packet can contain a single control instruction or a sequence -;; of up to four operations matching the regular expression: - -;; (I FM? I? FM? | FM? FM?) B? B? - -;; where I denotes an integer operation, FM a floating-point or media -;; operation, and B a branch operation. There are two units for each type -;; of instruction: I0 and I1, FM0 and FM1, and B0 and B1. Units are -;; allocated left-to-right: the first integer instruction uses I0, the -;; second uses I1, and so on. - -;; The FR400 is similar to the FR500 except that it allows only 2 operations -;; per packet and has only one branch unit. We can use the FR500 conflict -;; description for the FR400, but need to define different cpu_units -;; later. - -;; Slot/unit combinations available on the FR400 and above: -(define_cpu_unit "sl0_i0, sl0_fm0, sl0_b0, sl0_c" "nodiv") -(define_cpu_unit "sl1_fm0, sl1_i1, sl1_fm1, sl1_b0" "nodiv") - -;; These are available on the FR500 and above: -(define_cpu_unit "sl1_b1" "nodiv") -(define_cpu_unit "sl2_i1, sl2_fm1, sl2_b0, sl2_b1" "nodiv") -(define_cpu_unit "sl3_fm1, sl3_b0, sl3_b1" "nodiv") - -;; The following describes conlicts by slots -;; slot0 -(exclusion_set "sl0_i0" "sl0_fm0,sl0_b0,sl0_c") -(exclusion_set "sl0_fm0" "sl0_b0,sl0_c") -(exclusion_set "sl0_b0" "sl0_c") - -;; slot1 -(exclusion_set "sl1_fm0" "sl1_i1,sl1_fm1,sl1_b0,sl1_b1") -(exclusion_set "sl1_i1" "sl1_fm1,sl1_b0,sl1_b1") -(exclusion_set "sl1_fm1" "sl1_b0,sl1_b1") -(exclusion_set "sl1_b0" "sl1_b1") - -;; slot2 -(exclusion_set "sl2_i1" "sl2_fm1,sl2_b0,sl2_b1") -(exclusion_set "sl2_fm1" "sl2_b0,sl2_b1") -(exclusion_set "sl2_b0" "sl2_b1") - -;; slot3 -(exclusion_set "sl3_fm1" "sl3_b0,sl3_b1") -(exclusion_set "sl3_b0" "sl3_b1") - -;; The following describes conlicts by units -;; fm0 -(exclusion_set "sl0_fm0" "sl1_fm0") - -;; b0 -(exclusion_set "sl0_b0" "sl1_b0,sl2_b0,sl3_b0") -(exclusion_set "sl1_b0" "sl2_b0,sl3_b0") -(exclusion_set "sl2_b0" "sl3_b0") - -;; i1 -(exclusion_set "sl1_i1" "sl2_i1") - -;; fm1 -(exclusion_set "sl1_fm1" "sl2_fm1,sl3_fm1") -(exclusion_set "sl2_fm1" "sl3_fm1") - -;; b1 -(exclusion_set "sl1_b1" "sl2_b1,sl3_b1") -(exclusion_set "sl2_b1" "sl3_b1") - -;; The following describes remaining combinations of conflicts -;; slot0 -(exclusion_set "sl0_i0" "sl1_fm1,sl1_b1") -(exclusion_set "sl0_fm0" "sl1_i1,sl1_b1,sl2_i1,sl2_fm1,sl3_fm1,sl3_b0") -(exclusion_set "sl0_b0" "sl1_fm0,sl1_i1,sl1_fm1,sl2_i1,sl2_fm1,sl2_b1,\ - sl3_fm1,sl3_b1") -(exclusion_set "sl0_c" "sl1_fm0,sl1_i1,sl1_fm1,sl1_b0,sl1_b1,sl2_i1,sl2_fm1,\ - sl2_b0,sl2_b1,sl3_fm1,sl3_b0,sl3_b1") - - -;; slot1 -(exclusion_set "sl1_fm0" "sl2_b1") -(exclusion_set "sl1_i1" "sl2_fm1,sl2_b1,sl3_fm1,sl3_b0") -(exclusion_set "sl1_fm1" "sl2_i1,sl2_b1,sl3_b0") -(exclusion_set "sl1_b0" "sl2_i1,sl2_fm1,sl3_fm1,sl3_b1") -(exclusion_set "sl1_b1" "sl2_i1,sl2_fm1,sl2_b0,sl3_fm1,sl3_b0") - -;; slot2 -(exclusion_set "sl2_i1" "sl3_b1") -(exclusion_set "sl2_fm1" "sl3_b1") -(exclusion_set "sl2_b0" "sl3_fm1") -(exclusion_set "sl2_b1" "sl3_fm1,sl3_b0") - -;; slot3 -(exclusion_set "sl1_fm0" "sl2_i1,sl2_fm1,sl2_b0,sl2_b1,sl3_fm1,sl3_b0,sl3_b1") -(exclusion_set "sl3_fm1" "sl2_i1,sl2_fm1,sl2_b0,sl2_b1,sl3_b0,sl3_b1") - -;; :::::::::::::::::::: -;; :: -;; :: Generic/FR500 scheduler description -;; :: -;; :::::::::::::::::::: - -;; Define reservation in order to describe only in terms of units. - -(define_reservation "i0" "sl0_i0") -(define_reservation "f0" "sl0_fm0|sl1_fm0") -(define_reservation "m0" "f0") -(define_reservation "b0" "sl0_b0|sl1_b0|sl2_b0|sl3_b0") -(define_reservation "c" "sl0_c") -(define_reservation "i1" "sl1_i1|sl2_i1") -(define_reservation "f1" "sl1_fm1|sl2_fm1|sl3_fm1") -(define_reservation "m1" "f1") -(define_reservation "b1" "sl1_b1|sl2_b1|sl3_b1") - -;; Integer insns -;; It is not possibly to issue load & store in one VLIW insn. -(define_cpu_unit "idiv1" "idiv") -(define_cpu_unit "idiv2" "idiv") -(define_cpu_unit "l0" "nodiv") -(define_cpu_unit "l1" "nodiv") -(define_cpu_unit "s0" "nodiv") - -(exclusion_set "l1,l0" "s0") - -;; We set the default_latency of sethi to be 0 to allow sethi and setlo to be -;; combined in the same VLIW instruction as allowed by the architecture. This -;; assumes the only use of sethi is always followed by a setlo of the same -;; register. -(define_insn_reservation "i1_sethi" 0 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "sethi")) - "i0|i1") - -(define_insn_reservation "i1_setlo" 1 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "setlo")) - "i0|i1") - -(define_insn_reservation "i1_int" 1 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "int")) - "i0|i1") - -(define_insn_reservation "i1_mul" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "mul")) - "i0|i1") - -(define_insn_reservation "i1_div" 19 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "div")) - "(i0|i1),(idiv1*18|idiv2*18)") - -(define_insn_reservation "i2_gload" 4 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "gload")) - "(i0|i1)+(l0|l1)") - -(define_insn_reservation "i2_fload" 4 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "fload")) - "(i0|i1)+(l0|l1)") - -(define_insn_reservation "i3_gstore" 0 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "gstore")) - "i0+s0") - -(define_insn_reservation "i3_fstore" 0 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "fstore")) - "i0+s0") - -(define_insn_reservation "i4_move_gf" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "movgf")) - "i0") - -(define_insn_reservation "i4_move_fg" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "movfg")) - "i0") - -(define_insn_reservation "i5" 0 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "jumpl")) - "i0") - -;; Clear/commit is not generated now: -(define_insn_reservation "i6" 0 (const_int 0) "i0|i1") - -;; -;; Branch-instructions -;; -(define_insn_reservation "b1/b3" 0 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "jump,branch,ccr")) - "b0|b1") - -;; The following insn is not generated now. - -(define_insn_reservation "b2" 0 (const_int 0) "b0") - -(define_insn_reservation "b4" 0 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "call")) - "b0") - -;; The following insns are not generated now. -(define_insn_reservation "b5" 0 (const_int 0) "b0|b1") -(define_insn_reservation "b6" 0 (const_int 0) "b0|b1") - -;; Control insns -(define_insn_reservation "trap" 0 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "trap")) - "c") - -(define_insn_reservation "control" 0 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "spr")) - "c") - -;; Floating point insns -(define_cpu_unit "add0" "nodiv") -(define_cpu_unit "add1" "nodiv") -(define_cpu_unit "mul0" "nodiv") -(define_cpu_unit "mul1" "nodiv") -(define_cpu_unit "div1" "div") -(define_cpu_unit "div2" "div") -(define_cpu_unit "root" "div") - -(define_bypass 4 "f1" "m1,m2,m3,m4,m5,m6,m7") -(define_insn_reservation "f1" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "fsconv,fdconv")) - "(f0|f1)") - -(define_bypass 4 "f2" "m1,m2,m3,m4,m5,m6,m7") -(define_insn_reservation "f2" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "fsadd,fdadd")) - "(f0|f1)+(add0|add1)") - -(define_bypass 4 "f3" "m1,m2,m3,m4,m5,m6,m7") -(define_insn_reservation "f3" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "fsmul,fdmul")) - "(f0|f1)+(mul0|mul1)") - -(define_bypass 11 "f4_div" "m1,m2,m3,m4,m5,m6,m7") -(define_insn_reservation "f4_div" 10 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "fsdiv,fddiv")) - "(f0|f1),(div1*9|div2*9)") - -(define_bypass 16 "f4_root" "m1,m2,m3,m4,m5,m6,m7") -(define_insn_reservation "f4_root" 15 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "sqrt_single,sqrt_double")) - "(f0|f1)+root*15") - -(define_bypass 4 "f5" "m1,m2,m3,m4,m5,m6,m7") -(define_insn_reservation "f5" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "fmas")) - "(f0|f1)+(add0|add1)+(mul0|mul1)") - -;; The following insns are not generated by gcc now: -(define_insn_reservation "f6" 0 (const_int 0) "(f0|f1)+add0+add1") -(define_insn_reservation "f7" 0 (const_int 0) "(f0|f1)+mul0+mul1") - -;; Media insns. Now they are all not generated now. -(define_cpu_unit "m1_0" "nodiv") -(define_cpu_unit "m1_1" "nodiv") -(define_cpu_unit "m2_0" "nodiv") -(define_cpu_unit "m2_1" "nodiv") -(define_cpu_unit "m3_0" "nodiv") -(define_cpu_unit "m3_1" "nodiv") -(define_cpu_unit "m4_0" "nodiv") -(define_cpu_unit "m4_1" "nodiv") -(define_cpu_unit "m5" "nodiv") -(define_cpu_unit "m6" "nodiv") -(define_cpu_unit "m7" "nodiv") - -(exclusion_set "m5,m6,m7" "m2_0,m2_1,m3_0,m3_1") -(exclusion_set "m5" "m6,m7") -(exclusion_set "m6" "m4_0,m4_1,m7") -(exclusion_set "m7" "m1_0,m1_1,add0,add1,mul0,mul1") - -(define_bypass 2 "m1" "m1,m2,m3,m4,m5,m6,m7") -(define_bypass 4 "m1" "f1,f2,f3,f4_div,f4_root,f5,f6,f7") -(define_insn_reservation "m1" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "mlogic,maveh,msath,maddh,mqaddh")) - "(m0|m1)+(m1_0|m1_1)") - -(define_bypass 2 "m2" "m1,m2,m3,m4,m5,m6,m7") -(define_bypass 4 "m2" "f1,f2,f3,f4_div,f4_root,f5,f6,f7") -(define_insn_reservation "m2" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "mrdacc,mpackh,munpackh,mbhconv,mrot,mshift,mexpdhw,mexpdhd,mwcut,mcut,mdunpackh,mbhconve")) - "(m0|m1)+(m2_0|m2_1)") - -(define_bypass 1 "m3" "m4") -(define_insn_reservation "m3" 2 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "mclracc,mwtacc")) - "(m0|m1)+(m3_0|m3_1)") - -(define_bypass 1 "m4" "m4") -(define_insn_reservation "m4" 2 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach,mcpx,mqcpx")) - "(m0|m1)+(m4_0|m4_1)") - -(define_bypass 2 "m5" "m1,m2,m3,m4,m5,m6,m7") -(define_bypass 4 "m5" "f1,f2,f3,f4_div,f4_root,f5,f6,f7") -(define_insn_reservation "m5" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "mdpackh")) - "(m0|m1)+m5") - -(define_bypass 1 "m6" "m4") -(define_insn_reservation "m6" 2 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "mclracca")) - "(m0|m1)+m6") - -(define_bypass 2 "m7" "m1,m2,m3,m4,m5,m6,m7") -(define_bypass 4 "m7" "f1,f2,f3,f4_div,f4_root,f5,f6,f7") - -(define_insn_reservation "m7" 3 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "m7")) - "(m0|m1)+m7") - -;; Unknown & multi insns starts on new cycle and the next insn starts -;; on new cycle. To describe this we consider as a control insn. -(define_insn_reservation "unknown" 1 - (and (eq_attr "cpu" "generic,fr500,tomcat") - (eq_attr "type" "unknown,multi")) - "c") - -;; :::::::::::::::::::: -;; :: -;; :: FR400 scheduler description -;; :: -;; :::::::::::::::::::: - -;; Category 2 media instructions use both media units, but can be packed -;; with non-media instructions. Use fr400_m1unit to claim the M1 unit -;; without claiming a slot. - -(define_cpu_unit "fr400_m1unit" "nodiv") - -(define_reservation "fr400_i0" "sl0_i0") -(define_reservation "fr400_i1" "sl1_i1") -(define_reservation "fr400_m0" "sl0_fm0|sl1_fm0") -(define_reservation "fr400_m1" "sl1_fm1") -(define_reservation "fr400_meither" "fr400_m0|(fr400_m1+fr400_m1unit)") -(define_reservation "fr400_mboth" "fr400_m0+fr400_m1unit") -(define_reservation "fr400_b" "sl0_b0|sl1_b0") -(define_reservation "fr400_c" "sl0_c") - -;; Name Class Units Latency -;; ==== ===== ===== ======= -;; int I1 I0/I1 1 -;; sethi I1 I0/I1 0 -- does not interfere with setlo -;; setlo I1 I0/I1 1 -;; mul I1 I0 3 (*) -;; div I1 I0 20 (*) -;; gload I2 I0 4 (*) -;; fload I2 I0 4 -- only 3 if read by a media insn -;; gstore I3 I0 0 -- provides no result -;; fstore I3 I0 0 -- provides no result -;; movfg I4 I0 3 (*) -;; movgf I4 I0 3 (*) -;; jumpl I5 I0 0 -- provides no result -;; -;; (*) The results of these instructions can be read one cycle earlier -;; than indicated. The penalty given is for instructions with write-after- -;; write dependencies. - -;; The FR400 can only do loads and stores in I0, so we there's no danger -;; of memory unit collision in the same packet. There's only one divide -;; unit too. - -(define_insn_reservation "fr400_i1_int" 1 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "int")) - "fr400_i0|fr400_i1") - -(define_insn_reservation "fr400_i1_sethi" 0 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "sethi")) - "fr400_i0|fr400_i1") - -(define_insn_reservation "fr400_i1_setlo" 1 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "setlo")) - "fr400_i0|fr400_i1") - -(define_insn_reservation "fr400_i1_mul" 3 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "mul")) - "fr400_i0") - -(define_insn_reservation "fr400_i1_div" 20 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "div")) - "fr400_i0+idiv1*19") - -(define_insn_reservation "fr400_i2_gload" 4 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "gload")) - "fr400_i0") - -(define_insn_reservation "fr400_i2_fload" 4 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "fload")) - "fr400_i0") - -(define_insn_reservation "fr400_i3_gstore" 0 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "gstore")) - "fr400_i0") - -(define_insn_reservation "fr400_i3_fstore" 0 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "fstore")) - "fr400_i0") - -(define_insn_reservation "fr400_i4_movfg" 3 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "movfg")) - "fr400_i0") - -(define_insn_reservation "fr400_i4_movgf" 3 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "movgf")) - "fr400_i0") - -(define_insn_reservation "fr400_i5_jumpl" 0 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "jumpl")) - "fr400_i0") - -;; The bypass between FPR loads and media instructions, described above. - -(define_bypass 3 - "fr400_i2_fload" - "fr400_m1_1,fr400_m1_2,\ - fr400_m2_1,fr400_m2_2,\ - fr400_m3_1,fr400_m3_2,\ - fr400_m4_1,fr400_m4_2,\ - fr400_m5") - -;; The branch instructions all use the B unit and produce no result. - -(define_insn_reservation "fr400_b" 0 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "jump,branch,ccr,call")) - "fr400_b") - -;; Control instructions use the C unit, which excludes all the others. - -(define_insn_reservation "fr400_c" 0 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "spr,trap")) - "fr400_c") - -;; Unknown instructions use the C unit, since it requires single-operation -;; packets. - -(define_insn_reservation "fr400_unknown" 1 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "unknown,multi")) - "fr400_c") - -;; FP->FP moves are marked as "fsconv" instructions in the define_insns -;; below, but are implemented on the FR400 using "mlogic" instructions. -;; It's easier to class "fsconv" as a "m1:1" instruction than provide -;; separate define_insns for the FR400. - -;; M1 instructions store their results in FPRs. Any instruction can read -;; the result in the following cycle, so no penalty occurs. - -(define_insn_reservation "fr400_m1_1" 1 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "fsconv,mlogic,maveh,msath,maddh,mabsh,mset")) - "fr400_meither") - -(define_insn_reservation "fr400_m1_2" 1 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "mqaddh,mqsath")) - "fr400_mboth") - -;; M2 instructions store their results in accumulators, which are read -;; by M2 or M4 media commands. M2 instructions can read the results in -;; the following cycle, but M4 instructions must wait a cycle more. - -(define_bypass 1 - "fr400_m2_1,fr400_m2_2" - "fr400_m2_1,fr400_m2_2") - -(define_insn_reservation "fr400_m2_1" 2 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "mmulh,mmulxh,mmach,mmrdh,mcpx,maddacc")) - "fr400_meither") - -(define_insn_reservation "fr400_m2_2" 2 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "mqmulh,mqmulxh,mqmach,mqcpx,mdaddacc")) - "fr400_mboth") - -;; For our purposes, there seems to be little real difference between -;; M1 and M3 instructions. Keep them separate anyway in case the distinction -;; is needed later. - -(define_insn_reservation "fr400_m3_1" 1 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "mpackh,mrot,mshift,mexpdhw")) - "fr400_meither") - -(define_insn_reservation "fr400_m3_2" 1 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "munpackh,mdpackh,mbhconv,mexpdhd,mwcut,mdrot,mcpl")) - "fr400_mboth") - -;; M4 instructions write to accumulators or FPRs. MOVFG and STF -;; instructions can read an FPR result in the following cycle, but -;; M-unit instructions must wait a cycle more for either kind of result. - -(define_bypass 1 - "fr400_m4_1,fr400_m4_2" - "fr400_i3_fstore,fr400_i4_movfg") - -(define_insn_reservation "fr400_m4_1" 2 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "mrdacc,mcut,mclracc")) - "fr400_meither") - -(define_insn_reservation "fr400_m4_2" 2 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "mclracca,mdcut")) - "fr400_mboth") - -;; M5 instructions always incur a 1-cycle penalty. - -(define_insn_reservation "fr400_m5" 2 - (and (eq_attr "cpu" "fr400") - (eq_attr "type" "mwtacc")) - "fr400_mboth") - -;; :::::::::::::::::::: -;; :: -;; :: Simple/FR300 scheduler description -;; :: -;; :::::::::::::::::::: - -;; Fr300 or simple processor. To describe it as 1 insn issue -;; processor, we use control unit. - -(define_insn_reservation "fr300_lat1" 1 - (and (eq_attr "cpu" "fr300,simple") - (eq_attr "type" "!gload,fload,movfg,movgf")) - "c") - -(define_insn_reservation "fr300_lat2" 2 - (and (eq_attr "cpu" "fr300,simple") - (eq_attr "type" "gload,fload,movfg,movgf")) - "c") - - -;; :::::::::::::::::::: -;; :: -;; :: 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)]) - -;; Note - it is the backend's responsibility to fill any unfilled delay slots -;; at assembler generation time. This is usually done by adding a special print -;; operand to the delayed insrtuction, and then in the PRINT_OPERAND function -;; calling dbr_sequence_length() to determine how many delay slots were filled. -;; For example: -;; -;; --------------.md----------------- -;; (define_insn "call" -;; [(call (match_operand 0 "memory_operand" "m") -;; (match_operand 1 "" ""))] -;; "" -;; "call_delayed %0,%1,%2%#" -;; [(set_attr "length" "4") -;; (set_attr "type" "call")]) -;; -;; -------------.h------------------- -;; #define PRINT_OPERAND_PUNCT_VALID_P(CODE) (CODE == '#') -;; -;; ------------.c------------------ -;; void -;; machine_print_operand (file, x, code) -;; FILE * file; -;; rtx x; -;; int code; -;; { -;; switch (code) -;; { -;; case '#': -;; if (dbr_sequence_length () == 0) -;; fputs ("\n\tnop", file); -;; return; - -;; :::::::::::::::::::: -;; :: -;; :: Notes on Patterns -;; :: -;; :::::::::::::::::::: - -;; If you need to construct a sequence of assembler instructions in order -;; to implement a pattern be sure to escape any backslashes and double quotes -;; that you use, eg: -;; -;; (define_insn "an example" -;; [(some rtl)] -;; "" -;; "* -;; { static char buffer [100]; -;; sprintf (buffer, \"insn \\t %d\", REGNO (operands[1])); -;; return buffer; -;; }" -;; ) -;; -;; Also if there is more than one instruction, they can be separated by \\; -;; which is a space saving synonym for \\n\\t: -;; -;; (define_insn "another example" -;; [(some rtl)] -;; "" -;; "* -;; { static char buffer [100]; -;; sprintf (buffer, \"insn1 \\t %d\\;insn2 \\t %%1\", -;; REGNO (operands[1])); -;; return buffer; -;; }" -;; ) -;; - - -;; :::::::::::::::::::: -;; :: -;; :: 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. - -;; 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_load" - [(set (match_operand:QI 0 "register_operand" "=d,f") - (match_operand:QI 1 "frv_load_operand" "m,m"))] - "" - "* return output_move_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "gload,fload")]) - -(define_insn "*movqi_internal" - [(set (match_operand:QI 0 "move_destination_operand" "=d,d,m,m,?f,?f,?d,?m,f") - (match_operand:QI 1 "move_source_operand" "L,d,d,O, d, f, f, f,GO"))] - "register_operand(operands[0], QImode) || reg_or_0_operand (operands[1], QImode)" - "* return output_move_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "int,int,gstore,gstore,movgf,fsconv,movfg,fstore,movgf")]) - -(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_load" - [(set (match_operand:HI 0 "register_operand" "=d,f") - (match_operand:HI 1 "frv_load_operand" "m,m"))] - "" - "* return output_move_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "gload,fload")]) - -(define_insn "*movhi_internal" - [(set (match_operand:HI 0 "move_destination_operand" "=d,d,d,m,m,?f,?f,?d,?m,f") - (match_operand:HI 1 "move_source_operand" "L,i,d,d,O, d, f, f, f,GO"))] - "register_operand(operands[0], HImode) || reg_or_0_operand (operands[1], HImode)" - "* return output_move_single (operands, insn);" - [(set_attr "length" "4,8,4,4,4,4,4,4,4,4") - (set_attr "type" "int,multi,int,gstore,gstore,movgf,fsconv,movfg,fstore,movgf")]) - -;; Split 2 word load of constants into sethi/setlo instructions -(define_split - [(set (match_operand:HI 0 "integer_register_operand" "") - (match_operand:HI 1 "int_2word_operand" ""))] - "reload_completed" - [(set (match_dup 0) - (high:HI (match_dup 1))) - (set (match_dup 0) - (lo_sum:HI (match_dup 0) - (match_dup 1)))] - "") - -(define_insn "movhi_high" - [(set (match_operand:HI 0 "integer_register_operand" "=d") - (high:HI (match_operand:HI 1 "int_2word_operand" "i")))] - "" - "sethi #hi(%1), %0" - [(set_attr "type" "sethi") - (set_attr "length" "4")]) - -(define_insn "movhi_lo_sum" - [(set (match_operand:HI 0 "integer_register_operand" "+d") - (lo_sum:HI (match_dup 0) - (match_operand:HI 1 "int_2word_operand" "i")))] - "" - "setlo #lo(%1), %0" - [(set_attr "type" "setlo") - (set_attr "length" "4")]) - -(define_expand "movsi" - [(set (match_operand:SI 0 "move_destination_operand" "") - (match_operand:SI 1 "move_source_operand" ""))] - "" - " -{ - if (frv_emit_movsi (operands[0], operands[1])) - DONE; -}") - -;; Note - it is best to only have one movsi pattern and to handle -;; all the various contingencies by the use of alternatives. This -;; allows reload the greatest amount of flexability (since reload will -;; only choose amoungst alternatives for a selected insn, it will not -;; replace the insn with another one). - -;; Unfortunately, we do have to separate out load-type moves from the rest, -;; and only allow memory source operands in the former. If we do memory and -;; constant loads in a single pattern, reload will be tempted to force -;; constants into memory when the destination is a floating-point register. -;; That may make a function use a PIC pointer when it didn't before, and we -;; cannot change PIC usage (and hence stack layout) so late in the game. -;; The resulting sequences for loading cosntants into FPRs are preferable -;; even when we're not generating PIC code. - -(define_insn "*movsi_load" - [(set (match_operand:SI 0 "register_operand" "=d,f") - (match_operand:SI 1 "frv_load_operand" "m,m"))] - "" - "* return output_move_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "gload,fload")]) - -(define_insn "*movsi_internal" - [(set (match_operand:SI 0 "move_destination_operand" "=d,d,d,m,m,z,d,d,f,f,m,?f,?z") - (match_operand:SI 1 "move_source_operand" "LQ,i,d,d,O,d,z,f,d,f,f,GO,GO"))] - "register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode)" - "* return output_move_single (operands, insn);" - [(set_attr "length" "4,8,4,4,4,4,4,4,4,4,4,4,4") - (set_attr "type" "int,multi,int,gstore,gstore,spr,spr,movfg,movgf,fsconv,fstore,movgf,spr")]) - -(define_insn "*movsi_lda_sdata" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (plus:SI (match_operand:SI 1 "small_data_register_operand" "d") - (match_operand:SI 2 "small_data_symbolic_operand" "Q")))] - "" - "addi %1, #gprel12(%2), %0" - [(set_attr "type" "int") - (set_attr "length" "4")]) - -;; Split 2 word load of constants into sethi/setlo instructions -(define_split - [(set (match_operand:SI 0 "integer_register_operand" "") - (match_operand:SI 1 "int_2word_operand" ""))] - "reload_completed" - [(set (match_dup 0) - (high:SI (match_dup 1))) - (set (match_dup 0) - (lo_sum:SI (match_dup 0) - (match_dup 1)))] - "") - -(define_insn "movsi_high" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (high:SI (match_operand:SI 1 "int_2word_operand" "i")))] - "" - "sethi #hi(%1), %0" - [(set_attr "type" "sethi") - (set_attr "length" "4")]) - -(define_insn "movsi_lo_sum" - [(set (match_operand:SI 0 "integer_register_operand" "+d") - (lo_sum:SI (match_dup 0) - (match_operand:SI 1 "int_2word_operand" "i")))] - "" - "setlo #lo(%1), %0" - [(set_attr "type" "setlo") - (set_attr "length" "4")]) - -;; Split loads of addresses with PIC specified into 3 separate instructions -(define_insn_and_split "*movsi_pic" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (plus:SI (match_operand:SI 1 "pic_register_operand" "d") - (match_operand:SI 2 "pic_symbolic_operand" "")))] - "" - "#" - "reload_completed" - [(set (match_dup 0) - (high:SI (match_dup 2))) - (set (match_dup 0) - (lo_sum:SI (match_dup 0) - (match_dup 2))) - (set (match_dup 0) - (plus:SI (match_dup 0) (match_dup 1)))] - - "" - [(set_attr "type" "multi") - (set_attr "length" "12")]) - -(define_insn "movsi_high_pic" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (high:SI (match_operand:SI 1 "pic_symbolic_operand" "")))] - "" - "sethi #gprelhi(%1), %0" - [(set_attr "type" "sethi") - (set_attr "length" "4")]) - -(define_insn "movsi_lo_sum_pic" - [(set (match_operand:SI 0 "integer_register_operand" "+d") - (lo_sum:SI (match_dup 0) - (match_operand:SI 1 "pic_symbolic_operand" "")))] - "" - "setlo #gprello(%1), %0" - [(set_attr "type" "setlo") - (set_attr "length" "4")]) - -(define_expand "movdi" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress - && !reload_completed - && !register_operand (operands[0], DImode) - && !reg_or_0_operand (operands[1], DImode)) - operands[1] = copy_to_mode_reg (DImode, operands[1]); -}") - -(define_insn "*movdi_double" - [(set (match_operand:DI 0 "move_destination_operand" "=e,?h,??d,??f,R,?R,??m,??m,e,?h,??d,??f,?e,??d,?h,??f,R,m,e,??d,e,??d,?h,??f") - (match_operand:DI 1 "move_source_operand" " e,h,d,f,e,h,d,f,R,R,m,m,h,f,e,d,GO,GO,GO,GO,nF,nF,GO,GO"))] - "TARGET_DOUBLE - && (register_operand (operands[0], DImode) - || reg_or_0_operand (operands[1], DImode))" - "* return output_move_double (operands, insn);" - [(set_attr "length" "8,4,8,8,4,4,8,8,4,4,8,8,4,8,4,8,4,8,8,8,16,16,8,8") - (set_attr "type" "multi,fdconv,multi,multi,gstore,fstore,gstore,fstore,gload,fload,gload,fload,movfg,movfg,movgf,movgf,gstore,gstore,multi,multi,multi,multi,movgf,movgf")]) - -(define_insn "*movdi_nodouble" - [(set (match_operand:DI 0 "move_destination_operand" "=e,?h,??d,??f,R,?R,??m,??m,e,?h,??d,??f,?e,??d,?h,??f,R,m,e,??d,e,??d,?h,??f") - (match_operand:DI 1 "move_source_operand" " e,h,d,f,e,h,d,f,R,R,m,m,h,f,e,d,GO,GO,GO,GO,nF,nF,GO,GO"))] - "!TARGET_DOUBLE - && (register_operand (operands[0], DImode) - || reg_or_0_operand (operands[1], DImode))" - "* return output_move_double (operands, insn);" - [(set_attr "length" "8,8,8,8,4,4,8,8,4,4,8,8,8,8,8,8,4,8,8,8,16,16,8,8") - (set_attr "type" "multi,multi,multi,multi,gstore,fstore,gstore,fstore,gload,fload,gload,fload,movfg,movfg,movgf,movgf,gstore,gstore,multi,multi,multi,multi,movgf,movgf")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "dbl_memory_two_insn_operand" ""))] - "reload_completed" - [(const_int 0)] - "frv_split_double_load (operands[0], operands[1]);") - -(define_split - [(set (match_operand:DI 0 "odd_reg_operand" "") - (match_operand:DI 1 "memory_operand" ""))] - "reload_completed" - [(const_int 0)] - "frv_split_double_load (operands[0], operands[1]);") - -(define_split - [(set (match_operand:DI 0 "dbl_memory_two_insn_operand" "") - (match_operand:DI 1 "reg_or_0_operand" ""))] - "reload_completed" - [(const_int 0)] - "frv_split_double_store (operands[0], operands[1]);") - -(define_split - [(set (match_operand:DI 0 "memory_operand" "") - (match_operand:DI 1 "odd_reg_operand" ""))] - "reload_completed" - [(const_int 0)] - "frv_split_double_store (operands[0], operands[1]);") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "register_operand" ""))] - "reload_completed - && (odd_reg_operand (operands[0], DImode) - || odd_reg_operand (operands[1], DImode) - || (integer_register_operand (operands[0], DImode) - && integer_register_operand (operands[1], DImode)) - || (!TARGET_DOUBLE - && fpr_operand (operands[0], DImode) - && fpr_operand (operands[1], DImode)))" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - " -{ - rtx op0 = operands[0]; - rtx op0_low = gen_lowpart (SImode, op0); - rtx op0_high = gen_highpart (SImode, op0); - rtx op1 = operands[1]; - rtx op1_low = gen_lowpart (SImode, op1); - rtx op1_high = gen_highpart (SImode, op1); - - /* 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 (op0_high) == REGNO (op1_low)) - { - operands[2] = op0_low; - operands[3] = op0_high; - operands[4] = op1_low; - operands[5] = op1_high; - } - else - { - operands[2] = op0_high; - operands[3] = op0_low; - operands[4] = op1_high; - operands[5] = op1_low; - } -}") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "const_int_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 1))] - " -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - - operands[2] = gen_highpart (SImode, op0); - operands[3] = gen_lowpart (SImode, op0); - operands[4] = GEN_INT ((INTVAL (op1) < 0) ? -1 : 0); -}") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "const_double_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - " -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - - operands[2] = gen_highpart (SImode, op0); - operands[3] = gen_lowpart (SImode, op0); - operands[4] = GEN_INT (CONST_DOUBLE_HIGH (op1)); - operands[5] = GEN_INT (CONST_DOUBLE_LOW (op1)); -}") - -;; 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 - && !register_operand (operands[0], SFmode) - && !reg_or_0_operand (operands[1], SFmode)) - operands[1] = copy_to_mode_reg (SFmode, operands[1]); -}") - -(define_split - [(set (match_operand:SF 0 "integer_register_operand" "") - (match_operand:SF 1 "int_2word_operand" ""))] - "reload_completed" - [(set (match_dup 0) - (high:SF (match_dup 1))) - (set (match_dup 0) - (lo_sum:SF (match_dup 0) - (match_dup 1)))] - "") - -(define_insn "*movsf_load_has_fprs" - [(set (match_operand:SF 0 "register_operand" "=f,d") - (match_operand:SF 1 "frv_load_operand" "m,m"))] - "TARGET_HAS_FPRS" - "* return output_move_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "fload,gload")]) - -(define_insn "*movsf_internal_has_fprs" - [(set (match_operand:SF 0 "move_destination_operand" "=f,f,m,m,?f,?d,?d,m,?d") - (match_operand:SF 1 "move_source_operand" "f,OG,f,OG,d,f,d,d,F"))] - "TARGET_HAS_FPRS - && (register_operand (operands[0], SFmode) || reg_or_0_operand (operands[1], SFmode))" - "* return output_move_single (operands, insn);" - [(set_attr "length" "4,4,4,4,4,4,4,4,8") - (set_attr "type" "fsconv,movgf,fstore,gstore,movgf,movfg,int,gstore,multi")]) - -;; If we don't support the double instructions, prefer gprs over fprs, since it -;; will all be emulated -(define_insn "*movsf_internal_no_fprs" - [(set (match_operand:SF 0 "move_destination_operand" "=d,d,m,d,d") - (match_operand:SF 1 "move_source_operand" " d,OG,dOG,m,F"))] - "!TARGET_HAS_FPRS - && (register_operand (operands[0], SFmode) || reg_or_0_operand (operands[1], SFmode))" - "* return output_move_single (operands, insn);" - [(set_attr "length" "4,4,4,4,8") - (set_attr "type" "int,int,gstore,gload,multi")]) - -(define_insn "movsf_high" - [(set (match_operand:SF 0 "integer_register_operand" "=d") - (high:SF (match_operand:SF 1 "int_2word_operand" "i")))] - "" - "sethi #hi(%1), %0" - [(set_attr "type" "sethi") - (set_attr "length" "4")]) - -(define_insn "movsf_lo_sum" - [(set (match_operand:SF 0 "integer_register_operand" "+d") - (lo_sum:SF (match_dup 0) - (match_operand:SF 1 "int_2word_operand" "i")))] - "" - "setlo #lo(%1), %0" - [(set_attr "type" "setlo") - (set_attr "length" "4")]) - -(define_expand "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress - && !reload_completed - && !register_operand (operands[0], DFmode) - && !reg_or_0_operand (operands[1], DFmode)) - operands[1] = copy_to_mode_reg (DFmode, operands[1]); -}") - -(define_insn "*movdf_double" - [(set (match_operand:DF 0 "move_destination_operand" "=h,?e,??f,??d,R,?R,??m,??m,h,?e,??f,??d,?h,??f,?e,??d,R,m,h,??f,e,??d") - (match_operand:DF 1 "move_source_operand" " h,e,f,d,h,e,f,d,R,R,m,m,e,d,h,f,GO,GO,GO,GO,GO,GO"))] - "TARGET_DOUBLE - && (register_operand (operands[0], DFmode) - || reg_or_0_operand (operands[1], DFmode))" - "* return output_move_double (operands, insn);" - [(set_attr "length" "4,8,8,8,4,4,8,8,4,4,8,8,4,8,4,8,4,8,8,8,8,8") - (set_attr "type" "fdconv,multi,multi,multi,fstore,gstore,fstore,gstore,fload,gload,fload,gload,movgf,movgf,movfg,movfg,gstore,gstore,movgf,movgf,multi,multi")]) - -;; If we don't support the double instructions, prefer gprs over fprs, since it -;; will all be emulated -(define_insn "*movdf_nodouble" - [(set (match_operand:DF 0 "move_destination_operand" "=e,?h,??d,??f,R,?R,??m,??m,e,?h,??d,??f,?e,??d,?h,??f,R,m,e,??d,e,??d,?h,??f") - (match_operand:DF 1 "move_source_operand" " e,h,d,f,e,h,d,f,R,R,m,m,h,f,e,d,GO,GO,GO,GO,nF,nF,GO,GO"))] - "!TARGET_DOUBLE - && (register_operand (operands[0], DFmode) - || reg_or_0_operand (operands[1], DFmode))" - "* return output_move_double (operands, insn);" - [(set_attr "length" "8,8,8,8,4,4,8,8,4,4,8,8,8,8,8,8,4,8,8,8,16,16,8,8") - (set_attr "type" "multi,multi,multi,multi,gstore,fstore,gstore,fstore,gload,fload,gload,fload,movfg,movfg,movgf,movgf,gstore,gstore,multi,multi,multi,multi,movgf,movgf")]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "dbl_memory_two_insn_operand" ""))] - "reload_completed" - [(const_int 0)] - "frv_split_double_load (operands[0], operands[1]);") - -(define_split - [(set (match_operand:DF 0 "odd_reg_operand" "") - (match_operand:DF 1 "memory_operand" ""))] - "reload_completed" - [(const_int 0)] - "frv_split_double_load (operands[0], operands[1]);") - -(define_split - [(set (match_operand:DF 0 "dbl_memory_two_insn_operand" "") - (match_operand:DF 1 "reg_or_0_operand" ""))] - "reload_completed" - [(const_int 0)] - "frv_split_double_store (operands[0], operands[1]);") - -(define_split - [(set (match_operand:DF 0 "memory_operand" "") - (match_operand:DF 1 "odd_reg_operand" ""))] - "reload_completed" - [(const_int 0)] - "frv_split_double_store (operands[0], operands[1]);") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" ""))] - "reload_completed - && (odd_reg_operand (operands[0], DFmode) - || odd_reg_operand (operands[1], DFmode) - || (integer_register_operand (operands[0], DFmode) - && integer_register_operand (operands[1], DFmode)) - || (!TARGET_DOUBLE - && fpr_operand (operands[0], DFmode) - && fpr_operand (operands[1], DFmode)))" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - " -{ - rtx op0 = operands[0]; - rtx op0_low = gen_lowpart (SImode, op0); - rtx op0_high = gen_highpart (SImode, op0); - rtx op1 = operands[1]; - rtx op1_low = gen_lowpart (SImode, op1); - rtx op1_high = gen_highpart (SImode, op1); - - /* 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 (op0_high) == REGNO (op1_low)) - { - operands[2] = op0_low; - operands[3] = op0_high; - operands[4] = op1_low; - operands[5] = op1_high; - } - else - { - operands[2] = op0_high; - operands[3] = op0_low; - operands[4] = op1_high; - operands[5] = op1_low; - } -}") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "const_int_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 1))] - " -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - - operands[2] = gen_highpart (SImode, op0); - operands[3] = gen_lowpart (SImode, op0); - operands[4] = GEN_INT ((INTVAL (op1) < 0) ? -1 : 0); -}") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "const_double_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - " -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - REAL_VALUE_TYPE rv; - long l[2]; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, op1); - REAL_VALUE_TO_TARGET_DOUBLE (rv, l); - - operands[2] = gen_highpart (SImode, op0); - operands[3] = gen_lowpart (SImode, op0); - operands[4] = GEN_INT (l[0]); - operands[5] = GEN_INT (l[1]); -}") - -;; String/block move insn. -;; Argument 0 is the destination -;; Argument 1 is the source -;; Argument 2 is the length -;; Argument 3 is the alignment - -(define_expand "movstrsi" - [(parallel [(set (match_operand:BLK 0 "" "") - (match_operand:BLK 1 "" "")) - (use (match_operand:SI 2 "" "")) - (use (match_operand:SI 3 "" ""))])] - "" - " -{ - if (frv_expand_block_move (operands)) - DONE; - else - FAIL; -}") - -;; String/block clear insn. -;; Argument 0 is the destination -;; Argument 1 is the length -;; Argument 2 is the alignment - -(define_expand "clrstrsi" - [(parallel [(set (match_operand:BLK 0 "" "") - (const_int 0)) - (use (match_operand:SI 1 "" "")) - (use (match_operand:SI 2 "" ""))])] - "" - " -{ - if (frv_expand_block_clear (operands)) - DONE; - else - FAIL; -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Reload CC registers -;; :: -;; :::::::::::::::::::: - -;; Use as a define_expand so that cse/gcse/combine can't accidentally -;; create movcc insns. - -(define_expand "movcc" - [(parallel [(set (match_operand:CC 0 "move_destination_operand" "") - (match_operand:CC 1 "move_source_operand" "")) - (clobber (match_dup 2))])] - "" - " -{ - if (! reload_in_progress && ! reload_completed) - FAIL; - - operands[2] = gen_rtx_REG (CC_CCRmode, ICR_TEMP); -}") - -(define_insn "*internal_movcc" - [(set (match_operand:CC 0 "move_destination_operand" "=t,d,d,m,d") - (match_operand:CC 1 "move_source_operand" "d,d,m,d,t")) - (clobber (match_scratch:CC_CCR 2 "=X,X,X,X,&v"))] - "reload_in_progress || reload_completed" - "@ - cmpi %1, #0, %0 - mov %1, %0 - ld%I1%U1 %M1, %0 - st%I0%U0 %1, %M0 - #" - [(set_attr "length" "4,4,4,4,20") - (set_attr "type" "int,int,gload,gstore,multi")]) - -;; To move an ICC value to a GPR for a signed comparison, we create a value -;; that when compared to 0, sets the N and Z flags appropriately (we don't care -;; about the V and C flags, since these comparisons are signed). - -(define_split - [(set (match_operand:CC 0 "integer_register_operand" "") - (match_operand:CC 1 "icc_operand" "")) - (clobber (match_operand:CC_CCR 2 "icr_operand" ""))] - "reload_in_progress || reload_completed" - [(match_dup 3)] - " -{ - rtx dest = simplify_gen_subreg (SImode, operands[0], CCmode, 0); - rtx icc = operands[1]; - rtx icr = operands[2]; - - start_sequence (); - - emit_insn (gen_rtx_SET (VOIDmode, icr, - gen_rtx_LT (CC_CCRmode, icc, const0_rtx))); - - emit_insn (gen_movsi (dest, const1_rtx)); - - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (CC_CCRmode, icr, const0_rtx), - gen_rtx_SET (VOIDmode, dest, - gen_rtx_NEG (SImode, dest)))); - - emit_insn (gen_rtx_SET (VOIDmode, icr, - gen_rtx_EQ (CC_CCRmode, icc, const0_rtx))); - - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (CC_CCRmode, icr, const0_rtx), - gen_rtx_SET (VOIDmode, dest, const0_rtx))); - - operands[3] = get_insns (); - end_sequence (); -}") - -(define_expand "reload_incc" - [(parallel [(set (match_operand:CC 2 "integer_register_operand" "=&d") - (match_operand:CC 1 "memory_operand" "m")) - (clobber (match_scratch:CC_CCR 3 ""))]) - (parallel [(set (match_operand:CC 0 "icc_operand" "=t") - (match_dup 2)) - (clobber (match_scratch:CC_CCR 4 ""))])] - "" - "") - -(define_expand "reload_outcc" - [(parallel [(set (match_operand:CC 2 "integer_register_operand" "=&d") - (match_operand:CC 1 "icc_operand" "t")) - (clobber (match_dup 3))]) - (parallel [(set (match_operand:CC 0 "memory_operand" "=m") - (match_dup 2)) - (clobber (match_scratch:CC_CCR 4 ""))])] - "" - "operands[3] = gen_rtx_REG (CC_CCRmode, ICR_TEMP);") - -;; Reload CC_UNSmode for unsigned integer comparisons -;; Use define_expand so that cse/gcse/combine can't create movcc_uns insns - -(define_expand "movcc_uns" - [(parallel [(set (match_operand:CC_UNS 0 "move_destination_operand" "") - (match_operand:CC_UNS 1 "move_source_operand" "")) - (clobber (match_dup 2))])] - "" - " -{ - if (! reload_in_progress && ! reload_completed) - FAIL; - operands[2] = gen_rtx_REG (CC_CCRmode, ICR_TEMP); -}") - -(define_insn "*internal_movcc_uns" - [(set (match_operand:CC_UNS 0 "move_destination_operand" "=t,d,d,m,d") - (match_operand:CC_UNS 1 "move_source_operand" "d,d,m,d,t")) - (clobber (match_scratch:CC_CCR 2 "=X,X,X,X,&v"))] - "reload_in_progress || reload_completed" - "@ - cmpi %1, #1, %0 - mov %1, %0 - ld%I1%U1 %M1, %0 - st%I0%U0 %1, %M0 - #" - [(set_attr "length" "4,4,4,4,20") - (set_attr "type" "int,int,gload,gstore,multi")]) - -;; To move an ICC value to a GPR for an unsigned comparison, we create a value -;; that when compared to 1, sets the Z, V, and C flags appropriately (we don't -;; care about the N flag, since these comparisons are unsigned). - -(define_split - [(set (match_operand:CC_UNS 0 "integer_register_operand" "") - (match_operand:CC_UNS 1 "icc_operand" "")) - (clobber (match_operand:CC_CCR 2 "icr_operand" ""))] - "reload_in_progress || reload_completed" - [(match_dup 3)] - " -{ - rtx dest = simplify_gen_subreg (SImode, operands[0], CC_UNSmode, 0); - rtx icc = operands[1]; - rtx icr = operands[2]; - - start_sequence (); - - emit_insn (gen_rtx_SET (VOIDmode, icr, - gen_rtx_GTU (CC_CCRmode, icc, const0_rtx))); - - emit_insn (gen_movsi (dest, const1_rtx)); - - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (CC_CCRmode, icr, const0_rtx), - gen_addsi3 (dest, dest, dest))); - - emit_insn (gen_rtx_SET (VOIDmode, icr, - gen_rtx_LTU (CC_CCRmode, icc, const0_rtx))); - - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (CC_CCRmode, icr, const0_rtx), - gen_rtx_SET (VOIDmode, dest, const0_rtx))); - - operands[3] = get_insns (); - end_sequence (); -}") - -(define_expand "reload_incc_uns" - [(parallel [(set (match_operand:CC_UNS 2 "integer_register_operand" "=&d") - (match_operand:CC_UNS 1 "memory_operand" "m")) - (clobber (match_scratch:CC_CCR 3 ""))]) - (parallel [(set (match_operand:CC_UNS 0 "icc_operand" "=t") - (match_dup 2)) - (clobber (match_scratch:CC_CCR 4 ""))])] - "" - "") - -(define_expand "reload_outcc_uns" - [(parallel [(set (match_operand:CC_UNS 2 "integer_register_operand" "=&d") - (match_operand:CC_UNS 1 "icc_operand" "t")) - (clobber (match_dup 3))]) - (parallel [(set (match_operand:CC_UNS 0 "memory_operand" "=m") - (match_dup 2)) - (clobber (match_scratch:CC_CCR 4 ""))])] - "" - "operands[3] = gen_rtx_REG (CC_CCRmode, ICR_TEMP);") - -;; Reload CC_FPmode for floating point comparisons -;; We use a define_expand here so that cse/gcse/combine can't accidentally -;; create movcc insns. If this was a named define_insn, we would not be able -;; to make it conditional on reload. - -(define_expand "movcc_fp" - [(set (match_operand:CC_FP 0 "move_destination_operand" "") - (match_operand:CC_FP 1 "move_source_operand" ""))] - "TARGET_HAS_FPRS" - " -{ - if (! reload_in_progress && ! reload_completed) - FAIL; -}") - -(define_insn "*movcc_fp_internal" - [(set (match_operand:CC_FP 0 "move_destination_operand" "=d,d,d,m") - (match_operand:CC_FP 1 "move_source_operand" "u,d,m,d"))] - "TARGET_HAS_FPRS && (reload_in_progress || reload_completed)" - "@ - # - mov %1, %0 - ld%I1%U1 %M1, %0 - st%I0%U0 %1, %M0" - [(set_attr "length" "12,4,4,4") - (set_attr "type" "multi,int,gload,gstore")]) - - -(define_expand "reload_incc_fp" - [(match_operand:CC_FP 0 "fcc_operand" "=u") - (match_operand:CC_FP 1 "memory_operand" "m") - (match_operand:TI 2 "integer_register_operand" "=&d")] - "TARGET_HAS_FPRS" - " -{ - rtx cc_op2 = simplify_gen_subreg (CC_FPmode, operands[2], TImode, 0); - rtx int_op2 = simplify_gen_subreg (SImode, operands[2], TImode, 0); - rtx temp1 = simplify_gen_subreg (SImode, operands[2], TImode, 4); - rtx temp2 = simplify_gen_subreg (SImode, operands[2], TImode, 8); - int shift = CC_SHIFT_RIGHT (REGNO (operands[0])); - HOST_WIDE_INT mask; - - emit_insn (gen_movcc_fp (cc_op2, operands[1])); - if (shift) - emit_insn (gen_ashlsi3 (int_op2, int_op2, GEN_INT (shift))); - - mask = ~ ((HOST_WIDE_INT)CC_MASK << shift); - emit_insn (gen_movsi (temp1, GEN_INT (mask))); - emit_insn (gen_update_fcc (operands[0], int_op2, temp1, temp2)); - DONE; -}") - -(define_expand "reload_outcc_fp" - [(set (match_operand:CC_FP 2 "integer_register_operand" "=&d") - (match_operand:CC_FP 1 "fcc_operand" "u")) - (set (match_operand:CC_FP 0 "memory_operand" "=m") - (match_dup 2))] - "TARGET_HAS_FPRS" - "") - -;; Convert a FCC value to gpr -(define_insn "read_fcc" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (unspec:SI [(match_operand:CC_FP 1 "fcc_operand" "u")] - UNSPEC_CC_TO_GPR))] - "TARGET_HAS_FPRS" - "movsg ccr, %0" - [(set_attr "type" "spr") - (set_attr "length" "4")]) - -(define_split - [(set (match_operand:CC_FP 0 "integer_register_operand" "") - (match_operand:CC_FP 1 "fcc_operand" ""))] - "reload_completed && TARGET_HAS_FPRS" - [(match_dup 2)] - " -{ - rtx int_op0 = simplify_gen_subreg (SImode, operands[0], CC_FPmode, 0); - int shift = CC_SHIFT_RIGHT (REGNO (operands[1])); - - start_sequence (); - - emit_insn (gen_read_fcc (int_op0, operands[1])); - if (shift) - emit_insn (gen_lshrsi3 (int_op0, int_op0, GEN_INT (shift))); - - emit_insn (gen_andsi3 (int_op0, int_op0, GEN_INT (CC_MASK))); - - operands[2] = get_insns (); - end_sequence (); -}") - -;; Move a gpr value to FCC. -;; Operand0 = FCC -;; Operand1 = reloaded value shifted appropriately -;; Operand2 = mask to eliminate current register -;; Operand3 = temporary to load/store ccr -(define_insn "update_fcc" - [(set (match_operand:CC_FP 0 "fcc_operand" "=u") - (unspec:CC_FP [(match_operand:SI 1 "integer_register_operand" "d") - (match_operand:SI 2 "integer_register_operand" "d")] - UNSPEC_GPR_TO_CC)) - (clobber (match_operand:SI 3 "integer_register_operand" "=&d"))] - "TARGET_HAS_FPRS" - "movsg ccr, %3\;and %2, %3, %3\;or %1, %3, %3\;movgs %3, ccr" - [(set_attr "type" "multi") - (set_attr "length" "16")]) - -;; Reload CC_CCRmode for conditional execution registers -(define_insn "movcc_ccr" - [(set (match_operand:CC_CCR 0 "move_destination_operand" "=d,d,d,m,v,?w,C,d") - (match_operand:CC_CCR 1 "move_source_operand" "C,d,m,d,n,n,C,L"))] - "" - "@ - # - mov %1, %0 - ld%I1%U1 %M1, %0 - st%I0%U0 %1, %M0 - # - # - orcr %1, %1, %0 - setlos #%1, %0" - [(set_attr "length" "8,4,4,4,8,12,4,4") - (set_attr "type" "multi,int,gload,gstore,multi,multi,ccr,int")]) - -(define_expand "reload_incc_ccr" - [(match_operand:CC_CCR 0 "cr_operand" "=C") - (match_operand:CC_CCR 1 "memory_operand" "m") - (match_operand:CC_CCR 2 "integer_register_operand" "=&d")] - "" - " -{ - rtx icc = gen_rtx_REG (CCmode, ICC_TEMP); - rtx int_op2 = simplify_gen_subreg (SImode, operands[2], CC_CCRmode, 0); - rtx icr = (ICR_P (REGNO (operands[0])) - ? operands[0] : gen_rtx_REG (CC_CCRmode, ICR_TEMP)); - - emit_insn (gen_movcc_ccr (operands[2], operands[1])); - emit_insn (gen_cmpsi_cc (icc, int_op2, const0_rtx)); - emit_insn (gen_movcc_ccr (icr, gen_rtx_NE (CC_CCRmode, icc, const0_rtx))); - - if (! ICR_P (REGNO (operands[0]))) - emit_insn (gen_movcc_ccr (operands[0], icr)); - - DONE; -}") - -(define_expand "reload_outcc_ccr" - [(set (match_operand:CC_CCR 2 "integer_register_operand" "=&d") - (match_operand:CC_CCR 1 "cr_operand" "C")) - (set (match_operand:CC_CCR 0 "memory_operand" "=m") - (match_dup 2))] - "" - "") - -(define_split - [(set (match_operand:CC_CCR 0 "integer_register_operand" "") - (match_operand:CC_CCR 1 "cr_operand" ""))] - "reload_completed" - [(match_dup 2)] - " -{ - rtx int_op0 = simplify_gen_subreg (SImode, operands[0], CC_CCRmode, 0); - - start_sequence (); - emit_move_insn (operands[0], const1_rtx); - emit_insn (gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_EQ (CC_CCRmode, - operands[1], - const0_rtx), - gen_rtx_SET (VOIDmode, int_op0, - const0_rtx))); - - operands[2] = get_insns (); - end_sequence (); -}") - -(define_split - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (match_operand:CC_CCR 1 "const_int_operand" ""))] - "reload_completed" - [(match_dup 2)] - " -{ - rtx icc = gen_rtx_REG (CCmode, ICC_TEMP); - rtx r0 = gen_rtx_REG (SImode, GPR_FIRST); - rtx icr = (ICR_P (REGNO (operands[0])) - ? operands[0] : gen_rtx_REG (CC_CCRmode, ICR_TEMP)); - - start_sequence (); - - emit_insn (gen_cmpsi_cc (icc, r0, const0_rtx)); - - emit_insn (gen_movcc_ccr (icr, - gen_rtx_fmt_ee (((INTVAL (operands[1]) == 0) - ? EQ : NE), CC_CCRmode, - r0, const0_rtx))); - - if (! ICR_P (REGNO (operands[0]))) - emit_insn (gen_movcc_ccr (operands[0], icr)); - - operands[2] = get_insns (); - end_sequence (); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Conversions -;; :: -;; :::::::::::::::::::: - -;; Signed conversions from a smaller integer to a larger integer -;; -;; These operations are optional. If they are not -;; present GCC will synthesise them for itself -;; Even though frv does not provide these instructions, we define them -;; to allow load + sign extend to be collapsed together -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "integer_register_operand" "=d,d") - (sign_extend:HI (match_operand:QI 1 "gpr_or_memory_operand" "d,m")))] - "" - "@ - # - ldsb%I1%U1 %M1,%0" - [(set_attr "length" "8,4") - (set_attr "type" "multi,gload")]) - -(define_split - [(set (match_operand:HI 0 "integer_register_operand" "") - (sign_extend:HI (match_operand:QI 1 "integer_register_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_INT (24); - - operands[2] = gen_ashlsi3 (op0, op1, shift); - operands[3] = gen_ashrsi3 (op0, op0, shift); -}") - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d") - (sign_extend:SI (match_operand:QI 1 "gpr_or_memory_operand" "d,m")))] - "" - "@ - # - ldsb%I1%U1 %M1,%0" - [(set_attr "length" "8,4") - (set_attr "type" "multi,gload")]) - -(define_split - [(set (match_operand:SI 0 "integer_register_operand" "") - (sign_extend:SI (match_operand:QI 1 "integer_register_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_INT (24); - - operands[2] = gen_ashlsi3 (op0, op1, shift); - operands[3] = gen_ashrsi3 (op0, op0, shift); -}") - -;;(define_insn "extendqidi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (sign_extend:DI (match_operand:QI 1 "general_operand" "g")))] -;; "" -;; "extendqihi2 %0,%1" -;; [(set_attr "length" "4")]) - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d") - (sign_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "d,m")))] - "" - "@ - # - ldsh%I1%U1 %M1,%0" - [(set_attr "length" "8,4") - (set_attr "type" "multi,gload")]) - -(define_split - [(set (match_operand:SI 0 "integer_register_operand" "") - (sign_extend:SI (match_operand:HI 1 "integer_register_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_INT (16); - - operands[2] = gen_ashlsi3 (op0, op1, shift); - operands[3] = gen_ashrsi3 (op0, op0, shift); -}") - -;;(define_insn "extendhidi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (sign_extend:DI (match_operand:HI 1 "general_operand" "g")))] -;; "" -;; "extendhihi2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "extendsidi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (sign_extend:DI (match_operand:SI 1 "general_operand" "g")))] -;; "" -;; "extendsidi2 %0,%1" -;; [(set_attr "length" "4")]) - -;; Unsigned conversions from a smaller integer to a larger integer -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d") - (zero_extend:HI - (match_operand:QI 1 "gpr_or_memory_operand" "d,L,m")))] - "" - "@ - andi %1,#0xff,%0 - setlos %1,%0 - ldub%I1%U1 %M1,%0" - [(set_attr "length" "4") - (set_attr "type" "int,int,gload")]) - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d") - (zero_extend:SI - (match_operand:QI 1 "gpr_or_memory_operand" "d,L,m")))] - "" - "@ - andi %1,#0xff,%0 - setlos %1,%0 - ldub%I1%U1 %M1,%0" - [(set_attr "length" "4") - (set_attr "type" "int,int,gload")]) - -;;(define_insn "zero_extendqidi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (zero_extend:DI (match_operand:QI 1 "general_operand" "g")))] -;; "" -;; "zero_extendqihi2 %0,%1" -;; [(set_attr "length" "4")]) - -;; Do not set the type for the sethi to "sethi", since the scheduler will think -;; the sethi takes 0 cycles as part of allowing sethi/setlo to be in the same -;; VLIW instruction. -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d") - (zero_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "0,m")))] - "" - "@ - sethi #hi(#0),%0 - lduh%I1%U1 %M1,%0" - [(set_attr "length" "4") - (set_attr "type" "int,gload")]) - -;;(define_insn "zero_extendhidi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (zero_extend:DI (match_operand:HI 1 "general_operand" "g")))] -;; "" -;; "zero_extendhihi2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "zero_extendsidi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (zero_extend:DI (match_operand:SI 1 "general_operand" "g")))] -;; "" -;; "zero_extendsidi2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;;; Convert between floating point types of different sizes. -;; -;;(define_insn "extendsfdf2" -;; [(set (match_operand:DF 0 "register_operand" "=r") -;; (float_extend:DF (match_operand:SF 1 "register_operand" "r")))] -;; "" -;; "extendsfdf2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "truncdfsf2" -;; [(set (match_operand:SF 0 "register_operand" "=r") -;; (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))] -;; "" -;; "truncdfsf2 %0,%1" -;; [(set_attr "length" "4")]) - -;;;; Convert between signed integer types and floating point. -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (float:SF (match_operand:SI 1 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fitos %1,%0" - [(set_attr "length" "4") - (set_attr "type" "fsconv")]) - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "fpr_operand" "=h") - (float:DF (match_operand:SI 1 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "fitod %1,%0" - [(set_attr "length" "4") - (set_attr "type" "fdconv")]) - -;;(define_insn "floatdisf2" -;; [(set (match_operand:SF 0 "register_operand" "=r") -;; (float:SF (match_operand:DI 1 "register_operand" "r")))] -;; "" -;; "floatdisf2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "floatdidf2" -;; [(set (match_operand:DF 0 "register_operand" "=r") -;; (float:DF (match_operand:DI 1 "register_operand" "r")))] -;; "" -;; "floatdidf2 %0,%1" -;; [(set_attr "length" "4")]) - -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (fix:SI (match_operand:SF 1 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fstoi %1,%0" - [(set_attr "length" "4") - (set_attr "type" "fsconv")]) - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (fix:SI (match_operand:DF 1 "fpr_operand" "h")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "fdtoi %1,%0" - [(set_attr "length" "4") - (set_attr "type" "fdconv")]) - -;;(define_insn "fix_truncsfdi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (fix:DI (match_operand:SF 1 "register_operand" "r")))] -;; "" -;; "fix_truncsfdi2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "fix_truncdfdi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (fix:DI (match_operand:DF 1 "register_operand" "r")))] -;; "" -;; "fix_truncdfdi2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;;; Convert between unsigned integer types and floating point. -;; -;;(define_insn "floatunssisf2" -;; [(set (match_operand:SF 0 "register_operand" "=r") -;; (unsigned_float:SF (match_operand:SI 1 "register_operand" "r")))] -;; "" -;; "floatunssisf2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "floatunssidf2" -;; [(set (match_operand:DF 0 "register_operand" "=r") -;; (unsigned_float:DF (match_operand:SI 1 "register_operand" "r")))] -;; "" -;; "floatunssidf2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "floatunsdisf2" -;; [(set (match_operand:SF 0 "register_operand" "=r") -;; (unsigned_float:SF (match_operand:DI 1 "register_operand" "r")))] -;; "" -;; "floatunsdisf2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "floatunsdidf2" -;; [(set (match_operand:DF 0 "register_operand" "=r") -;; (unsigned_float:DF (match_operand:DI 1 "register_operand" "r")))] -;; "" -;; "floatunsdidf2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "fixuns_truncsfsi2" -;; [(set (match_operand:SI 0 "register_operand" "=r") -;; (unsigned_fix:SI (match_operand:SF 1 "register_operand" "r")))] -;; "" -;; "fixuns_truncsfsi2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "fixuns_truncdfsi2" -;; [(set (match_operand:SI 0 "register_operand" "=r") -;; (unsigned_fix:SI (match_operand:DF 1 "register_operand" "r")))] -;; "" -;; "fixuns_truncdfsi2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "fixuns_truncsfdi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (unsigned_fix:DI (match_operand:SF 1 "register_operand" "r")))] -;; "" -;; "fixuns_truncsfdi2 %0,%1" -;; [(set_attr "length" "4")]) -;; -;;(define_insn "fixuns_truncdfdi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (unsigned_fix:DI (match_operand:DF 1 "register_operand" "r")))] -;; "" -;; "fixuns_truncdfdi2 %0,%1" -;; [(set_attr "length" "4")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 32 bit Integer arithmetic -;; :: -;; :::::::::::::::::::: - -;; Addition -(define_insn "addsi3" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (plus:SI (match_operand:SI 1 "integer_register_operand" "%d") - (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))] - "" - "add%I2 %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -;; Subtraction. No need to worry about constants, since the compiler -;; canonicalizes them into addsi3's. We prevent SUBREG's here to work around a -;; combine bug, that combines the 32x32->upper 32 bit multiply that uses a -;; SUBREG with a minus that shows up in modulus by constants. -(define_insn "subsi3" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (minus:SI (match_operand:SI 1 "gpr_no_subreg_operand" "d") - (match_operand:SI 2 "gpr_no_subreg_operand" "d")))] - "" - "sub %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -;; Signed multiplication producing 64 bit results from 32 bit inputs -;; Note, frv doesn't have a 32x32->32 bit multiply, but the compiler -;; will do the 32x32->64 bit multiply and use the bottom word. -(define_expand "mulsidi3" - [(set (match_operand:DI 0 "integer_register_operand" "") - (mult:DI (sign_extend:DI (match_operand:SI 1 "integer_register_operand" "")) - (sign_extend:DI (match_operand:SI 2 "gpr_or_int12_operand" ""))))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - emit_insn (gen_mulsidi3_const (operands[0], operands[1], operands[2])); - DONE; - } -}") - -(define_insn "*mulsidi3_reg" - [(set (match_operand:DI 0 "even_gpr_operand" "=e") - (mult:DI (sign_extend:DI (match_operand:SI 1 "integer_register_operand" "%d")) - (sign_extend:DI (match_operand:SI 2 "integer_register_operand" "d"))))] - "" - "smul %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "mulsidi3_const" - [(set (match_operand:DI 0 "even_gpr_operand" "=e") - (mult:DI (sign_extend:DI (match_operand:SI 1 "integer_register_operand" "d")) - (match_operand:SI 2 "int12_operand" "NOP")))] - "" - "smuli %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -;; Unsigned multiplication producing 64 bit results from 32 bit inputs -(define_expand "umulsidi3" - [(set (match_operand:DI 0 "even_gpr_operand" "") - (mult:DI (zero_extend:DI (match_operand:SI 1 "integer_register_operand" "")) - (zero_extend:DI (match_operand:SI 2 "gpr_or_int12_operand" ""))))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - emit_insn (gen_umulsidi3_const (operands[0], operands[1], operands[2])); - DONE; - } -}") - -(define_insn "*mulsidi3_reg" - [(set (match_operand:DI 0 "even_gpr_operand" "=e") - (mult:DI (zero_extend:DI (match_operand:SI 1 "integer_register_operand" "%d")) - (zero_extend:DI (match_operand:SI 2 "integer_register_operand" "d"))))] - "" - "umul %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "umulsidi3_const" - [(set (match_operand:DI 0 "even_gpr_operand" "=e") - (mult:DI (zero_extend:DI (match_operand:SI 1 "integer_register_operand" "d")) - (match_operand:SI 2 "int12_operand" "NOP")))] - "" - "umuli %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -;; Signed Division -(define_insn "divsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (div:SI (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] - "" - "sdiv%I2 %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "div")]) - -;; Unsigned Division -(define_insn "udivsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (udiv:SI (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] - "" - "udiv%I2 %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "div")]) - -;; Negation -(define_insn "negsi2" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (neg:SI (match_operand:SI 1 "integer_register_operand" "d")))] - "" - "sub %.,%1,%0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -;; Find first one bit -;; (define_insn "ffssi2" -;; [(set (match_operand:SI 0 "register_operand" "=r") -;; (ffs:SI (match_operand:SI 1 "register_operand" "r")))] -;; "" -;; "ffssi2 %0,%1" -;; [(set_attr "length" "4")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 64 bit Integer arithmetic -;; :: -;; :::::::::::::::::::: - -;; Addition -(define_expand "adddi3" - [(parallel [(set (match_operand:DI 0 "integer_register_operand" "") - (plus:DI (match_operand:DI 1 "integer_register_operand" "") - (match_operand:DI 2 "gpr_or_int10_operand" ""))) - (clobber (match_scratch:CC 3 ""))])] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == -2048 - && !no_new_pseudos) - operands[2] = force_reg (DImode, operands[2]); -}") - -(define_insn_and_split "*adddi3_internal" - [(set (match_operand:DI 0 "integer_register_operand" "=&e,e,e,&e,e,&e,e") - (plus:DI (match_operand:DI 1 "integer_register_operand" "%e,0,e,e,0,e,0") - (match_operand:DI 2 "gpr_or_int10_operand" "e,e,0,N,N,OP,OP"))) - (clobber (match_scratch:CC 3 "=t,t,t,t,t,t,t"))] - "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -2048" - "#" - "reload_completed" - [(match_dup 4) - (match_dup 5)] - " -{ - rtx op0_high = gen_highpart (SImode, operands[0]); - rtx op1_high = gen_highpart (SImode, operands[1]); - rtx op0_low = gen_lowpart (SImode, operands[0]); - rtx op1_low = gen_lowpart (SImode, operands[1]); - rtx op2 = operands[2]; - rtx op3 = operands[3]; - - if (GET_CODE (op2) != CONST_INT) - { - rtx op2_high = gen_highpart (SImode, operands[2]); - rtx op2_low = gen_lowpart (SImode, operands[2]); - operands[4] = gen_adddi3_lower (op0_low, op1_low, op2_low, op3); - operands[5] = gen_adddi3_upper (op0_high, op1_high, op2_high, op3); - } - else if (INTVAL (op2) >= 0) - { - operands[4] = gen_adddi3_lower (op0_low, op1_low, op2, op3); - operands[5] = gen_adddi3_upper (op0_high, op1_high, const0_rtx, op3); - } - else - { - operands[4] = gen_subdi3_lower (op0_low, op1_low, - GEN_INT (- INTVAL (op2)), op3); - operands[5] = gen_subdi3_upper (op0_high, op1_high, const0_rtx, op3); - } -}" - [(set_attr "length" "8") - (set_attr "type" "multi")]) - -;; Subtraction No need to worry about constants, since the compiler -;; canonicalizes them into adddi3's. -(define_expand "subdi3" - [(parallel [(set (match_operand:DI 0 "integer_register_operand" "") - (minus:DI (match_operand:DI 1 "integer_register_operand" "") - (match_operand:DI 2 "integer_register_operand" ""))) - (clobber (match_dup 3))])] - "" - " -{ - operands[3] = gen_reg_rtx (CCmode); -}") - -(define_insn_and_split "*subdi3_internal" - [(set (match_operand:DI 0 "integer_register_operand" "=&e,e,e") - (minus:DI (match_operand:DI 1 "integer_register_operand" "e,0,e") - (match_operand:DI 2 "integer_register_operand" "e,e,0"))) - (clobber (match_operand:CC 3 "icc_operand" "=t,t,t"))] - "" - "#" - "reload_completed" - [(match_dup 4) - (match_dup 5)] - " -{ - rtx op0_high = gen_highpart (SImode, operands[0]); - rtx op1_high = gen_highpart (SImode, operands[1]); - rtx op2_high = gen_highpart (SImode, operands[2]); - rtx op0_low = gen_lowpart (SImode, operands[0]); - rtx op1_low = gen_lowpart (SImode, operands[1]); - rtx op2_low = gen_lowpart (SImode, operands[2]); - rtx op3 = operands[3]; - - operands[4] = gen_subdi3_lower (op0_low, op1_low, op2_low, op3); - operands[5] = gen_subdi3_upper (op0_high, op1_high, op2_high, op3); -}" - [(set_attr "length" "8") - (set_attr "type" "multi")]) - -;; Patterns for addsi3/subdi3 after spliting -(define_insn "adddi3_lower" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (plus:SI (match_operand:SI 1 "integer_register_operand" "d") - (match_operand:SI 2 "gpr_or_int10_operand" "dOP"))) - (set (match_operand:CC 3 "icc_operand" "=t") - (compare:CC (plus:SI (match_dup 1) - (match_dup 2)) - (const_int 0)))] - "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) >= 0" - "add%I2cc %1,%2,%0,%3" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_insn "adddi3_upper" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d") - (plus:SI (match_operand:SI 1 "integer_register_operand" "d,d") - (plus:SI (match_operand:SI 2 "reg_or_0_operand" "d,O") - (match_operand:CC 3 "icc_operand" "t,t"))))] - "" - "@ - addx %1,%2,%0,%3 - addx %1,%.,%0,%3" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_insn "subdi3_lower" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (minus:SI (match_operand:SI 1 "integer_register_operand" "d") - (match_operand:SI 2 "gpr_or_int10_operand" "dOP"))) - (set (match_operand:CC 3 "icc_operand" "=t") - (compare:CC (plus:SI (match_dup 1) - (match_dup 2)) - (const_int 0)))] - "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) >= 0" - "sub%I2cc %1,%2,%0,%3" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_insn "subdi3_upper" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d") - (minus:SI (match_operand:SI 1 "integer_register_operand" "d,d") - (minus:SI (match_operand:SI 2 "reg_or_0_operand" "d,O") - (match_operand:CC 3 "icc_operand" "t,t"))))] - "" - "@ - subx %1,%2,%0,%3 - subx %1,%.,%0,%3" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -;; Multiplication (same size) -;; (define_insn "muldi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (mult:DI (match_operand:DI 1 "register_operand" "%r") -;; (match_operand:DI 2 "nonmemory_operand" "ri")))] -;; "" -;; "muldi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Signed Division -;; (define_insn "divdi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (div:DI (match_operand:DI 1 "register_operand" "r") -;; (match_operand:DI 2 "nonmemory_operand" "ri")))] -;; "" -;; "divdi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Undsgned Division -;; (define_insn "udivdi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (udiv:DI (match_operand:DI 1 "register_operand" "r") -;; (match_operand:DI 2 "nonmemory_operand" "ri")))] -;; "" -;; "udivdi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Negation -;; (define_insn "negdi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (neg:DI (match_operand:DI 1 "register_operand" "r")))] -;; "" -;; "negdi2 %0,%1" -;; [(set_attr "length" "4")]) - -;; Find first one bit -;; (define_insn "ffsdi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (ffs:DI (match_operand:DI 1 "register_operand" "r")))] -;; "" -;; "ffsdi2 %0,%1" -;; [(set_attr "length" "4")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 32 bit floating point arithmetic -;; :: -;; :::::::::::::::::::: - -;; Addition -(define_insn "addsf3" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (plus:SF (match_operand:SF 1 "fpr_operand" "%f") - (match_operand:SF 2 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fadds %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fsadd")]) - -;; Subtraction -(define_insn "subsf3" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (minus:SF (match_operand:SF 1 "fpr_operand" "f") - (match_operand:SF 2 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fsubs %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fsadd")]) - -;; Multiplication -(define_insn "mulsf3" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (mult:SF (match_operand:SF 1 "fpr_operand" "%f") - (match_operand:SF 2 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fmuls %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fsmul")]) - -;; Multiplication with addition/subtraction -(define_insn "*muladdsf4" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (plus:SF (mult:SF (match_operand:SF 1 "fpr_operand" "%f") - (match_operand:SF 2 "fpr_operand" "f")) - (match_operand:SF 3 "fpr_operand" "0")))] - "TARGET_HARD_FLOAT && TARGET_MULADD" - "fmadds %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fmas")]) - -(define_insn "*mulsubsf4" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (minus:SF (mult:SF (match_operand:SF 1 "fpr_operand" "%f") - (match_operand:SF 2 "fpr_operand" "f")) - (match_operand:SF 3 "fpr_operand" "0")))] - "TARGET_HARD_FLOAT && TARGET_MULADD" - "fmsubs %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fmas")]) - -;; Division -(define_insn "divsf3" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (div:SF (match_operand:SF 1 "fpr_operand" "f") - (match_operand:SF 2 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fdivs %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fsdiv")]) - -;; Negation -(define_insn "negsf2" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (neg:SF (match_operand:SF 1 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fnegs %1,%0" - [(set_attr "length" "4") - (set_attr "type" "fsconv")]) - -;; Absolute value -(define_insn "abssf2" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (abs:SF (match_operand:SF 1 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fabss %1,%0" - [(set_attr "length" "4") - (set_attr "type" "fsconv")]) - -;; Square root -(define_insn "sqrtsf2" - [(set (match_operand:SF 0 "fpr_operand" "=f") - (sqrt:SF (match_operand:SF 1 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fsqrts %1,%0" - [(set_attr "length" "4") - (set_attr "type" "sqrt_single")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 64 bit floating point arithmetic -;; :: -;; :::::::::::::::::::: - -;; Addition -(define_insn "adddf3" - [(set (match_operand:DF 0 "even_fpr_operand" "=h") - (plus:DF (match_operand:DF 1 "fpr_operand" "%h") - (match_operand:DF 2 "fpr_operand" "h")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "faddd %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fdadd")]) - -;; Subtraction -(define_insn "subdf3" - [(set (match_operand:DF 0 "even_fpr_operand" "=h") - (minus:DF (match_operand:DF 1 "fpr_operand" "h") - (match_operand:DF 2 "fpr_operand" "h")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "fsubd %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fdadd")]) - -;; Multiplication -(define_insn "muldf3" - [(set (match_operand:DF 0 "even_fpr_operand" "=h") - (mult:DF (match_operand:DF 1 "fpr_operand" "%h") - (match_operand:DF 2 "fpr_operand" "h")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "fmuld %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fdmul")]) - -;; Multiplication with addition/subtraction -(define_insn "*muladddf4" - [(set (match_operand:DF 0 "fpr_operand" "=f") - (plus:DF (mult:DF (match_operand:DF 1 "fpr_operand" "%f") - (match_operand:DF 2 "fpr_operand" "f")) - (match_operand:DF 3 "fpr_operand" "0")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE && TARGET_MULADD" - "fmaddd %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fmas")]) - -(define_insn "*mulsubdf4" - [(set (match_operand:DF 0 "fpr_operand" "=f") - (minus:DF (mult:DF (match_operand:DF 1 "fpr_operand" "%f") - (match_operand:DF 2 "fpr_operand" "f")) - (match_operand:DF 3 "fpr_operand" "0")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE && TARGET_MULADD" - "fmsubd %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fmas")]) - -;; Division -(define_insn "divdf3" - [(set (match_operand:DF 0 "even_fpr_operand" "=h") - (div:DF (match_operand:DF 1 "fpr_operand" "h") - (match_operand:DF 2 "fpr_operand" "h")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "fdivd %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fddiv")]) - -;; Negation -(define_insn "negdf2" - [(set (match_operand:DF 0 "even_fpr_operand" "=h") - (neg:DF (match_operand:DF 1 "fpr_operand" "h")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "fnegd %1,%0" - [(set_attr "length" "4") - (set_attr "type" "fdconv")]) - -;; Absolute value -(define_insn "absdf2" - [(set (match_operand:DF 0 "even_fpr_operand" "=h") - (abs:DF (match_operand:DF 1 "fpr_operand" "h")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "fabsd %1,%0" - [(set_attr "length" "4") - (set_attr "type" "fdconv")]) - -;; Square root -(define_insn "sqrtdf2" - [(set (match_operand:DF 0 "even_fpr_operand" "=h") - (sqrt:DF (match_operand:DF 1 "fpr_operand" "h")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "fsqrtd %1,%0" - [(set_attr "length" "4") - (set_attr "type" "sqrt_double")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 32 bit Integer Shifts and Rotates -;; :: -;; :::::::::::::::::::: - -;; Arithmetic Shift Left -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d") - (ashift:SI (match_operand:SI 1 "integer_register_operand" "d,d") - (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] - "" - "sll%I2 %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -;; Arithmetic Shift Right -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d") - (ashiftrt:SI (match_operand:SI 1 "integer_register_operand" "d,d") - (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] - "" - "sra%I2 %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -;; Logical Shift Right -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d") - (lshiftrt:SI (match_operand:SI 1 "integer_register_operand" "d,d") - (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))] - "" - "srl%I2 %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -;; Rotate Left -;; (define_insn "rotlsi3" -;; [(set (match_operand:SI 0 "register_operand" "=r") -;; (rotate:SI (match_operand:SI 1 "register_operand" "r") -;; (match_operand:SI 2 "nonmemory_operand" "ri")))] -;; "" -;; "rotlsi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Rotate Right -;; (define_insn "rotrsi3" -;; [(set (match_operand:SI 0 "register_operand" "=r") -;; (rotatert:SI (match_operand:SI 1 "register_operand" "r") -;; (match_operand:SI 2 "nonmemory_operand" "ri")))] -;; "" -;; "rotrsi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 64 bit Integer Shifts and Rotates -;; :: -;; :::::::::::::::::::: - -;; Arithmetic Shift Left -;; (define_insn "ashldi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (ashift:DI (match_operand:DI 1 "register_operand" "r") -;; (match_operand:SI 2 "nonmemory_operand" "ri")))] -;; "" -;; "ashldi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Arithmetic Shift Right -;; (define_insn "ashrdi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") -;; (match_operand:SI 2 "nonmemory_operand" "ri")))] -;; "" -;; "ashrdi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Logical Shift Right -;; (define_insn "lshrdi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") -;; (match_operand:SI 2 "nonmemory_operand" "ri")))] -;; "" -;; "lshrdi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Rotate Left -;; (define_insn "rotldi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (rotate:DI (match_operand:DI 1 "register_operand" "r") -;; (match_operand:SI 2 "nonmemory_operand" "ri")))] -;; "" -;; "rotldi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Rotate Right -;; (define_insn "rotrdi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (rotatert:DI (match_operand:DI 1 "register_operand" "r") -;; (match_operand:SI 2 "nonmemory_operand" "ri")))] -;; "" -;; "rotrdi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 32 Bit Integer Logical operations -;; :: -;; :::::::::::::::::::: - -;; Logical AND, 32 bit integers -(define_insn "andsi3_media" - [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f") - (and:SI (match_operand:SI 1 "gpr_or_fpr_operand" "%d,f") - (match_operand:SI 2 "gpr_fpr_or_int12_operand" "dNOP,f")))] - "TARGET_MEDIA" - "@ - and%I2 %1, %2, %0 - mand %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "int,mlogic")]) - -(define_insn "andsi3_nomedia" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (and:SI (match_operand:SI 1 "integer_register_operand" "%d") - (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))] - "!TARGET_MEDIA" - "and%I2 %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_expand "andsi3" - [(set (match_operand:SI 0 "gpr_or_fpr_operand" "") - (and:SI (match_operand:SI 1 "gpr_or_fpr_operand" "") - (match_operand:SI 2 "gpr_fpr_or_int12_operand" "")))] - "" - "") - -;; Inclusive OR, 32 bit integers -(define_insn "iorsi3_media" - [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f") - (ior:SI (match_operand:SI 1 "gpr_or_fpr_operand" "%d,f") - (match_operand:SI 2 "gpr_fpr_or_int12_operand" "dNOP,f")))] - "TARGET_MEDIA" - "@ - or%I2 %1, %2, %0 - mor %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "int,mlogic")]) - -(define_insn "iorsi3_nomedia" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (ior:SI (match_operand:SI 1 "integer_register_operand" "%d") - (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))] - "!TARGET_MEDIA" - "or%I2 %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_expand "iorsi3" - [(set (match_operand:SI 0 "gpr_or_fpr_operand" "") - (ior:SI (match_operand:SI 1 "gpr_or_fpr_operand" "") - (match_operand:SI 2 "gpr_fpr_or_int12_operand" "")))] - "" - "") - -;; Exclusive OR, 32 bit integers -(define_insn "xorsi3_media" - [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f") - (xor:SI (match_operand:SI 1 "gpr_or_fpr_operand" "%d,f") - (match_operand:SI 2 "gpr_fpr_or_int12_operand" "dNOP,f")))] - "TARGET_MEDIA" - "@ - xor%I2 %1, %2, %0 - mxor %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "int,mlogic")]) - -(define_insn "xorsi3_nomedia" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (xor:SI (match_operand:SI 1 "integer_register_operand" "%d") - (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))] - "!TARGET_MEDIA" - "xor%I2 %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_expand "xorsi3" - [(set (match_operand:SI 0 "gpr_or_fpr_operand" "") - (xor:SI (match_operand:SI 1 "gpr_or_fpr_operand" "") - (match_operand:SI 2 "gpr_fpr_or_int12_operand" "")))] - "" - "") - -;; One's complement, 32 bit integers -(define_insn "one_cmplsi2_media" - [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f") - (not:SI (match_operand:SI 1 "gpr_or_fpr_operand" "d,f")))] - "TARGET_MEDIA" - "@ - not %1, %0 - mnot %1, %0" - [(set_attr "length" "4") - (set_attr "type" "int,mlogic")]) - -(define_insn "one_cmplsi2_nomedia" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (not:SI (match_operand:SI 1 "integer_register_operand" "d")))] - "!TARGET_MEDIA" - "not %1,%0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_expand "one_cmplsi2" - [(set (match_operand:SI 0 "gpr_or_fpr_operand" "") - (not:SI (match_operand:SI 1 "gpr_or_fpr_operand" "")))] - "" - "") - - -;; :::::::::::::::::::: -;; :: -;; :: 64 Bit Integer Logical operations -;; :: -;; :::::::::::::::::::: - -;; Logical AND, 64 bit integers -;; (define_insn "anddi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (and:DI (match_operand:DI 1 "register_operand" "%r") -;; (match_operand:DI 2 "nonmemory_operand" "ri")))] -;; "" -;; "anddi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Includive OR, 64 bit integers -;; (define_insn "iordi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (ior:DI (match_operand:DI 1 "register_operand" "%r") -;; (match_operand:DI 2 "nonmemory_operand" "ri")))] -;; "" -;; "iordi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; Excludive OR, 64 bit integers -;; (define_insn "xordi3" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (xor:DI (match_operand:DI 1 "register_operand" "%r") -;; (match_operand:DI 2 "nonmemory_operand" "ri")))] -;; "" -;; "xordi3 %0,%1,%2" -;; [(set_attr "length" "4")]) - -;; One's complement, 64 bit integers -;; (define_insn "one_cmpldi2" -;; [(set (match_operand:DI 0 "register_operand" "=r") -;; (not:DI (match_operand:DI 1 "register_operand" "r")))] -;; "" -;; "notdi3 %0,%1" -;; [(set_attr "length" "4")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Combination of integer operation with comparison -;; :: -;; :::::::::::::::::::: - -(define_insn "*combo_intop_compare1" - [(set (match_operand:CC 0 "icc_operand" "=t") - (compare:CC (match_operator:SI 1 "intop_compare_operator" - [(match_operand:SI 2 "integer_register_operand" "d") - (match_operand:SI 3 "gpr_or_int10_operand" "dJ")]) - (const_int 0)))] - "" - "%O1%I3cc %2, %3, %., %0" - [(set_attr "type" "int") - (set_attr "length" "4")]) - -(define_insn "*combo_intop_compare2" - [(set (match_operand:CC_UNS 0 "icc_operand" "=t") - (compare:CC_UNS (match_operator:SI 1 "intop_compare_operator" - [(match_operand:SI 2 "integer_register_operand" "d") - (match_operand:SI 3 "gpr_or_int10_operand" "dJ")]) - (const_int 0)))] - "" - "%O1%I3cc %2, %3, %., %0" - [(set_attr "type" "int") - (set_attr "length" "4")]) - -(define_insn "*combo_intop_compare3" - [(set (match_operand:CC 0 "icc_operand" "=t") - (compare:CC (match_operator:SI 1 "intop_compare_operator" - [(match_operand:SI 2 "integer_register_operand" "d") - (match_operand:SI 3 "gpr_or_int10_operand" "dJ")]) - (const_int 0))) - (set (match_operand:SI 4 "integer_register_operand" "=d") - (match_operator:SI 5 "intop_compare_operator" - [(match_dup 2) - (match_dup 3)]))] - "GET_CODE (operands[1]) == GET_CODE (operands[5])" - "%O1%I3cc %2, %3, %4, %0" - [(set_attr "type" "int") - (set_attr "length" "4")]) - -(define_insn "*combo_intop_compare4" - [(set (match_operand:CC_UNS 0 "icc_operand" "=t") - (compare:CC_UNS (match_operator:SI 1 "intop_compare_operator" - [(match_operand:SI 2 "integer_register_operand" "d") - (match_operand:SI 3 "gpr_or_int10_operand" "dJ")]) - (const_int 0))) - (set (match_operand:SI 4 "integer_register_operand" "=d") - (match_operator:SI 5 "intop_compare_operator" - [(match_dup 2) - (match_dup 3)]))] - "GET_CODE (operands[1]) == GET_CODE (operands[5])" - "%O1%I3cc %2, %3, %4, %0" - [(set_attr "type" "int") - (set_attr "length" "4")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 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 "integer_register_operand" "") - (match_operand:SI 1 "gpr_or_int10_operand" "")))] - "" - " -{ - frv_compare_op0 = operands[0]; - frv_compare_op1 = operands[1]; - DONE; -}") - -;(define_expand "cmpdi" -; [(set (cc0) -; (compare (match_operand:DI 0 "register_operand" "") -; (match_operand:DI 1 "nonmemory_operand" "")))] -; "" -; " -;{ -; frv_compare_op0 = operands[0]; -; frv_compare_op1 = operands[1]; -; DONE; -;}") - -(define_expand "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "fpr_operand" "") - (match_operand:SF 1 "fpr_operand" "")))] - "TARGET_HARD_FLOAT" - " -{ - frv_compare_op0 = operands[0]; - frv_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "fpr_operand" "") - (match_operand:DF 1 "fpr_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - " -{ - frv_compare_op0 = operands[0]; - frv_compare_op1 = operands[1]; - DONE; -}") - -;; Now, the actual comparisons, generated by the branch and/or scc operations - -(define_insn "cmpsi_cc" - [(set (match_operand:CC 0 "icc_operand" "=t,t") - (compare:CC (match_operand:SI 1 "integer_register_operand" "d,d") - (match_operand:SI 2 "gpr_or_int10_operand" "d,J")))] - "" - "cmp%I2 %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_insn "*cmpsi_cc_uns" - [(set (match_operand:CC_UNS 0 "icc_operand" "=t,t") - (compare:CC_UNS (match_operand:SI 1 "integer_register_operand" "d,d") - (match_operand:SI 2 "gpr_or_int10_operand" "d,J")))] - "" - "cmp%I2 %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_insn "*cmpsf_cc_fp" - [(set (match_operand:CC_FP 0 "fcc_operand" "=u") - (compare:CC_FP (match_operand:SF 1 "fpr_operand" "f") - (match_operand:SF 2 "fpr_operand" "f")))] - "TARGET_HARD_FLOAT" - "fcmps %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fsadd")]) - -(define_insn "*cmpdf_cc_fp" - [(set (match_operand:CC_FP 0 "fcc_operand" "=u") - (compare:CC_FP (match_operand:DF 1 "even_fpr_operand" "h") - (match_operand:DF 2 "even_fpr_operand" "h")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE" - "fcmpd %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "fdadd")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Branches -;; :: -;; :::::::::::::::::::: - -;; Define_expands called by the machine independent part of the compiler -;; to allocate a new comparison register. Each of these named patterns -;; must be present, and they cannot be amalgamated into one pattern. -;; -;; If a fixed condition code register is being used, (as opposed to, say, -;; using cc0), then the expands should look like this: -;; -;; (define_expand "" -;; [(set (reg:CC ) -;; (compare:CC (match_dup 1) -;; (match_dup 2))) -;; (set (pc) -;; (if_then_else (eq:CC (reg:CC ) -;; (const_int 0)) -;; (label_ref (match_operand 0 "" "")) -;; (pc)))] -;; "" -;; "{ -;; operands[1] = frv_compare_op0; -;; operands[2] = frv_compare_op1; -;; }" -;; ) - -(define_expand "beq" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (EQ, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bne" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (NE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "blt" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "ble" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bgt" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bge" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bltu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LTU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bleu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (LEU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bgtu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GTU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "bgeu" - [(use (match_operand 0 "" ""))] - "" - " -{ - if (! frv_emit_cond_branch (GEU, operands[0])) - FAIL; - - DONE; -}") - -;; 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. -;; -;; Note - unlike the define expands above, these patterns can be amalgamated -;; into one pattern for branch-if-true and one for branch-if-false. This does -;; require an operand operator to select the correct branch mnemonic. -;; -;; If a fixed condition code register is being used, (as opposed to, say, -;; using cc0), then the expands could look like this: -;; -;; (define_insn "*branch_true" -;; [(set (pc) -;; (if_then_else (match_operator:CC 0 "comparison_operator" -;; [(reg:CC ) -;; (const_int 0)]) -;; (label_ref (match_operand 1 "" "")) -;; (pc)))] -;; "" -;; "b%B0 %1" -;; [(set_attr "length" "4")] -;; ) -;; -;; In the above example the %B is a directive to frv_print_operand() -;; to decode and print the correct branch mnemonic. - -(define_insn "*branch_signed_true" - [(set (pc) - (if_then_else (match_operator:CC 0 "signed_relational_operator" - [(match_operand 1 "icc_operand" "t") - (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "* -{ - if (get_attr_length (insn) == 4) - return \"b%c0 %1,%#,%l2\"; - else - return \"b%C0 %1,%#,1f\;call %l2\\n1:\"; -}" - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) - (le (minus (match_dup 2) (pc)) (const_int 32764))) - (const_int 4) - (const_int 8))) - (set (attr "far_jump") - (if_then_else - (eq_attr "length" "4") - (const_string "no") - (const_string "yes"))) - (set (attr "type") - (if_then_else - (eq_attr "length" "4") - (const_string "branch") - (const_string "multi")))]) - -(define_insn "*branch_signed_false" - [(set (pc) - (if_then_else (match_operator:CC 0 "signed_relational_operator" - [(match_operand 1 "icc_operand" "t") - (const_int 0)]) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "* -{ - if (get_attr_length (insn) == 4) - return \"b%C0 %1,%#,%l2\"; - else - return \"b%c0 %1,%#,1f\;call %l2\\n1:\"; -}" - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) - (le (minus (match_dup 2) (pc)) (const_int 32764))) - (const_int 4) - (const_int 8))) - (set (attr "far_jump") - (if_then_else - (eq_attr "length" "4") - (const_string "no") - (const_string "yes"))) - (set (attr "type") - (if_then_else - (eq_attr "length" "4") - (const_string "branch") - (const_string "multi")))]) - -(define_insn "*branch_unsigned_true" - [(set (pc) - (if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator" - [(match_operand 1 "icc_operand" "t") - (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "* -{ - if (get_attr_length (insn) == 4) - return \"b%c0 %1,%#,%l2\"; - else - return \"b%C0 %1,%#,1f\;call %l2\\n1:\"; -}" - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) - (le (minus (match_dup 2) (pc)) (const_int 32764))) - (const_int 4) - (const_int 8))) - (set (attr "far_jump") - (if_then_else - (eq_attr "length" "4") - (const_string "no") - (const_string "yes"))) - (set (attr "type") - (if_then_else - (eq_attr "length" "4") - (const_string "branch") - (const_string "multi")))]) - -(define_insn "*branch_unsigned_false" - [(set (pc) - (if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator" - [(match_operand 1 "icc_operand" "t") - (const_int 0)]) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "* -{ - if (get_attr_length (insn) == 4) - return \"b%C0 %1,%#,%l2\"; - else - return \"b%c0 %1,%#,1f\;call %l2\\n1:\"; -}" - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) - (le (minus (match_dup 2) (pc)) (const_int 32764))) - (const_int 4) - (const_int 8))) - (set (attr "far_jump") - (if_then_else - (eq_attr "length" "4") - (const_string "no") - (const_string "yes"))) - (set (attr "type") - (if_then_else - (eq_attr "length" "4") - (const_string "branch") - (const_string "multi")))]) - -(define_insn "*branch_fp_true" - [(set (pc) - (if_then_else (match_operator:CC_FP 0 "float_relational_operator" - [(match_operand 1 "fcc_operand" "u") - (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "* -{ - if (get_attr_length (insn) == 4) - return \"fb%f0 %1,%#,%l2\"; - else - return \"fb%F0 %1,%#,1f\;call %l2\\n1:\"; -}" - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) - (le (minus (match_dup 2) (pc)) (const_int 32764))) - (const_int 4) - (const_int 8))) - (set (attr "far_jump") - (if_then_else - (eq_attr "length" "4") - (const_string "no") - (const_string "yes"))) - (set (attr "type") - (if_then_else - (eq_attr "length" "4") - (const_string "branch") - (const_string "multi")))]) - -(define_insn "*branch_fp_false" - [(set (pc) - (if_then_else (match_operator:CC_FP 0 "float_relational_operator" - [(match_operand 1 "fcc_operand" "u") - (const_int 0)]) - (pc) - (label_ref (match_operand 2 "" ""))))] - "" - "* -{ - if (get_attr_length (insn) == 4) - return \"fb%F0 %1,%#,%l2\"; - else - return \"fb%f0 %1,%#,1f\;call %l2\\n1:\"; -}" - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) - (le (minus (match_dup 2) (pc)) (const_int 32764))) - (const_int 4) - (const_int 8))) - (set (attr "far_jump") - (if_then_else - (eq_attr "length" "4") - (const_string "no") - (const_string "yes"))) - (set (attr "type") - (if_then_else - (eq_attr "length" "4") - (const_string "branch") - (const_string "multi")))]) - - -;; :::::::::::::::::::: -;; :: -;; :: Set flag operations -;; :: -;; :::::::::::::::::::: - -;; Define_expands called by the machine independent part of the compiler -;; to allocate a new comparison register - -(define_expand "seq" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (EQ, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sne" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (NE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "slt" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sle" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sgt" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GT, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sge" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GE, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sltu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LTU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sleu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (LEU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sgtu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GTU, operands[0])) - FAIL; - - DONE; -}") - -(define_expand "sgeu" - [(match_operand:SI 0 "integer_register_operand" "")] - "TARGET_SCC" - " -{ - if (! frv_emit_scc (GEU, operands[0])) - FAIL; - - DONE; -}") - -(define_insn "*scc_signed" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (match_operator:SI 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t") - (const_int 0)])) - (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))] - "" - "#" - [(set_attr "length" "12") - (set_attr "type" "multi")]) - -(define_insn "*scc_unsigned" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (match_operator:SI 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t") - (const_int 0)])) - (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))] - "" - "#" - [(set_attr "length" "12") - (set_attr "type" "multi")]) - -(define_insn "*scc_float" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (match_operator:SI 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u") - (const_int 0)])) - (clobber (match_operand:CC_CCR 3 "fcr_operand" "=w"))] - "" - "#" - [(set_attr "length" "12") - (set_attr "type" "multi")]) - -;; XXX -- add reload_completed to the splits, because register allocation -;; currently isn't ready to see cond_exec packets. -(define_split - [(set (match_operand:SI 0 "integer_register_operand" "") - (match_operator:SI 1 "relational_operator" - [(match_operand 2 "cc_operand" "") - (const_int 0)])) - (clobber (match_operand 3 "cr_operand" ""))] - "reload_completed" - [(match_dup 4)] - "operands[4] = frv_split_scc (operands[0], operands[1], operands[2], - operands[3], (HOST_WIDE_INT) 1);") - -(define_insn "*scc_neg1_signed" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (neg:SI (match_operator:SI 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t") - (const_int 0)]))) - (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))] - "" - "#" - [(set_attr "length" "12") - (set_attr "type" "multi")]) - -(define_insn "*scc_neg1_unsigned" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (neg:SI (match_operator:SI 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t") - (const_int 0)]))) - (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))] - "" - "#" - [(set_attr "length" "12") - (set_attr "type" "multi")]) - -(define_insn "*scc_neg1_float" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (neg:SI (match_operator:SI 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u") - (const_int 0)]))) - (clobber (match_operand:CC_CCR 3 "fcr_operand" "=w"))] - "" - "#" - [(set_attr "length" "12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:SI 0 "integer_register_operand" "") - (neg:SI (match_operator:SI 1 "relational_operator" - [(match_operand 2 "cc_operand" "") - (const_int 0)]))) - (clobber (match_operand 3 "cr_operand" ""))] - "reload_completed" - [(match_dup 4)] - "operands[4] = frv_split_scc (operands[0], operands[1], operands[2], - operands[3], (HOST_WIDE_INT) -1);") - - -;; :::::::::::::::::::: -;; :: -;; :: Conditionally executed instructions -;; :: -;; :::::::::::::::::::: - -;; Convert ICC/FCC comparison into CCR bits so we can do conditional execution -(define_insn "*ck_signed" - [(set (match_operand:CC_CCR 0 "icr_operand" "=v") - (match_operator:CC_CCR 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t") - (const_int 0)]))] - "" - "ck%c1 %2, %0" - [(set_attr "length" "4") - (set_attr "type" "ccr")]) - -(define_insn "*ck_unsigned" - [(set (match_operand:CC_CCR 0 "icr_operand" "=v") - (match_operator:CC_CCR 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t") - (const_int 0)]))] - "" - "ck%c1 %2, %0" - [(set_attr "length" "4") - (set_attr "type" "ccr")]) - -(define_insn "*fck_float" - [(set (match_operand:CC_CCR 0 "fcr_operand" "=w") - (match_operator:CC_CCR 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u") - (const_int 0)]))] - "TARGET_HAS_FPRS" - "fck%c1 %2, %0" - [(set_attr "length" "4") - (set_attr "type" "ccr")]) - -;; Conditionally convert ICC/FCC comparison into CCR bits to provide && and || -;; tests in conditional execution -(define_insn "cond_exec_ck" - [(set (match_operand:CC_CCR 0 "cr_operand" "=v,w") - (if_then_else:CC_CCR (match_operator 1 "ccr_eqne_operator" - [(match_operand 2 "cr_operand" "C,C") - (const_int 0)]) - (match_operator 3 "relational_operator" - [(match_operand 4 "cc_operand" "t,u") - (const_int 0)]) - (const_int 0)))] - "" - "@ - cck%c3 %4, %0, %2, %e1 - cfck%f3 %4, %0, %2, %e1" - [(set_attr "length" "4") - (set_attr "type" "ccr")]) - -;; Conditionally set a register to either 0 or another register -(define_insn "*cond_exec_movqi" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C,C,C,C,C,C") - (const_int 0)]) - (set (match_operand:QI 2 "condexec_dest_operand" "=d,d,U,?f,?f,?d") - (match_operand:QI 3 "condexec_source_operand" "dO,U,dO,f,d,f")))] - "register_operand(operands[2], QImode) || reg_or_0_operand (operands[3], QImode)" - "* return output_condmove_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "int,gload,gstore,fsconv,movgf,movfg")]) - -(define_insn "*cond_exec_movhi" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C,C,C,C,C,C") - (const_int 0)]) - (set (match_operand:HI 2 "condexec_dest_operand" "=d,d,U,?f,?f,?d") - (match_operand:HI 3 "condexec_source_operand" "dO,U,dO,f,d,f")))] - "register_operand(operands[2], HImode) || reg_or_0_operand (operands[3], HImode)" - "* return output_condmove_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "int,gload,gstore,fsconv,movgf,movfg")]) - -(define_insn "*cond_exec_movsi" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C,C,C,C,C,C,C,C") - (const_int 0)]) - (set (match_operand:SI 2 "condexec_dest_operand" "=d,d,U,?f,?f,?d,?f,?m") - (match_operand:SI 3 "condexec_source_operand" "dO,U,dO,f,d,f,m,f")))] - "register_operand(operands[2], SImode) || reg_or_0_operand (operands[3], SImode)" - "* return output_condmove_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "int,gload,gstore,fsconv,movgf,movfg,fload,fstore")]) - - -(define_insn "*cond_exec_movsf_has_fprs" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C,C,C,C,C,C,C,C,C,C") - (const_int 0)]) - (set (match_operand:SF 2 "condexec_dest_operand" "=f,?d,?d,?f,f,f,?d,U,?U,U") - (match_operand:SF 3 "condexec_source_operand" "f,d,f,d,G,U,U,f,d,G")))] - "TARGET_HAS_FPRS" - "* return output_condmove_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "fsconv,int,movgf,movfg,movgf,fload,gload,fstore,gstore,gstore")]) - -(define_insn "*cond_exec_movsf_no_fprs" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C,C,C") - (const_int 0)]) - (set (match_operand:SF 2 "condexec_dest_operand" "=d,d,U") - (match_operand:SF 3 "condexec_source_operand" "d,U,dG")))] - "! TARGET_HAS_FPRS" - "* return output_condmove_single (operands, insn);" - [(set_attr "length" "4") - (set_attr "type" "int,gload,gstore")]) - -(define_insn "*cond_exec_si_binary1" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "integer_register_operand" "=d") - (match_operator:SI 3 "condexec_si_binary_operator" - [(match_operand:SI 4 "integer_register_operand" "d") - (match_operand:SI 5 "integer_register_operand" "d")])))] - "" - "* -{ - switch (GET_CODE (operands[3])) - { - case PLUS: return \"cadd %4, %z5, %2, %1, %e0\"; - case MINUS: return \"csub %4, %z5, %2, %1, %e0\"; - case AND: return \"cand %4, %z5, %2, %1, %e0\"; - case IOR: return \"cor %4, %z5, %2, %1, %e0\"; - case XOR: return \"cxor %4, %z5, %2, %1, %e0\"; - case ASHIFT: return \"csll %4, %z5, %2, %1, %e0\"; - case ASHIFTRT: return \"csra %4, %z5, %2, %1, %e0\"; - case LSHIFTRT: return \"csrl %4, %z5, %2, %1, %e0\"; - default: abort (); - } -}" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_insn "*cond_exec_si_binary2" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "fpr_operand" "=f") - (match_operator:SI 3 "condexec_si_media_operator" - [(match_operand:SI 4 "fpr_operand" "f") - (match_operand:SI 5 "fpr_operand" "f")])))] - "TARGET_MEDIA" - "* -{ - switch (GET_CODE (operands[3])) - { - case AND: return \"cmand %4, %5, %2, %1, %e0\"; - case IOR: return \"cmor %4, %5, %2, %1, %e0\"; - case XOR: return \"cmxor %4, %5, %2, %1, %e0\"; - default: abort (); - } -}" - [(set_attr "length" "4") - (set_attr "type" "mlogic")]) - -;; Note, flow does not (currently) know how to handle an operation that uses -;; only part of the hard registers allocated for a multiregister value, such as -;; DImode in this case if the user is only interested in the lower 32-bits. So -;; we emit a USE of the entire register after the csmul instruction so it won't -;; get confused. See frv_ifcvt_modify_insn for more details. - -(define_insn "*cond_exec_si_smul" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:DI 2 "even_gpr_operand" "=e") - (mult:DI (sign_extend:DI (match_operand:SI 3 "integer_register_operand" "%d")) - (sign_extend:DI (match_operand:SI 4 "integer_register_operand" "d")))))] - "" - "csmul %3, %4, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*cond_exec_si_divide" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "integer_register_operand" "=d") - (match_operator:SI 3 "condexec_si_divide_operator" - [(match_operand:SI 4 "integer_register_operand" "d") - (match_operand:SI 5 "integer_register_operand" "d")])))] - "" - "* -{ - switch (GET_CODE (operands[3])) - { - case DIV: return \"csdiv %4, %z5, %2, %1, %e0\"; - case UDIV: return \"cudiv %4, %z5, %2, %1, %e0\"; - default: abort (); - } -}" - [(set_attr "length" "4") - (set_attr "type" "div")]) - -(define_insn "*cond_exec_si_unary1" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "integer_register_operand" "=d") - (match_operator:SI 3 "condexec_si_unary_operator" - [(match_operand:SI 4 "integer_register_operand" "d")])))] - "" - "* -{ - switch (GET_CODE (operands[3])) - { - case NOT: return \"cnot %4, %2, %1, %e0\"; - case NEG: return \"csub %., %4, %2, %1, %e0\"; - default: abort (); - } -}" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_insn "*cond_exec_si_unary2" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "fpr_operand" "=f") - (not:SI (match_operand:SI 3 "fpr_operand" "f"))))] - "TARGET_MEDIA" - "cmnot %3, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "mlogic")]) - -(define_insn "*cond_exec_cmpsi_cc" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:CC 2 "icc_operand" "=t") - (compare:CC (match_operand:SI 3 "integer_register_operand" "d") - (match_operand:SI 4 "reg_or_0_operand" "dO"))))] - "reload_completed - && REGNO (operands[1]) == REGNO (operands[2]) - ICC_FIRST + ICR_FIRST" - "ccmp %3, %z4, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_insn "*cond_exec_cmpsi_cc_uns" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:CC_UNS 2 "icc_operand" "=t") - (compare:CC_UNS (match_operand:SI 3 "integer_register_operand" "d") - (match_operand:SI 4 "reg_or_0_operand" "dO"))))] - "reload_completed - && REGNO (operands[1]) == REGNO (operands[2]) - ICC_FIRST + ICR_FIRST" - "ccmp %3, %z4, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -(define_insn "*cond_exec_sf_conv" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SF 2 "fpr_operand" "=f") - (match_operator:SF 3 "condexec_sf_conv_operator" - [(match_operand:SF 4 "fpr_operand" "f")])))] - "TARGET_HARD_FLOAT" - "* -{ - switch (GET_CODE (operands[3])) - { - case ABS: return \"cfabss %4, %2, %1, %e0\"; - case NEG: return \"cfnegs %4, %2, %1, %e0\"; - default: abort (); - } -}" - [(set_attr "length" "4") - (set_attr "type" "fsconv")]) - -(define_insn "*cond_exec_sf_add" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SF 2 "fpr_operand" "=f") - (match_operator:SF 3 "condexec_sf_add_operator" - [(match_operand:SF 4 "fpr_operand" "f") - (match_operand:SF 5 "fpr_operand" "f")])))] - "TARGET_HARD_FLOAT" - "* -{ - switch (GET_CODE (operands[3])) - { - case PLUS: return \"cfadds %4, %5, %2, %1, %e0\"; - case MINUS: return \"cfsubs %4, %5, %2, %1, %e0\"; - default: abort (); - } -}" - [(set_attr "length" "4") - (set_attr "type" "fsadd")]) - -(define_insn "*cond_exec_sf_mul" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SF 2 "fpr_operand" "=f") - (mult:SF (match_operand:SF 3 "fpr_operand" "f") - (match_operand:SF 4 "fpr_operand" "f"))))] - "TARGET_HARD_FLOAT" - "cfmuls %3, %4, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "fsmul")]) - -(define_insn "*cond_exec_sf_div" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SF 2 "fpr_operand" "=f") - (div:SF (match_operand:SF 3 "fpr_operand" "f") - (match_operand:SF 4 "fpr_operand" "f"))))] - "TARGET_HARD_FLOAT" - "cfdivs %3, %4, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "fsdiv")]) - -(define_insn "*cond_exec_sf_sqrt" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SF 2 "fpr_operand" "=f") - (sqrt:SF (match_operand:SF 3 "fpr_operand" "f"))))] - "TARGET_HARD_FLOAT" - "cfsqrts %3, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "fsdiv")]) - -(define_insn "*cond_exec_cmpsi_cc_fp" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:CC_FP 2 "fcc_operand" "=u") - (compare:CC_FP (match_operand:SF 3 "fpr_operand" "f") - (match_operand:SF 4 "fpr_operand" "f"))))] - "reload_completed && TARGET_HARD_FLOAT - && REGNO (operands[1]) == REGNO (operands[2]) - FCC_FIRST + FCR_FIRST" - "cfcmps %3, %4, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "fsconv")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Logical operations on CR registers -;; :: -;; :::::::::::::::::::: - -;; We use UNSPEC to encode andcr/iorcr/etc. rather than the normal RTL -;; operations, since the RTL operations only have an idea of TRUE and FALSE, -;; while the CRs have TRUE, FALSE, and UNDEFINED. - -(define_expand "andcr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_operand:CC_CCR 2 "cr_operand" "") - (const_int 0)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_expand "orcr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_operand:CC_CCR 2 "cr_operand" "") - (const_int 1)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_expand "xorcr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_operand:CC_CCR 2 "cr_operand" "") - (const_int 2)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_expand "nandcr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_operand:CC_CCR 2 "cr_operand" "") - (const_int 3)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_expand "norcr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_operand:CC_CCR 2 "cr_operand" "") - (const_int 4)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_expand "andncr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_operand:CC_CCR 2 "cr_operand" "") - (const_int 5)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_expand "orncr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_operand:CC_CCR 2 "cr_operand" "") - (const_int 6)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_expand "nandncr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_operand:CC_CCR 2 "cr_operand" "") - (const_int 7)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_expand "norncr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_operand:CC_CCR 2 "cr_operand" "") - (const_int 8)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_expand "notcr" - [(set (match_operand:CC_CCR 0 "cr_operand" "") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "") - (match_dup 1) - (const_int 9)] UNSPEC_CR_LOGIC))] - "" - "") - -(define_insn "*logical_cr" - [(set (match_operand:CC_CCR 0 "cr_operand" "=C") - (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "C") - (match_operand:CC_CCR 2 "cr_operand" "C") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_CR_LOGIC))] - "" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case 0: return \"andcr %1, %2, %0\"; - case 1: return \"orcr %1, %2, %0\"; - case 2: return \"xorcr %1, %2, %0\"; - case 3: return \"nandcr %1, %2, %0\"; - case 4: return \"norcr %1, %2, %0\"; - case 5: return \"andncr %1, %2, %0\"; - case 6: return \"orncr %1, %2, %0\"; - case 7: return \"nandncr %1, %2, %0\"; - case 8: return \"norncr %1, %2, %0\"; - case 9: return \"notcr %1, %0\"; - } - - fatal_insn (\"logical_cr\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "ccr")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Conditional move instructions -;; :: -;; :::::::::::::::::::: - - -;; - conditional moves based on floating-point comparisons require -;; TARGET_HARD_FLOAT, because an FPU is required to do the comparison. - -;; - conditional moves between FPRs based on integer comparisons -;; require TARGET_HAS_FPRS. - -(define_expand "movqicc" - [(set (match_operand:QI 0 "integer_register_operand" "") - (if_then_else:QI (match_operand 1 "" "") - (match_operand:QI 2 "gpr_or_int_operand" "") - (match_operand:QI 3 "gpr_or_int_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movqicc_internal1_signed" - [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d") - (if_then_else:QI (match_operator:CC 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t,t,t") - (const_int 0)]) - (match_operand:QI 3 "reg_or_0_operand" "0,dO,dO") - (match_operand:QI 4 "reg_or_0_operand" "dO,0,dO"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movqicc_internal1_unsigned" - [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d") - (if_then_else:QI (match_operator:CC_UNS 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t,t,t") - (const_int 0)]) - (match_operand:QI 3 "reg_or_0_operand" "0,dO,dO") - (match_operand:QI 4 "reg_or_0_operand" "dO,0,dO"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movqicc_internal1_float" - [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d") - (if_then_else:QI (match_operator:CC_FP 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u,u,u") - (const_int 0)]) - (match_operand:QI 3 "reg_or_0_operand" "0,dO,dO") - (match_operand:QI 4 "reg_or_0_operand" "dO,0,dO"))) - (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] - "TARGET_HARD_FLOAT" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movqicc_internal2_signed" - [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d,d,d") - (if_then_else:QI (match_operator:CC 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t,t,t,t,t") - (const_int 0)]) - (match_operand:QI 3 "const_int_operand" "O,O,L,n,n") - (match_operand:QI 4 "const_int_operand" "L,n,O,O,n"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))] - "(INTVAL (operands[3]) == 0 - || INTVAL (operands[4]) == 0 - || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047) - && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" - "#" - [(set_attr "length" "8,12,8,12,12") - (set_attr "type" "multi")]) - -(define_insn "*movqicc_internal2_unsigned" - [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d,d,d") - (if_then_else:QI (match_operator:CC_UNS 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t,t,t,t,t") - (const_int 0)]) - (match_operand:QI 3 "const_int_operand" "O,O,L,n,n") - (match_operand:QI 4 "const_int_operand" "L,n,O,O,n"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))] - "(INTVAL (operands[3]) == 0 - || INTVAL (operands[4]) == 0 - || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047) - && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" - "#" - [(set_attr "length" "8,12,8,12,12") - (set_attr "type" "multi")]) - -(define_insn "*movqicc_internal2_float" - [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d,d,d") - (if_then_else:QI (match_operator:CC_FP 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u") - (const_int 0)]) - (match_operand:QI 3 "const_int_operand" "O,O,L,n,n") - (match_operand:QI 4 "const_int_operand" "L,n,O,O,n"))) - (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w"))] - "TARGET_HARD_FLOAT - && (INTVAL (operands[3]) == 0 - || INTVAL (operands[4]) == 0 - || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047) - && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" - "#" - [(set_attr "length" "8,12,8,12,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:QI 0 "integer_register_operand" "") - (if_then_else:QI (match_operator 1 "relational_operator" - [(match_operand 2 "cc_operand" "") - (const_int 0)]) - (match_operand:QI 3 "gpr_or_int_operand" "") - (match_operand:QI 4 "gpr_or_int_operand" ""))) - (clobber (match_operand:CC_CCR 5 "cr_operand" ""))] - "reload_completed" - [(match_dup 6)] - "operands[6] = frv_split_cond_move (operands);") - -(define_expand "movhicc" - [(set (match_operand:HI 0 "integer_register_operand" "") - (if_then_else:HI (match_operand 1 "" "") - (match_operand:HI 2 "gpr_or_int_operand" "") - (match_operand:HI 3 "gpr_or_int_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movhicc_internal1_signed" - [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d") - (if_then_else:HI (match_operator:CC 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t,t,t") - (const_int 0)]) - (match_operand:HI 3 "reg_or_0_operand" "0,dO,dO") - (match_operand:HI 4 "reg_or_0_operand" "dO,0,dO"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movhicc_internal1_unsigned" - [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d") - (if_then_else:HI (match_operator:CC_UNS 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t,t,t") - (const_int 0)]) - (match_operand:HI 3 "reg_or_0_operand" "0,dO,dO") - (match_operand:HI 4 "reg_or_0_operand" "dO,0,dO"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movhicc_internal1_float" - [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d") - (if_then_else:HI (match_operator:CC_FP 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u,u,u") - (const_int 0)]) - (match_operand:HI 3 "reg_or_0_operand" "0,dO,dO") - (match_operand:HI 4 "reg_or_0_operand" "dO,0,dO"))) - (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] - "TARGET_HARD_FLOAT" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movhicc_internal2_signed" - [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d,d,d") - (if_then_else:HI (match_operator:CC 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t,t,t,t,t") - (const_int 0)]) - (match_operand:HI 3 "const_int_operand" "O,O,L,n,n") - (match_operand:HI 4 "const_int_operand" "L,n,O,O,n"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))] - "(INTVAL (operands[3]) == 0 - || INTVAL (operands[4]) == 0 - || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047) - && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" - "#" - [(set_attr "length" "8,12,8,12,12") - (set_attr "type" "multi")]) - -(define_insn "*movhicc_internal2_unsigned" - [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d,d,d") - (if_then_else:HI (match_operator:CC_UNS 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t,t,t,t,t") - (const_int 0)]) - (match_operand:HI 3 "const_int_operand" "O,O,L,n,n") - (match_operand:HI 4 "const_int_operand" "L,n,O,O,n"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))] - "(INTVAL (operands[3]) == 0 - || INTVAL (operands[4]) == 0 - || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047) - && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" - "#" - [(set_attr "length" "8,12,8,12,12") - (set_attr "type" "multi")]) - -(define_insn "*movhicc_internal2_float" - [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d,d,d") - (if_then_else:HI (match_operator:CC_FP 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u") - (const_int 0)]) - (match_operand:HI 3 "const_int_operand" "O,O,L,n,n") - (match_operand:HI 4 "const_int_operand" "L,n,O,O,n"))) - (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w"))] - "TARGET_HARD_FLOAT - && (INTVAL (operands[3]) == 0 - || INTVAL (operands[4]) == 0 - || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047) - && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" - "#" - [(set_attr "length" "8,12,8,12,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HI 0 "integer_register_operand" "") - (if_then_else:HI (match_operator 1 "relational_operator" - [(match_operand 2 "cc_operand" "") - (const_int 0)]) - (match_operand:HI 3 "gpr_or_int_operand" "") - (match_operand:HI 4 "gpr_or_int_operand" ""))) - (clobber (match_operand:CC_CCR 5 "cr_operand" ""))] - "reload_completed" - [(match_dup 6)] - "operands[6] = frv_split_cond_move (operands);") - -(define_expand "movsicc" - [(set (match_operand:SI 0 "integer_register_operand" "") - (if_then_else:SI (match_operand 1 "" "") - (match_operand:SI 2 "gpr_or_int_operand" "") - (match_operand:SI 3 "gpr_or_int_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movsicc_internal1_signed" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d") - (if_then_else:SI (match_operator:CC 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t,t,t") - (const_int 0)]) - (match_operand:SI 3 "reg_or_0_operand" "0,dO,dO") - (match_operand:SI 4 "reg_or_0_operand" "dO,0,dO"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movsicc_internal1_unsigned" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d") - (if_then_else:SI (match_operator:CC_UNS 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t,t,t") - (const_int 0)]) - (match_operand:SI 3 "reg_or_0_operand" "0,dO,dO") - (match_operand:SI 4 "reg_or_0_operand" "dO,0,dO"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movsicc_internal1_float" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d") - (if_then_else:SI (match_operator:CC_FP 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u,u,u") - (const_int 0)]) - (match_operand:SI 3 "reg_or_0_operand" "0,dO,dO") - (match_operand:SI 4 "reg_or_0_operand" "dO,0,dO"))) - (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] - "TARGET_HARD_FLOAT" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movsicc_internal2_signed" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d,d,d") - (if_then_else:SI (match_operator:CC 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t,t,t,t,t") - (const_int 0)]) - (match_operand:SI 3 "const_int_operand" "O,O,L,n,n") - (match_operand:SI 4 "const_int_operand" "L,n,O,O,n"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))] - "(INTVAL (operands[3]) == 0 - || INTVAL (operands[4]) == 0 - || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047) - && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" - "#" - [(set_attr "length" "8,12,8,12,12") - (set_attr "type" "multi")]) - -(define_insn "*movsicc_internal2_unsigned" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d,d,d") - (if_then_else:SI (match_operator:CC_UNS 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t,t,t,t,t") - (const_int 0)]) - (match_operand:SI 3 "const_int_operand" "O,O,L,n,n") - (match_operand:SI 4 "const_int_operand" "L,n,O,O,n"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))] - "(INTVAL (operands[3]) == 0 - || INTVAL (operands[4]) == 0 - || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047) - && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" - "#" - [(set_attr "length" "8,12,8,12,12") - (set_attr "type" "multi")]) - -(define_insn "*movsicc_internal2_float" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d,d,d") - (if_then_else:SI (match_operator:CC_FP 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u") - (const_int 0)]) - (match_operand:SI 3 "const_int_operand" "O,O,L,n,n") - (match_operand:SI 4 "const_int_operand" "L,n,O,O,n"))) - (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w"))] - "TARGET_HARD_FLOAT - && (INTVAL (operands[3]) == 0 - || INTVAL (operands[4]) == 0 - || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047) - && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))" - "#" - [(set_attr "length" "8,12,8,12,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:SI 0 "integer_register_operand" "") - (if_then_else:SI (match_operator 1 "relational_operator" - [(match_operand 2 "cc_operand" "") - (const_int 0)]) - (match_operand:SI 3 "gpr_or_int_operand" "") - (match_operand:SI 4 "gpr_or_int_operand" ""))) - (clobber (match_operand:CC_CCR 5 "cr_operand" ""))] - "reload_completed" - [(match_dup 6)] - "operands[6] = frv_split_cond_move (operands);") - -(define_expand "movsfcc" - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operand 1 "" "") - (match_operand:SF 2 "register_operand" "") - (match_operand:SF 3 "register_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movsfcc_has_fprs_signed" - [(set (match_operand:SF 0 "register_operand" "=f,f,f,?f,?f,?d") - (if_then_else:SF (match_operator:CC 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t,t,t,t,t,t") - (const_int 0)]) - (match_operand:SF 3 "register_operand" "0,f,f,f,d,fd") - (match_operand:SF 4 "register_operand" "f,0,f,d,fd,fd"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v,v"))] - "TARGET_HAS_FPRS" - "#" - [(set_attr "length" "8,8,12,12,12,12") - (set_attr "type" "multi")]) - -(define_insn "*movsfcc_has_fprs_unsigned" - [(set (match_operand:SF 0 "register_operand" "=f,f,f,?f,?f,?d") - (if_then_else:SF (match_operator:CC_UNS 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t,t,t,t,t,t") - (const_int 0)]) - (match_operand:SF 3 "register_operand" "0,f,f,f,d,fd") - (match_operand:SF 4 "register_operand" "f,0,f,d,fd,fd"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v,v"))] - "TARGET_HAS_FPRS" - "#" - [(set_attr "length" "8,8,12,12,12,12") - (set_attr "type" "multi")]) - -(define_insn "*movsfcc_hardfloat_float" - [(set (match_operand:SF 0 "register_operand" "=f,f,f,?f,?f,?d") - (if_then_else:SF (match_operator:CC_FP 1 "float_relational_operator" - [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u,u") - (const_int 0)]) - (match_operand:SF 3 "register_operand" "0,f,f,f,d,fd") - (match_operand:SF 4 "register_operand" "f,0,f,d,fd,fd"))) - (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w,w"))] - "TARGET_HARD_FLOAT" - "#" - [(set_attr "length" "8,8,12,12,12,12") - (set_attr "type" "multi")]) - -(define_insn "*movsfcc_no_fprs_signed" - [(set (match_operand:SF 0 "integer_register_operand" "=d,d,d") - (if_then_else:SF (match_operator:CC 1 "signed_relational_operator" - [(match_operand:CC 2 "icc_operand" "t,t,t") - (const_int 0)]) - (match_operand:SF 3 "integer_register_operand" "0,d,d") - (match_operand:SF 4 "integer_register_operand" "d,0,d"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "! TARGET_HAS_FPRS" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_insn "*movsfcc_no_fprs_unsigned" - [(set (match_operand:SF 0 "integer_register_operand" "=d,d,d") - (if_then_else:SF (match_operator:CC_UNS 1 "unsigned_relational_operator" - [(match_operand:CC_UNS 2 "icc_operand" "t,t,t") - (const_int 0)]) - (match_operand:SF 3 "integer_register_operand" "0,d,d") - (match_operand:SF 4 "integer_register_operand" "d,0,d"))) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "! TARGET_HAS_FPRS" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operator 1 "relational_operator" - [(match_operand 2 "cc_operand" "") - (const_int 0)]) - (match_operand:SF 3 "register_operand" "") - (match_operand:SF 4 "register_operand" ""))) - (clobber (match_operand:CC_CCR 5 "cr_operand" ""))] - "reload_completed" - [(match_dup 6)] - "operands[6] = frv_split_cond_move (operands);") - - -;; :::::::::::::::::::: -;; :: -;; :: Minimum, maximum, and integer absolute value -;; :: -;; :::::::::::::::::::: - -;; These 'instructions' are provided to give the compiler a slightly better -;; nudge at register allocation, then it would if it constructed the -;; instructions from basic building blocks (since it indicates it prefers one -;; of the operands to be the same as the destination. It also helps the -;; earlier passes of the compiler, by not breaking things into small basic -;; blocks. - -(define_expand "abssi2" - [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") - (abs:SI (match_operand:SI 1 "integer_register_operand" ""))) - (clobber (match_dup 2)) - (clobber (match_dup 3))])] - "TARGET_COND_MOVE" - " -{ - operands[2] = gen_reg_rtx (CCmode); - operands[3] = gen_reg_rtx (CC_CCRmode); -}") - -(define_insn_and_split "*abssi2_internal" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d") - (abs:SI (match_operand:SI 1 "integer_register_operand" "0,d"))) - (clobber (match_operand:CC 2 "icc_operand" "=t,t")) - (clobber (match_operand:CC_CCR 3 "icr_operand" "=v,v"))] - "TARGET_COND_MOVE" - "#" - "reload_completed" - [(match_dup 4)] - "operands[4] = frv_split_abs (operands);" - [(set_attr "length" "12,16") - (set_attr "type" "multi")]) - -(define_expand "sminsi3" - [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") - (smin:SI (match_operand:SI 1 "integer_register_operand" "") - (match_operand:SI 2 "gpr_or_int10_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "TARGET_COND_MOVE" - " -{ - operands[3] = gen_reg_rtx (CCmode); - operands[4] = gen_reg_rtx (CC_CCRmode); -}") - -(define_expand "smaxsi3" - [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") - (smax:SI (match_operand:SI 1 "integer_register_operand" "") - (match_operand:SI 2 "gpr_or_int10_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "TARGET_COND_MOVE" - " -{ - operands[3] = gen_reg_rtx (CCmode); - operands[4] = gen_reg_rtx (CC_CCRmode); -}") - -(define_insn_and_split "*minmax_si_signed" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d,&d") - (match_operator:SI 1 "minmax_operator" - [(match_operand:SI 2 "integer_register_operand" "%0,dO,d") - (match_operand:SI 3 "gpr_or_int10_operand" "dO,0,dJ")])) - (clobber (match_operand:CC 4 "icc_operand" "=t,t,t")) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "TARGET_COND_MOVE" - "#" - "reload_completed" - [(match_dup 6)] - "operands[6] = frv_split_minmax (operands);" - [(set_attr "length" "12,12,16") - (set_attr "type" "multi")]) - -(define_expand "uminsi3" - [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") - (umin:SI (match_operand:SI 1 "integer_register_operand" "") - (match_operand:SI 2 "gpr_or_int10_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "TARGET_COND_MOVE" - " -{ - operands[3] = gen_reg_rtx (CC_UNSmode); - operands[4] = gen_reg_rtx (CC_CCRmode); -}") - -(define_expand "umaxsi3" - [(parallel [(set (match_operand:SI 0 "integer_register_operand" "") - (umax:SI (match_operand:SI 1 "integer_register_operand" "") - (match_operand:SI 2 "gpr_or_int10_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "TARGET_COND_MOVE" - " -{ - operands[3] = gen_reg_rtx (CC_UNSmode); - operands[4] = gen_reg_rtx (CC_CCRmode); -}") - -(define_insn_and_split "*minmax_si_unsigned" - [(set (match_operand:SI 0 "integer_register_operand" "=d,d,&d") - (match_operator:SI 1 "minmax_operator" - [(match_operand:SI 2 "integer_register_operand" "%0,dO,d") - (match_operand:SI 3 "gpr_or_int10_operand" "dO,0,dJ")])) - (clobber (match_operand:CC_UNS 4 "icc_operand" "=t,t,t")) - (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))] - "TARGET_COND_MOVE" - "#" - "reload_completed" - [(match_dup 6)] - "operands[6] = frv_split_minmax (operands);" - [(set_attr "length" "12,12,16") - (set_attr "type" "multi")]) - -(define_expand "sminsf3" - [(parallel [(set (match_operand:SF 0 "fpr_operand" "") - (smin:SF (match_operand:SF 1 "fpr_operand" "") - (match_operand:SF 2 "fpr_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "TARGET_COND_MOVE && TARGET_HARD_FLOAT" - " -{ - operands[3] = gen_reg_rtx (CC_FPmode); - operands[4] = gen_reg_rtx (CC_CCRmode); -}") - -(define_expand "smaxsf3" - [(parallel [(set (match_operand:SF 0 "fpr_operand" "") - (smax:SF (match_operand:SF 1 "fpr_operand" "") - (match_operand:SF 2 "fpr_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "TARGET_COND_MOVE && TARGET_HARD_FLOAT" - " -{ - operands[3] = gen_reg_rtx (CC_FPmode); - operands[4] = gen_reg_rtx (CC_CCRmode); -}") - -(define_insn_and_split "*minmax_sf" - [(set (match_operand:SF 0 "fpr_operand" "=f,f,f") - (match_operator:SF 1 "minmax_operator" - [(match_operand:SF 2 "fpr_operand" "%0,f,f") - (match_operand:SF 3 "fpr_operand" "f,0,f")])) - (clobber (match_operand:CC_FP 4 "fcc_operand" "=u,u,u")) - (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] - "TARGET_COND_MOVE && TARGET_HARD_FLOAT" - "#" - "reload_completed" - [(match_dup 6)] - "operands[6] = frv_split_minmax (operands);" - [(set_attr "length" "12,12,16") - (set_attr "type" "multi")]) - -(define_expand "smindf3" - [(parallel [(set (match_operand:DF 0 "fpr_operand" "") - (smin:DF (match_operand:DF 1 "fpr_operand" "") - (match_operand:DF 2 "fpr_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "TARGET_COND_MOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE" - " -{ - operands[3] = gen_reg_rtx (CC_FPmode); - operands[4] = gen_reg_rtx (CC_CCRmode); -}") - -(define_expand "smaxdf3" - [(parallel [(set (match_operand:DF 0 "fpr_operand" "") - (smax:DF (match_operand:DF 1 "fpr_operand" "") - (match_operand:DF 2 "fpr_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "TARGET_COND_MOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE" - " -{ - operands[3] = gen_reg_rtx (CC_FPmode); - operands[4] = gen_reg_rtx (CC_CCRmode); -}") - -(define_insn_and_split "*minmax_df" - [(set (match_operand:DF 0 "fpr_operand" "=f,f,f") - (match_operator:DF 1 "minmax_operator" - [(match_operand:DF 2 "fpr_operand" "%0,f,f") - (match_operand:DF 3 "fpr_operand" "f,0,f")])) - (clobber (match_operand:CC_FP 4 "fcc_operand" "=u,u,u")) - (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))] - "TARGET_COND_MOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE" - "#" - "reload_completed" - [(match_dup 6)] - "operands[6] = frv_split_minmax (operands);" - [(set_attr "length" "12,12,16") - (set_attr "type" "multi")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 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" - [(use (match_operand:QI 0 "" "")) - (use (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" ""))] - "" - " -{ - rtx lr = gen_rtx_REG (Pmode, LR_REGNO); - rtx addr; - - if (GET_CODE (operands[0]) != MEM) - abort (); - - addr = XEXP (operands[0], 0); - if (! call_operand (addr, Pmode)) - addr = force_reg (Pmode, addr); - - if (! operands[2]) - operands[2] = const0_rtx; - - emit_call_insn (gen_call_internal (addr, operands[1], operands[2], lr)); - DONE; -}") - -(define_insn "call_internal" - [(call (mem:QI (match_operand:SI 0 "call_operand" "S,dNOP")) - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (clobber (match_operand:SI 3 "lr_operand" "=l,l"))] - "" - "@ - call %0 - call%i0l %M0" - [(set_attr "length" "4") - (set_attr "type" "call,jumpl")]) - -;; 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" - [(use (match_operand 0 "" "")) - (use (match_operand:QI 1 "" "")) - (use (match_operand 2 "" "")) - (use (match_operand 3 "" "")) - (use (match_operand 4 "" ""))] - "" - " -{ - rtx lr = gen_rtx_REG (Pmode, LR_REGNO); - rtx addr; - - if (GET_CODE (operands[1]) != MEM) - abort (); - - addr = XEXP (operands[1], 0); - if (! call_operand (addr, Pmode)) - addr = force_reg (Pmode, addr); - - if (! operands[3]) - operands[3] = const0_rtx; - - emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2], - operands[3], lr)); - DONE; -}") - -(define_insn "call_value_internal" - [(set (match_operand 0 "register_operand" "=d,d") - (call (mem:QI (match_operand:SI 1 "call_operand" "S,dNOP")) - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (clobber (match_operand:SI 4 "lr_operand" "=l,l"))] - "" - "@ - call %1 - call%i1l %M1" - [(set_attr "length" "4") - (set_attr "type" "call,jumpl")]) - -;; return instruction generated instead of jmp to epilog -(define_expand "return" - [(parallel [(return) - (use (match_dup 0)) - (use (const_int 1))])] - "direct_return_p ()" - " -{ - operands[0] = gen_rtx_REG (Pmode, LR_REGNO); -}") - -;; return instruction generated by the epilogue -(define_expand "epilogue_return" - [(parallel [(return) - (use (match_operand:SI 0 "register_operand" "")) - (use (const_int 0))])] - "" - "") - -(define_insn "*return_internal" - [(return) - (use (match_operand:SI 0 "register_operand" "l,d")) - (use (match_operand:SI 1 "immediate_operand" "n,n"))] - "" - "@ - ret - jmpl @(%0,%.)" - [(set_attr "length" "4") - (set_attr "type" "jump,jumpl")]) - -;; A version of addsi3 for deallocating stack space at the end of the -;; epilogue. The addition is done in parallel with an (unspec_volatile), -;; which represents the clobbering of the deallocated space. -(define_insn "stack_adjust" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "general_operand" "dNOP"))) - (unspec_volatile [(const_int 0)] UNSPEC_STACK_ADJUST)] - "" - "add%I2 %1,%2,%0" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -;; Normal unconditional jump - -;; Use the "call" instruction for long branches, but prefer to use "bra" for -;; short ones since it does not force us to save the link register. - -;; This define_insn uses the branch-shortening code to decide which -;; instruction it emits. Since the main branch-shortening interface is -;; through get_attr_length(), the two alternatives must be given different -;; lengths. Here we pretend that the far jump is 8 rather than 4 bytes -;; long, though both alternatives are really the same size. -(define_insn "jump" - [(set (pc) (label_ref (match_operand 0 "" "")))] - "" - "* -{ - if (get_attr_length (insn) == 4) - return \"bra %l0\"; - else - return \"call %l0\"; -}" - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 0) (pc)) (const_int -32768)) - (le (minus (match_dup 0) (pc)) (const_int 32764))) - (const_int 4) - (const_int 8))) - (set (attr "far_jump") - (if_then_else - (eq_attr "length" "4") - (const_string "no") - (const_string "yes"))) - (set (attr "type") - (if_then_else - (eq_attr "length" "4") - (const_string "jump") - (const_string "call")))]) - -;; Indirect jump through a register -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "d,l"))] - "" - "@ - jmpl @(%0,%.) - bralr" - [(set_attr "length" "4") - (set_attr "type" "jumpl,branch")]) - -;; 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. Either the 'casesi' pattern or the 'tablejump' pattern, or both, -;; MUST be present in this file. - -;; 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_expand "tablejump" - [(parallel [(set (pc) (match_operand:SI 0 "address_operand" "p")) - (use (label_ref (match_operand 1 "" "")))])] - "!flag_pic" - "") - -(define_insn "tablejump_insn" - [(set (pc) (match_operand:SI 0 "address_operand" "p")) - (use (label_ref (match_operand 1 "" "")))] - "" - "jmp%I0l %M0" - [(set_attr "length" "4") - (set_attr "type" "jumpl")]) - -;; Implement switch statements when generating PIC code. Switches are -;; implemented by `tablejump' when not using -fpic. - -;; Emit code here to do the range checking and make the index zero based. -;; operand 0 is the index -;; operand 1 is the lower bound -;; operand 2 is the range of indices (highest - lowest + 1) -;; operand 3 is the label that precedes the table itself -;; operand 4 is the fall through label - -(define_expand "casesi" - [(use (match_operand:SI 0 "integer_register_operand" "")) - (use (match_operand:SI 1 "const_int_operand" "")) - (use (match_operand:SI 2 "const_int_operand" "")) - (use (match_operand 3 "" "")) - (use (match_operand 4 "" ""))] - "flag_pic" - " -{ - rtx indx; - rtx scale; - rtx low = operands[1]; - rtx range = operands[2]; - rtx table = operands[3]; - rtx treg; - rtx fail = operands[4]; - rtx mem; - rtx reg2; - rtx reg3; - - if (GET_CODE (operands[1]) != CONST_INT) - abort (); - - if (GET_CODE (operands[2]) != CONST_INT) - abort (); - - /* If we can't generate an immediate instruction, promote to register */ - if (! IN_RANGE_P (INTVAL (range), -2048, 2047)) - range = force_reg (SImode, range); - - /* If low bound is 0, we don't have to subtract it. */ - if (INTVAL (operands[1]) == 0) - indx = operands[0]; - else - { - indx = gen_reg_rtx (SImode); - if (IN_RANGE_P (INTVAL (low), -2047, 2048)) - emit_insn (gen_addsi3 (indx, operands[0], GEN_INT (- INTVAL (low)))); - else - emit_insn (gen_subsi3 (indx, operands[0], force_reg (SImode, low))); - } - - /* Do an unsigned comparison (in the proper mode) between the index - expression and the value which represents the length of the range. - Since we just finished subtracting the lower bound of the range - from the index expression, this comparison allows us to simultaneously - check that the original index expression value is both greater than - or equal to the minimum value of the range and less than or equal to - the maximum value of the range. */ - - emit_cmp_and_jump_insns (indx, range, GTU, NULL_RTX, SImode, 1, fail); - - /* Move the table address to a register */ - treg = gen_reg_rtx (Pmode); - emit_insn (gen_movsi (treg, gen_rtx_LABEL_REF (VOIDmode, table))); - - /* scale index-low by wordsize */ - scale = gen_reg_rtx (SImode); - emit_insn (gen_ashlsi3 (scale, indx, GEN_INT (2))); - - /* Load the address, add the start of the table back in, - and jump to it. */ - mem = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, scale, treg)); - reg2 = gen_reg_rtx (SImode); - reg3 = gen_reg_rtx (SImode); - emit_insn (gen_movsi (reg2, mem)); - emit_insn (gen_addsi3 (reg3, reg2, treg)); - emit_jump_insn (gen_tablejump_insn (reg3, table)); - DONE; -}") - - -;; :::::::::::::::::::: -;; :: -;; :: 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)] - "" - " -{ - frv_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_EPILOGUE macro, since it allows the scheduler -;; to intermix instructions with the restires 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. -(define_expand "epilogue" - [(const_int 2)] - "" - " -{ - frv_expand_epilogue (FALSE); - DONE; -}") - -;; This pattern, if defined, emits RTL for exit from a function without the final -;; branch back to the calling function. This pattern will be emitted before any -;; sibling call (aka tail call) sites. -;; -;; The sibcall_epilogue pattern must not clobber any arguments used for -;; parameter passing or any stack slots for arguments passed to the current -;; function. -(define_expand "sibcall_epilogue" - [(const_int 3)] - "" - " -{ - frv_expand_epilogue (TRUE); - DONE; -}") - -;; Set up the pic register to hold the address of the pic table -(define_insn "pic_prologue" - [(set (match_operand:SI 0 "integer_register_operand" "=d") - (unspec_volatile:SI [(const_int 0)] UNSPEC_PIC_PROLOGUE)) - (clobber (match_operand:SI 1 "lr_operand" "=l")) - (clobber (match_operand:SI 2 "integer_register_operand" "=d"))] - "" - "* -{ - static int frv_pic_labelno = 0; - - operands[3] = GEN_INT (frv_pic_labelno++); - return \"call %P3\\n%P3:\;movsg %1, %0\;sethi #gprelhi(%P3), %2\;setlo #gprello(%P3), %2\;sub %0,%2,%0\"; -}" - [(set_attr "length" "16") - (set_attr "type" "multi")]) - -;; :::::::::::::::::::: -;; :: -;; :: Miscellaneous instructions -;; :: -;; :::::::::::::::::::: - -;; No operation, needed in case the user uses -g but not -O. -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "length" "4") - (set_attr "type" "int")]) - -;; Pseudo instruction that prevents the scheduler from moving code above this -;; point. Note, type unknown is used to make sure the VLIW instructions are -;; not continued past this point. -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)] - "" - "# blockage" - [(set_attr "length" "0") - (set_attr "type" "unknown")]) - -;; :::::::::::::::::::: -;; :: -;; :: Media instructions -;; :: -;; :::::::::::::::::::: - -;; Unimplemented instructions: -;; - MCMPSH, MCMPUH - -(define_constants - [(UNSPEC_MLOGIC 100) - (UNSPEC_MNOT 101) - (UNSPEC_MAVEH 102) - (UNSPEC_MSATH 103) - (UNSPEC_MADDH 104) - (UNSPEC_MQADDH 105) - (UNSPEC_MPACKH 106) - (UNSPEC_MUNPACKH 107) - (UNSPEC_MDPACKH 108) - (UNSPEC_MBTOH 109) - (UNSPEC_MHTOB 110) - (UNSPEC_MROT 111) - (UNSPEC_MSHIFT 112) - (UNSPEC_MEXPDHW 113) - (UNSPEC_MEXPDHD 114) - (UNSPEC_MWCUT 115) - (UNSPEC_MMULH 116) - (UNSPEC_MMULXH 117) - (UNSPEC_MMACH 118) - (UNSPEC_MMRDH 119) - (UNSPEC_MQMULH 120) - (UNSPEC_MQMULXH 121) - (UNSPEC_MQMACH 122) - (UNSPEC_MCPX 123) - (UNSPEC_MQCPX 124) - (UNSPEC_MCUT 125) - (UNSPEC_MRDACC 126) - (UNSPEC_MRDACCG 127) - (UNSPEC_MWTACC 128) - (UNSPEC_MWTACCG 129) - (UNSPEC_MTRAP 130) - (UNSPEC_MCLRACC 131) - (UNSPEC_MCLRACCA 132) - (UNSPEC_MCOP1 133) - (UNSPEC_MCOP2 134) - (UNSPEC_MDUNPACKH 135) - (UNSPEC_MDUNPACKH_INTERNAL 136) - (UNSPEC_MBTOHE 137) - (UNSPEC_MBTOHE_INTERNAL 138) - (UNSPEC_MBTOHE 137) - (UNSPEC_MBTOHE_INTERNAL 138) - (UNSPEC_MQMACH2 139) - (UNSPEC_MADDACC 140) - (UNSPEC_MDADDACC 141) - (UNSPEC_MABSHS 142) - (UNSPEC_MDROTLI 143) - (UNSPEC_MCPLHI 144) - (UNSPEC_MCPLI 145) - (UNSPEC_MDCUTSSI 146) - (UNSPEC_MQSATHS 147) - (UNSPEC_MHSETLOS 148) - (UNSPEC_MHSETLOH 149) - (UNSPEC_MHSETHIS 150) - (UNSPEC_MHSETHIH 151) - (UNSPEC_MHDSETS 152) - (UNSPEC_MHDSETH 153) -]) - -;; Logic operations: type "mlogic" - -(define_expand "mand" - [(set (match_operand:SI 0 "fpr_operand" "") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "") - (match_operand:SI 2 "fpr_operand" "") - (match_dup 3)] - UNSPEC_MLOGIC))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MAND);") - -(define_expand "mor" - [(set (match_operand:SI 0 "fpr_operand" "") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "") - (match_operand:SI 2 "fpr_operand" "") - (match_dup 3)] - UNSPEC_MLOGIC))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MOR);") - -(define_expand "mxor" - [(set (match_operand:SI 0 "fpr_operand" "") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "") - (match_operand:SI 2 "fpr_operand" "") - (match_dup 3)] - UNSPEC_MLOGIC))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MXOR);") - -(define_insn "*mlogic" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MLOGIC))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MAND: return \"mand %1, %2, %0\"; - case FRV_BUILTIN_MOR: return \"mor %1, %2, %0\"; - case FRV_BUILTIN_MXOR: return \"mxor %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mlogic\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mlogic")]) - -(define_insn "*cond_exec_mlogic" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 3 "fpr_operand" "f") - (match_operand:SI 4 "fpr_operand" "f") - (match_operand:SI 5 "const_int_operand" "n")] - UNSPEC_MLOGIC)))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[5])) - { - default: break; - case FRV_BUILTIN_MAND: return \"cmand %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MOR: return \"cmor %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MXOR: return \"cmxor %3, %4, %2, %1, %e0\"; - } - - fatal_insn (\"Bad media insn, cond_exec_mlogic\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mlogic")]) - -;; Logical not: type "mlogic" - -(define_insn "mnot" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MNOT))] - "TARGET_MEDIA" - "mnot %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mlogic")]) - -(define_insn "*cond_exec_mnot" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 3 "fpr_operand" "f")] UNSPEC_MNOT)))] - "TARGET_MEDIA" - "cmnot %3, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "mlogic")]) - -;; Dual average (halfword): type "maveh" - -(define_insn "maveh" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f")] - UNSPEC_MAVEH))] - "TARGET_MEDIA" - "maveh %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "maveh")]) - -;; Dual saturation (halfword): type "msath" - -(define_expand "msaths" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 3)] - UNSPEC_MSATH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MSATHS);") - -(define_expand "msathu" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 3)] - UNSPEC_MSATH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MSATHU);") - -(define_insn "*msath" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MSATH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MSATHS: return \"msaths %1, %2, %0\"; - case FRV_BUILTIN_MSATHU: return \"msathu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, msath\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "msath")]) - -;; Dual addition/subtraction with saturation (halfword): type "maddh" - -(define_expand "maddhss" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 3)] - UNSPEC_MADDH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MADDHSS);") - -(define_expand "maddhus" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 3)] - UNSPEC_MADDH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MADDHUS);") - -(define_expand "msubhss" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 3)] - UNSPEC_MADDH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MSUBHSS);") - -(define_expand "msubhus" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 3)] - UNSPEC_MADDH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MSUBHUS);") - -(define_insn "*maddh" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MADDH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MADDHSS: return \"maddhss %1, %2, %0\"; - case FRV_BUILTIN_MADDHUS: return \"maddhus %1, %2, %0\"; - case FRV_BUILTIN_MSUBHSS: return \"msubhss %1, %2, %0\"; - case FRV_BUILTIN_MSUBHUS: return \"msubhus %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, maddh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "maddh")]) - -(define_insn "*cond_exec_maddh" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 3 "fpr_operand" "f") - (match_operand:SI 4 "fpr_operand" "f") - (match_operand:SI 5 "const_int_operand" "n")] - UNSPEC_MADDH)))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[5])) - { - default: break; - case FRV_BUILTIN_MADDHSS: return \"cmaddhss %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MADDHUS: return \"cmaddhus %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MSUBHSS: return \"cmsubhss %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MSUBHUS: return \"cmsubhus %3, %4, %2, %1, %e0\"; - } - - fatal_insn (\"Bad media insn, cond_exec_maddh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "maddh")]) - -;; Quad addition/subtraction with saturation (halfword): type "mqaddh" - -(define_expand "mqaddhss" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_dup 3)] - UNSPEC_MQADDH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MQADDHSS);") - -(define_expand "mqaddhus" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_dup 3)] - UNSPEC_MQADDH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MQADDHUS);") - -(define_expand "mqsubhss" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_dup 3)] - UNSPEC_MQADDH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MQSUBHSS);") - -(define_expand "mqsubhus" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_dup 3)] - UNSPEC_MQADDH))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MQSUBHUS);") - -(define_insn "*mqaddh" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MQADDH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MQADDHSS: return \"mqaddhss %1, %2, %0\"; - case FRV_BUILTIN_MQADDHUS: return \"mqaddhus %1, %2, %0\"; - case FRV_BUILTIN_MQSUBHSS: return \"mqsubhss %1, %2, %0\"; - case FRV_BUILTIN_MQSUBHUS: return \"mqsubhus %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mqaddh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mqaddh")]) - -(define_insn "*cond_exec_mqaddh" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:DI 2 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 3 "even_fpr_operand" "h") - (match_operand:DI 4 "even_fpr_operand" "h") - (match_operand:SI 5 "const_int_operand" "n")] - UNSPEC_MQADDH)))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[5])) - { - default: break; - case FRV_BUILTIN_MQADDHSS: return \"cmqaddhss %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MQADDHUS: return \"cmqaddhus %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MQSUBHSS: return \"cmqsubhss %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MQSUBHUS: return \"cmqsubhus %3, %4, %2, %1, %e0\"; - } - - fatal_insn (\"Bad media insn, cond_exec_mqaddh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mqaddh")]) - -;; Pack halfword: type "mpackh" - -(define_insn "mpackh" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:HI 1 "fpr_operand" "f") - (match_operand:HI 2 "fpr_operand" "f")] - UNSPEC_MPACKH))] - "TARGET_MEDIA" - "mpackh %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mpackh")]) - -;; Unpack halfword: type "mpackh" - -(define_insn "munpackh" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")] - UNSPEC_MUNPACKH))] - "TARGET_MEDIA" - "munpackh %1, %0" - [(set_attr "length" "4") - (set_attr "type" "munpackh")]) - -;; Dual pack halfword: type "mdpackh" - -(define_insn "mdpackh" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h")] - UNSPEC_MDPACKH))] - "TARGET_MEDIA" - "mdpackh %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mdpackh")]) - -;; Byte-halfword conversion: type "mbhconv" - -(define_insn "mbtoh" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")] - UNSPEC_MBTOH))] - "TARGET_MEDIA" - "mbtoh %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mbhconv")]) - -(define_insn "*cond_exec_mbtoh" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:DI 2 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:SI 3 "fpr_operand" "f")] - UNSPEC_MBTOH)))] - "TARGET_MEDIA" - "cmbtoh %3, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "mbhconv")]) - -(define_insn "mhtob" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:DI 1 "even_fpr_operand" "h")] - UNSPEC_MHTOB))] - "TARGET_MEDIA" - "mhtob %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mbhconv")]) - -(define_insn "*cond_exec_mhtob" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "fpr_operand" "=f") - (unspec:SI [(match_operand:DI 3 "even_fpr_operand" "h")] - UNSPEC_MHTOB)))] - "TARGET_MEDIA" - "cmhtob %3, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "mbhconv")]) - -;; Rotate: type "mrot" - -(define_expand "mrotli" - [(set (match_operand:SI 0 "fpr_operand" "") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "") - (match_operand:SI 2 "uint5_operand" "") - (match_dup 3)] - UNSPEC_MROT))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MROTLI);") - -(define_expand "mrotri" - [(set (match_operand:SI 0 "fpr_operand" "") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "") - (match_operand:SI 2 "uint5_operand" "") - (match_dup 3)] - UNSPEC_MROT))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MROTRI);") - -(define_insn "*mrot" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "uint5_operand" "I") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MROT))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MROTLI: return \"mrotli %1, %2, %0\"; - case FRV_BUILTIN_MROTRI: return \"mrotri %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mrot\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mrot")]) - -;; Dual shift halfword: type "msh" - -(define_expand "msllhi" - [(set (match_operand:SI 0 "fpr_operand" "") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "") - (match_operand:SI 2 "uint4_operand" "") - (match_dup 3)] - UNSPEC_MSHIFT))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MSLLHI);") - -(define_expand "msrlhi" - [(set (match_operand:SI 0 "fpr_operand" "") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "") - (match_operand:SI 2 "uint4_operand" "") - (match_dup 3)] - UNSPEC_MSHIFT))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MSRLHI);") - -(define_expand "msrahi" - [(set (match_operand:SI 0 "fpr_operand" "") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "") - (match_operand:SI 2 "uint4_operand" "") - (match_dup 3)] - UNSPEC_MSHIFT))] - "TARGET_MEDIA" - "operands[3] = GEN_INT (FRV_BUILTIN_MSRAHI);") - -(define_insn "*mshift" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "uint4_operand" "I") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MSHIFT))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MSLLHI: return \"msllhi %1, %2, %0\"; - case FRV_BUILTIN_MSRLHI: return \"msrlhi %1, %2, %0\"; - case FRV_BUILTIN_MSRAHI: return \"msrahi %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mshift\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mshift")]) - -;; Expand halfword to word: type "mexpdhw" - -(define_insn "mexpdhw" - [(set (match_operand:SI 0 "even_fpr_operand" "=h") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "uint1_operand" "I")] - UNSPEC_MEXPDHW))] - "TARGET_MEDIA" - "mexpdhw %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mexpdhw")]) - -(define_insn "*cond_exec_mexpdhw" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:SI 2 "even_fpr_operand" "=h") - (unspec:SI [(match_operand:SI 3 "fpr_operand" "f") - (match_operand:SI 4 "uint1_operand" "I")] - UNSPEC_MEXPDHW)))] - "TARGET_MEDIA" - "cmexpdhw %3, %4, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "mexpdhw")]) - -;; Expand halfword to double: type "mexpdhd" - -(define_insn "mexpdhd" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "uint1_operand" "I")] - UNSPEC_MEXPDHD))] - "TARGET_MEDIA" - "mexpdhd %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mexpdhd")]) - -(define_insn "*cond_exec_mexpdhd" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (set (match_operand:DI 2 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:SI 3 "fpr_operand" "f") - (match_operand:SI 4 "uint1_operand" "I")] - UNSPEC_MEXPDHD)))] - "TARGET_MEDIA" - "cmexpdhd %3, %4, %2, %1, %e0" - [(set_attr "length" "4") - (set_attr "type" "mexpdhd")]) - -;; FR cut: type "mwcut" - -(define_insn "mwcut" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:DI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_or_int6_operand" "fI")] - UNSPEC_MWCUT))] - "TARGET_MEDIA" - "mwcut%i2 %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mwcut")]) - -;; Dual multiplication (halfword): type "mmulh" - -(define_expand "mmulhs" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MMULH)) - (set (match_operand:HI 3 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MMULH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MMULHS);") - -(define_expand "mmulhu" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MMULH)) - (set (match_operand:HI 3 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MMULH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MMULHU);") - -(define_insn "*mmulh" - [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MMULH)) - (set (match_operand:HI 4 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MMULH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MMULHS: return \"mmulhs %1, %2, %0\"; - case FRV_BUILTIN_MMULHU: return \"mmulhu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mmulh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mmulh")]) - -(define_insn "*cond_exec_mmulh" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (parallel [(set (match_operand:DI 2 "even_acc_operand" "=b") - (unspec:DI [(match_operand:SI 3 "fpr_operand" "f") - (match_operand:SI 4 "fpr_operand" "f") - (match_operand:SI 5 "const_int_operand" "n")] - UNSPEC_MMULH)) - (set (match_operand:HI 6 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MMULH))]))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[5])) - { - default: break; - case FRV_BUILTIN_MMULHS: return \"cmmulhs %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MMULHU: return \"cmmulhu %3, %4, %2, %1, %e0\"; - } - - fatal_insn (\"Bad media insn, cond_exec_mmulh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mmulh")]) - -;; Dual cross multiplication (halfword): type "mmulxh" - -(define_expand "mmulxhs" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MMULXH)) - (set (match_operand:HI 3 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MMULXH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MMULXHS);") - -(define_expand "mmulxhu" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MMULXH)) - (set (match_operand:HI 3 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MMULXH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MMULXHU);") - -(define_insn "*mmulxh" - [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MMULXH)) - (set (match_operand:HI 4 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MMULXH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MMULXHS: return \"mmulxhs %1, %2, %0\"; - case FRV_BUILTIN_MMULXHU: return \"mmulxhu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mmulxh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mmulxh")]) - -;; Dual product-sum (halfword): type "mmach" - -(define_expand "mmachs" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b") - (unspec:DI [(match_dup 0) - (match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:HI 3 "accg_operand" "+B") - (match_dup 4)] - UNSPEC_MMACH)) - (set (match_dup 3) - (unspec:HI [(const_int 0)] UNSPEC_MMACH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MMACHS);") - -(define_expand "mmachu" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b") - (unspec:DI [(match_dup 0) - (match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:HI 3 "accg_operand" "+B") - (match_dup 4)] - UNSPEC_MMACH)) - (set (match_dup 3) - (unspec:HI [(const_int 0)] UNSPEC_MMACH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MMACHU);") - -(define_insn "*mmach" - [(set (match_operand:DI 0 "even_acc_operand" "+b") - (unspec:DI [(match_dup 0) - (match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:HI 3 "accg_operand" "+B") - (match_operand:SI 4 "const_int_operand" "n")] - UNSPEC_MMACH)) - (set (match_dup 3) (unspec:HI [(const_int 0)] UNSPEC_MMACH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[4])) - { - default: break; - case FRV_BUILTIN_MMACHS: return \"mmachs %1, %2, %0\"; - case FRV_BUILTIN_MMACHU: return \"mmachu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mmach\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mmach")]) - -(define_insn "*cond_exec_mmach" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (parallel [(set (match_operand:DI 2 "even_acc_operand" "+b") - (unspec:DI [(match_dup 2) - (match_operand:SI 3 "fpr_operand" "f") - (match_operand:SI 4 "fpr_operand" "f") - (match_operand:HI 5 "accg_operand" "+B") - (match_operand:SI 6 "const_int_operand" "n")] - UNSPEC_MMACH)) - (set (match_dup 5) - (unspec:HI [(const_int 0)] UNSPEC_MMACH))]))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[6])) - { - default: break; - case FRV_BUILTIN_MMACHS: return \"cmmachs %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MMACHU: return \"cmmachu %3, %4, %2, %1, %e0\"; - } - - fatal_insn (\"Bad media insn, cond_exec_mmach\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mmach")]) - -;; Dual product-difference: type "mmrdh" - -(define_expand "mmrdhs" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b") - (unspec:DI [(match_dup 0) - (match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:HI 3 "accg_operand" "+B") - (match_dup 4)] - UNSPEC_MMRDH)) - (set (match_dup 3) - (unspec:HI [(const_int 0)] UNSPEC_MMRDH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MMRDHS);") - -(define_expand "mmrdhu" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b") - (unspec:DI [(match_dup 0) - (match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:HI 3 "accg_operand" "+B") - (match_dup 4)] - UNSPEC_MMRDH)) - (set (match_dup 3) - (unspec:HI [(const_int 0)] UNSPEC_MMRDH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MMRDHU);") - -(define_insn "*mmrdh" - [(set (match_operand:DI 0 "even_acc_operand" "+b") - (unspec:DI [(match_dup 0) - (match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:HI 3 "accg_operand" "+B") - (match_operand:SI 4 "const_int_operand" "n")] - UNSPEC_MMRDH)) - (set (match_dup 3) - (unspec:HI [(const_int 0)] UNSPEC_MMRDH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[4])) - { - default: break; - case FRV_BUILTIN_MMRDHS: return \"mmrdhs %1, %2, %0\"; - case FRV_BUILTIN_MMRDHU: return \"mmrdhu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mrdh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mmrdh")]) - -;; Quad multiply (halfword): type "mqmulh" - -(define_expand "mqmulhs" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") - (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_dup 4)] - UNSPEC_MQMULH)) - (set (match_operand:V4QI 3 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQMULHS);") - -(define_expand "mqmulhu" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") - (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_dup 4)] - UNSPEC_MQMULH)) - (set (match_operand:V4QI 3 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQMULHU);") - -(define_insn "*mqmulh" - [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") - (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MQMULH)) - (set (match_operand:V4QI 4 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MQMULHS: return \"mqmulhs %1, %2, %0\"; - case FRV_BUILTIN_MQMULHU: return \"mqmulhu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mqmulh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mqmulh")]) - -(define_insn "*cond_exec_mqmulh" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (parallel [(set (match_operand:V4SI 2 "quad_acc_operand" "=A") - (unspec:V4SI [(match_operand:DI 3 "even_fpr_operand" "h") - (match_operand:DI 4 "even_fpr_operand" "h") - (match_operand:SI 5 "const_int_operand" "n")] - UNSPEC_MQMULH)) - (set (match_operand:V4QI 6 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))]))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[5])) - { - default: break; - case FRV_BUILTIN_MQMULHS: return \"cmqmulhs %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MQMULHU: return \"cmqmulhu %3, %4, %2, %1, %e0\"; - } - - fatal_insn (\"Bad media insn, cond_exec_mqmulh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mqmulh")]) - -;; Quad cross multiply (halfword): type "mqmulxh" - -(define_expand "mqmulxhs" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") - (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_dup 4)] - UNSPEC_MQMULXH)) - (set (match_operand:V4QI 3 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MQMULXH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQMULXHS);") - -(define_expand "mqmulxhu" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") - (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_dup 4)] - UNSPEC_MQMULXH)) - (set (match_operand:V4QI 3 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MQMULXH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQMULXHU);") - -(define_insn "*mqmulxh" - [(set (match_operand:V4SI 0 "quad_acc_operand" "=A") - (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MQMULXH)) - (set (match_operand:V4QI 4 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MQMULXH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MQMULXHS: return \"mqmulxhs %1, %2, %0\"; - case FRV_BUILTIN_MQMULXHU: return \"mqmulxhu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mqmulxh\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mqmulxh")]) - -;; Quad product-sum (halfword): type "mqmach" - -(define_expand "mqmachs" - [(parallel [(set (match_operand:V4SI 0 "even_acc_operand" "+A") - (unspec:V4SI [(match_dup 0) - (match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_operand:V4QI 3 "accg_operand" "+B") - (match_dup 4)] - UNSPEC_MQMACH)) - (set (match_dup 3) - (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQMACHS);") - -(define_expand "mqmachu" - [(parallel [(set (match_operand:V4SI 0 "even_acc_operand" "+A") - (unspec:V4SI [(match_dup 0) - (match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_operand:V4QI 3 "accg_operand" "+B") - (match_dup 4)] - UNSPEC_MQMACH)) - (set (match_dup 3) - (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQMACHU);") - -(define_insn "*mqmach" - [(set (match_operand:V4SI 0 "even_acc_operand" "+A") - (unspec:V4SI [(match_dup 0) - (match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_operand:V4QI 3 "accg_operand" "+B") - (match_operand:SI 4 "const_int_operand" "n")] - UNSPEC_MQMACH)) - (set (match_dup 3) - (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[4])) - { - default: break; - case FRV_BUILTIN_MQMACHS: return \"mqmachs %1, %2, %0\"; - case FRV_BUILTIN_MQMACHU: return \"mqmachu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mqmach\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mqmach")]) - -(define_insn "*cond_exec_mqmach" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (parallel [(set (match_operand:V4SI 2 "even_acc_operand" "+A") - (unspec:V4SI [(match_dup 2) - (match_operand:DI 3 "even_fpr_operand" "h") - (match_operand:DI 4 "even_fpr_operand" "h") - (match_operand:V4QI 5 "accg_operand" "+B") - (match_operand:SI 6 "const_int_operand" "n")] - UNSPEC_MQMACH)) - (set (match_dup 5) - (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))]))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[6])) - { - default: break; - case FRV_BUILTIN_MQMACHS: return \"cmqmachs %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MQMACHU: return \"cmqmachu %3, %4, %2, %1, %e0\"; - } - - fatal_insn (\"Bad media insn, cond_exec_mqmach\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mqmach")]) - -;; Dual complex number product-sum (halfword) - -(define_expand "mcpxrs" - [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MCPX)) - (set (match_operand:QI 3 "accg_operand" "=B") - (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MCPXRS);") - -(define_expand "mcpxru" - [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MCPX)) - (set (match_operand:QI 3 "accg_operand" "=B") - (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MCPXRU);") - -(define_expand "mcpxis" - [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MCPX)) - (set (match_operand:QI 3 "accg_operand" "=B") - (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MCPXIS);") - -(define_expand "mcpxiu" - [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MCPX)) - (set (match_operand:QI 3 "accg_operand" "=B") - (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MCPXIU);") - -(define_insn "*mcpx" - [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MCPX)) - (set (match_operand:QI 4 "accg_operand" "=B") - (unspec:QI [(const_int 0)] UNSPEC_MCPX))])] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MCPXRS: return \"mcpxrs %1, %2, %0\"; - case FRV_BUILTIN_MCPXRU: return \"mcpxru %1, %2, %0\"; - case FRV_BUILTIN_MCPXIS: return \"mcpxis %1, %2, %0\"; - case FRV_BUILTIN_MCPXIU: return \"mcpxiu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mcpx\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mcpx")]) - -(define_insn "*cond_exec_mcpx" - [(cond_exec - (match_operator 0 "ccr_eqne_operator" - [(match_operand 1 "cr_operand" "C") - (const_int 0)]) - (parallel [(set (match_operand:SI 2 "acc_operand" "=a") - (unspec:SI [(match_operand:SI 3 "fpr_operand" "f") - (match_operand:SI 4 "fpr_operand" "f") - (match_operand:SI 5 "const_int_operand" "n")] - UNSPEC_MCPX)) - (set (match_operand:QI 6 "accg_operand" "=B") - (unspec:QI [(const_int 0)] UNSPEC_MCPX))]))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[5])) - { - default: break; - case FRV_BUILTIN_MCPXRS: return \"cmcpxrs %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MCPXRU: return \"cmcpxru %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MCPXIS: return \"cmcpxis %3, %4, %2, %1, %e0\"; - case FRV_BUILTIN_MCPXIU: return \"cmcpxiu %3, %4, %2, %1, %e0\"; - } - - fatal_insn (\"Bad media insn, cond_exec_mcpx\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mcpx")]) - -;; Quad complex number product-sum (halfword): type "mqcpx" - -(define_expand "mqcpxrs" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") - (match_operand:DI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MQCPX)) - (set (match_operand:HI 3 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXRS);") - -(define_expand "mqcpxru" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") - (match_operand:DI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MQCPX)) - (set (match_operand:HI 3 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXRU);") - -(define_expand "mqcpxis" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") - (match_operand:DI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MQCPX)) - (set (match_operand:HI 3 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXIS);") - -(define_expand "mqcpxiu" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") - (match_operand:DI 2 "fpr_operand" "f") - (match_dup 4)] - UNSPEC_MQCPX)) - (set (match_operand:HI 3 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXIU);") - -(define_insn "*mqcpx" - [(set (match_operand:DI 0 "even_acc_operand" "=b") - (unspec:DI [(match_operand:DI 1 "fpr_operand" "f") - (match_operand:DI 2 "fpr_operand" "f") - (match_operand:SI 3 "const_int_operand" "n")] - UNSPEC_MQCPX)) - (set (match_operand:HI 4 "accg_operand" "=B") - (unspec:HI [(const_int 0)] UNSPEC_MQCPX))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[3])) - { - default: break; - case FRV_BUILTIN_MQCPXRS: return \"mqcpxrs %1, %2, %0\"; - case FRV_BUILTIN_MQCPXRU: return \"mqcpxru %1, %2, %0\"; - case FRV_BUILTIN_MQCPXIS: return \"mqcpxis %1, %2, %0\"; - case FRV_BUILTIN_MQCPXIU: return \"mqcpxiu %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mqcpx\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mqcpx")]) - -;; Cut: type "mcut" - -(define_expand "mcut" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "acc_operand" "a") - (match_operand:SI 2 "fpr_or_int6_operand" "fI") - (match_operand:QI 3 "accg_operand" "B") - (match_dup 4)] - UNSPEC_MCUT))] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MCUT);") - -(define_expand "mcutss" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "acc_operand" "a") - (match_operand:SI 2 "fpr_or_int6_operand" "fI") - (match_operand:QI 3 "accg_operand" "B") - (match_dup 4)] - UNSPEC_MCUT))] - "TARGET_MEDIA" - "operands[4] = GEN_INT (FRV_BUILTIN_MCUTSS);") - -(define_insn "*mcut" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "acc_operand" "a") - (match_operand:SI 2 "fpr_or_int6_operand" "fI") - (match_operand:QI 3 "accg_operand" "B") - (match_operand:SI 4 "const_int_operand" "n")] - UNSPEC_MCUT))] - "TARGET_MEDIA" - "* -{ - switch (INTVAL (operands[4])) - { - default: break; - case FRV_BUILTIN_MCUT: return \"mcut%i2 %1, %2, %0\"; - case FRV_BUILTIN_MCUTSS: return \"mcutss%i2 %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mcut\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mcut")]) - -;; Accumulator read: type "mrdacc" - -(define_insn "mrdacc" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "acc_operand" "a")] UNSPEC_MRDACC))] - "TARGET_MEDIA" - "mrdacc %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mrdacc")]) - -(define_insn "mrdaccg" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:QI 1 "accg_operand" "B")] UNSPEC_MRDACCG))] - "TARGET_MEDIA" - "mrdaccg %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mrdacc")]) - -;; Accumulator write: type "mwtacc" - -(define_insn "mwtacc" - [(set (match_operand:SI 0 "acc_operand" "=a") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MWTACC))] - "TARGET_MEDIA" - "mwtacc %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mwtacc")]) - -(define_insn "mwtaccg" - [(set (match_operand:QI 0 "accg_operand" "=B") - (unspec:QI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MWTACCG))] - "TARGET_MEDIA" - "mwtaccg %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mwtacc")]) - -;; Trap: This one executes on the control unit, not the media units. - -(define_insn "mtrap" - [(unspec_volatile [(const_int 0)] UNSPEC_MTRAP)] - "TARGET_MEDIA" - "mtrap" - [(set_attr "length" "4") - (set_attr "type" "trap")]) - -;; Clear single accumulator: type "mclracc" - -(define_insn "mclracc_internal" - [(set (match_operand:SI 0 "acc_operand" "=a") - (unspec:SI [(const_int 0)] UNSPEC_MCLRACC)) - (set (match_operand:QI 1 "accg_operand" "=B") - (unspec:QI [(const_int 0)] UNSPEC_MCLRACC))] - "TARGET_MEDIA" - "mclracc %0,#0" - [(set_attr "length" "4") - (set_attr "type" "mclracc")]) - -(define_expand "mclracc" - [(parallel [(set (match_operand:SI 0 "acc_operand" "=a") - (unspec:SI [(const_int 0)] UNSPEC_MCLRACC)) - (set (match_dup 1) - (unspec:QI [(const_int 0)] UNSPEC_MCLRACC))])] - "TARGET_MEDIA" - " -{ - if (GET_CODE (operands[0]) != REG || !ACC_P (REGNO (operands[0]))) - FAIL; - - operands[1] = frv_matching_accg_for_acc (operands[0]); -}") - -;; Clear all accumulators: type "mclracca" - -(define_insn "mclracca8_internal" - [(set (match_operand:V4SI 0 "quad_acc_operand" "=b") - (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) - (set (match_operand:V4SI 1 "quad_acc_operand" "=b") - (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) - (set (match_operand:V4QI 2 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA)) - (set (match_operand:V4QI 3 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))] - "TARGET_MEDIA && TARGET_ACC_8" - "mclracc acc0,#1" - [(set_attr "length" "4") - (set_attr "type" "mclracca")]) - -(define_insn "mclracca4_internal" - [(set (match_operand:V4SI 0 "quad_acc_operand" "=b") - (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) - (set (match_operand:V4QI 1 "accg_operand" "=B") - (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))] - "TARGET_MEDIA && TARGET_ACC_4" - "mclracc acc0,#1" - [(set_attr "length" "4") - (set_attr "type" "mclracca")]) - -(define_expand "mclracca8" - [(parallel [(set (match_dup 0) (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) - (set (match_dup 1) (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) - (set (match_dup 2) (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA)) - (set (match_dup 3) (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))])] - "TARGET_MEDIA && TARGET_ACC_8" - " -{ - operands[0] = gen_rtx_REG (V4SImode, ACC_FIRST); - operands[1] = gen_rtx_REG (V4SImode, ACC_FIRST + 4); - operands[2] = gen_rtx_REG (V4QImode, ACCG_FIRST); - operands[3] = gen_rtx_REG (V4QImode, ACCG_FIRST + 4); -}") - -(define_expand "mclracca4" - [(parallel [(set (match_dup 0) (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA)) - (set (match_dup 1) (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))])] - "TARGET_MEDIA && TARGET_ACC_4" - " -{ - operands[0] = gen_rtx_REG (V4SImode, ACC_FIRST); - operands[1] = gen_rtx_REG (V4QImode, ACCG_FIRST); -}") - -(define_insn "mcop1" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f")] UNSPEC_MCOP1))] - "TARGET_MEDIA_REV1" - "mcop1 %1, %2, %0" - [(set_attr "length" "4") -;; What is the class of the insn ??? - (set_attr "type" "multi")]) - -(define_insn "mcop2" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f") - (match_operand:SI 2 "fpr_operand" "f")] UNSPEC_MCOP2))] - "TARGET_MEDIA_REV1" - "mcop2 %1, %2, %0" - [(set_attr "length" "4") -;; What is the class of the insn ??? - (set_attr "type" "multi")]) - -(define_insn "*mdunpackh_internal" - [(set (match_operand:V4SI 0 "quad_fpr_operand" "=x") - (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")] - UNSPEC_MDUNPACKH_INTERNAL))] - "TARGET_MEDIA_REV1" - "mdunpackh %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mdunpackh")]) - -(define_insn_and_split "mdunpackh" - [(set (match_operand:V4SI 0 "memory_operand" "=o") - (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")] - UNSPEC_MDUNPACKH)) - (clobber (match_scratch:V4SI 2 "=x"))] - "TARGET_MEDIA_REV1" - "#" - "reload_completed" - [(set (match_dup 2) - (unspec:V4SI [(match_dup 1)] UNSPEC_MDUNPACKH_INTERNAL)) - (set (match_dup 3) - (match_dup 4)) - (set (match_dup 5) - (match_dup 6))] - " -{ - operands[3] = change_address (operands[0], DImode, NULL_RTX); - operands[4] = gen_rtx_REG (DImode, REGNO (operands[2])); - operands[5] = frv_index_memory (operands[0], DImode, 1); - operands[6] = gen_rtx_REG (DImode, REGNO (operands[2])+2); -}" - [(set_attr "length" "20") - (set_attr "type" "multi")]) - -(define_insn "*mbtohe_internal" - [(set (match_operand:V4SI 0 "quad_fpr_operand" "=x") - (unspec:V4SI [(match_operand:SI 1 "fpr_operand" "f")] - UNSPEC_MBTOHE_INTERNAL))] - "TARGET_MEDIA_REV1" - "mbtohe %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mbhconve")]) - -(define_insn_and_split "mbtohe" - [(set (match_operand:V4SI 0 "memory_operand" "=o") - (unspec:V4SI [(match_operand:SI 1 "fpr_operand" "f")] - UNSPEC_MBTOHE)) - (clobber (match_scratch:V4SI 2 "=x"))] - "TARGET_MEDIA_REV1" - "#" - "reload_completed" - [(set (match_dup 2) - (unspec:V4SI [(match_dup 1)] UNSPEC_MBTOHE_INTERNAL)) - (set (match_dup 3) - (match_dup 4)) - (set (match_dup 5) - (match_dup 6))] - " -{ - operands[3] = change_address (operands[0], DImode, NULL_RTX); - operands[4] = gen_rtx_REG (DImode, REGNO (operands[2])); - operands[5] = frv_index_memory (operands[0], DImode, 1); - operands[6] = gen_rtx_REG (DImode, REGNO (operands[2])+2); -}" - [(set_attr "length" "20") - (set_attr "type" "multi")]) - -;; Quad product-sum (halfword) instructions only found on the FR400. -;; type "mqmach" - -(define_expand "mqxmachs" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "") - (unspec:V4SI [(match_dup 0) - (match_operand:DI 1 "even_fpr_operand" "") - (match_operand:DI 2 "even_fpr_operand" "") - (match_operand:V4QI 3 "accg_operand" "") - (match_dup 4)] - UNSPEC_MQMACH2)) - (set (match_dup 3) - (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))])] - "TARGET_MEDIA_REV2" - "operands[4] = GEN_INT (FRV_BUILTIN_MQXMACHS);") - -(define_expand "mqxmacxhs" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "") - (unspec:V4SI [(match_dup 0) - (match_operand:DI 1 "even_fpr_operand" "") - (match_operand:DI 2 "even_fpr_operand" "") - (match_operand:V4QI 3 "accg_operand" "") - (match_dup 4)] - UNSPEC_MQMACH2)) - (set (match_dup 3) - (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))])] - "TARGET_MEDIA_REV2" - "operands[4] = GEN_INT (FRV_BUILTIN_MQXMACXHS);") - -(define_expand "mqmacxhs" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "") - (unspec:V4SI [(match_dup 0) - (match_operand:DI 1 "even_fpr_operand" "") - (match_operand:DI 2 "even_fpr_operand" "") - (match_operand:V4QI 3 "accg_operand" "") - (match_dup 4)] - UNSPEC_MQMACH2)) - (set (match_dup 3) - (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))])] - "TARGET_MEDIA_REV2" - "operands[4] = GEN_INT (FRV_BUILTIN_MQMACXHS);") - -(define_insn "*mqmach2" - [(set (match_operand:V4SI 0 "quad_acc_operand" "+A") - (unspec:V4SI [(match_dup 0) - (match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h") - (match_operand:V4QI 3 "accg_operand" "+B") - (match_operand:SI 4 "const_int_operand" "n")] - UNSPEC_MQMACH2)) - (set (match_dup 3) - (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))] - "TARGET_MEDIA_REV2" - "* -{ - switch (INTVAL (operands[4])) - { - default: break; - case FRV_BUILTIN_MQXMACHS: return \"mqxmachs %1, %2, %0\"; - case FRV_BUILTIN_MQXMACXHS: return \"mqxmacxhs %1, %2, %0\"; - case FRV_BUILTIN_MQMACXHS: return \"mqmacxhs %1, %2, %0\"; - } - - fatal_insn (\"Bad media insn, mqmach2\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mqmach")]) - -;; Accumulator addition/subtraction: type "maddacc" - -(define_expand "maddaccs" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "") - (unspec:DI [(match_dup 0) - (match_operand:DI 1 "even_acc_operand" "")] - UNSPEC_MADDACC)) - (set (match_operand:HI 2 "accg_operand" "") - (unspec:HI [(match_dup 2) - (match_operand:HI 3 "accg_operand" "") - (match_dup 4)] - UNSPEC_MADDACC))])] - "TARGET_MEDIA_REV2" - "operands[4] = GEN_INT (FRV_BUILTIN_MADDACCS);") - -(define_expand "msubaccs" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "") - (unspec:DI [(match_dup 0) - (match_operand:DI 1 "even_acc_operand" "")] - UNSPEC_MADDACC)) - (set (match_operand:HI 2 "accg_operand" "") - (unspec:HI [(match_dup 2) - (match_operand:HI 3 "accg_operand" "") - (match_dup 4)] - UNSPEC_MADDACC))])] - "TARGET_MEDIA_REV2" - "operands[4] = GEN_INT (FRV_BUILTIN_MSUBACCS);") - -(define_expand "masaccs" - [(parallel [(set (match_operand:DI 0 "even_acc_operand" "") - (unspec:DI [(match_dup 0) - (match_operand:DI 1 "even_acc_operand" "")] - UNSPEC_MADDACC)) - (set (match_operand:HI 2 "accg_operand" "") - (unspec:HI [(match_dup 2) - (match_operand:HI 3 "accg_operand" "") - (match_dup 4)] - UNSPEC_MADDACC))])] - "TARGET_MEDIA_REV2" - "operands[4] = GEN_INT (FRV_BUILTIN_MASACCS);") - -(define_insn "*maddacc" - [(set (match_operand:DI 0 "even_acc_operand" "+b") - (unspec:DI [(match_dup 0) - (match_operand:DI 1 "even_acc_operand" "b")] - UNSPEC_MADDACC)) - (set (match_operand:HI 2 "accg_operand" "+B") - (unspec:HI [(match_dup 2) - (match_operand:HI 3 "accg_operand" "B") - (match_operand:SI 4 "const_int_operand" "n")] - UNSPEC_MADDACC))] - "TARGET_MEDIA_REV2" - "* -{ - switch (INTVAL (operands[4])) - { - default: break; - case FRV_BUILTIN_MADDACCS: return \"maddaccs %1, %0\"; - case FRV_BUILTIN_MSUBACCS: return \"msubaccs %1, %0\"; - case FRV_BUILTIN_MASACCS: return \"masaccs %1, %0\"; - } - - fatal_insn (\"Bad media insn, maddacc\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "maddacc")]) - -;; Dual accumulator addition/subtraction: type "mdaddacc" - -(define_expand "mdaddaccs" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "") - (unspec:V4SI [(match_dup 0) - (match_operand:V4SI 1 "quad_acc_operand" "")] - UNSPEC_MDADDACC)) - (set (match_operand:V4QI 2 "accg_operand" "") - (unspec:V4QI [(match_dup 2) - (match_operand:V4QI 3 "accg_operand" "") - (match_dup 4)] - UNSPEC_MDADDACC))])] - "TARGET_MEDIA_REV2" - "operands[4] = GEN_INT (FRV_BUILTIN_MDADDACCS);") - -(define_expand "mdsubaccs" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "") - (unspec:V4SI [(match_dup 0) - (match_operand:V4SI 1 "quad_acc_operand" "")] - UNSPEC_MDADDACC)) - (set (match_operand:V4QI 2 "accg_operand" "") - (unspec:V4QI [(match_dup 2) - (match_operand:V4QI 3 "accg_operand" "") - (match_dup 4)] - UNSPEC_MDADDACC))])] - "TARGET_MEDIA_REV2" - "operands[4] = GEN_INT (FRV_BUILTIN_MDSUBACCS);") - -(define_expand "mdasaccs" - [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "") - (unspec:V4SI [(match_dup 0) - (match_operand:V4SI 1 "quad_acc_operand" "")] - UNSPEC_MDADDACC)) - (set (match_operand:V4QI 2 "accg_operand" "") - (unspec:V4QI [(match_dup 2) - (match_operand:V4QI 3 "accg_operand" "") - (match_dup 4)] - UNSPEC_MDADDACC))])] - "TARGET_MEDIA_REV2" - "operands[4] = GEN_INT (FRV_BUILTIN_MDASACCS);") - -(define_insn "*mdaddacc" - [(set (match_operand:V4SI 0 "quad_acc_operand" "+A") - (unspec:V4SI [(match_dup 0) - (match_operand:V4SI 1 "quad_acc_operand" "A")] - UNSPEC_MDADDACC)) - (set (match_operand:V4QI 2 "accg_operand" "+B") - (unspec:V4QI [(match_dup 2) - (match_operand:V4QI 3 "accg_operand" "B") - (match_operand:SI 4 "const_int_operand" "n")] - UNSPEC_MDADDACC))] - "TARGET_MEDIA_REV2" - "* -{ - switch (INTVAL (operands[4])) - { - default: break; - case FRV_BUILTIN_MDADDACCS: return \"mdaddaccs %1, %0\"; - case FRV_BUILTIN_MDSUBACCS: return \"mdsubaccs %1, %0\"; - case FRV_BUILTIN_MDASACCS: return \"mdasaccs %1, %0\"; - } - - fatal_insn (\"Bad media insn, mdaddacc\", insn); -}" - [(set_attr "length" "4") - (set_attr "type" "mdaddacc")]) - -;; Dual absolute (halfword): type "mabsh" - -(define_insn "mabshs" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MABSHS))] - "TARGET_MEDIA_REV2" - "mabshs %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mabsh")]) - -;; Dual rotate: type "mdrot" - -(define_insn "mdrotli" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:SI 2 "uint5_operand" "I")] - UNSPEC_MDROTLI))] - "TARGET_MEDIA_REV2" - "mdrotli %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mdrot")]) - -;; Dual coupling (concatenation): type "mcpl" - -(define_insn "mcplhi" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:DI 1 "fpr_operand" "h") - (match_operand:SI 2 "uint4_operand" "I")] - UNSPEC_MCPLHI))] - "TARGET_MEDIA_REV2" - "mcplhi %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mcpl")]) - -(define_insn "mcpli" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:DI 1 "fpr_operand" "h") - (match_operand:SI 2 "uint5_operand" "I")] - UNSPEC_MCPLI))] - "TARGET_MEDIA_REV2" - "mcpli %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mcpl")]) - -;; Dual cut: type "mdcut" - -(define_insn "mdcutssi" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 1 "even_acc_operand" "b") - (match_operand:SI 2 "int6_operand" "I") - (match_operand:HI 3 "accg_operand" "B")] - UNSPEC_MDCUTSSI))] - "TARGET_MEDIA_REV2" - "mdcutssi %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mdcut")]) - -;; Quad saturate (halfword): type "mqsath" - -(define_insn "mqsaths" - [(set (match_operand:DI 0 "even_fpr_operand" "=h") - (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h") - (match_operand:DI 2 "even_fpr_operand" "h")] - UNSPEC_MQSATHS))] - "TARGET_MEDIA_REV2" - "mqsaths %1, %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mqsath")]) - -;; Set hi/lo instrctions: type "mset" - -(define_insn "mhsetlos" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") - (match_operand:SI 2 "int12_operand" "NOP")] - UNSPEC_MHSETLOS))] - "TARGET_MEDIA_REV2" - "mhsetlos %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mset")]) - -(define_insn "mhsetloh" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") - (match_operand:SI 2 "int5_operand" "I")] - UNSPEC_MHSETLOH))] - "TARGET_MEDIA_REV2" - "mhsetloh %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mset")]) - -(define_insn "mhsethis" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") - (match_operand:SI 2 "int12_operand" "NOP")] - UNSPEC_MHSETHIS))] - "TARGET_MEDIA_REV2" - "mhsethis %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mset")]) - -(define_insn "mhsethih" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") - (match_operand:SI 2 "int5_operand" "I")] - UNSPEC_MHSETHIH))] - "TARGET_MEDIA_REV2" - "mhsethih %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mset")]) - -(define_insn "mhdsets" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "int12_operand" "NOP")] - UNSPEC_MHDSETS))] - "TARGET_MEDIA_REV2" - "mhdsets %1, %0" - [(set_attr "length" "4") - (set_attr "type" "mset")]) - -(define_insn "mhdseth" - [(set (match_operand:SI 0 "fpr_operand" "=f") - (unspec:SI [(match_operand:SI 1 "fpr_operand" "0") - (match_operand:SI 2 "int5_operand" "I")] - UNSPEC_MHDSETH))] - "TARGET_MEDIA_REV2" - "mhdseth %2, %0" - [(set_attr "length" "4") - (set_attr "type" "mset")]) diff --git a/gcc/config/frv/frvbegin.c b/gcc/config/frv/frvbegin.c deleted file mode 100644 index a5f5b1fa93e..00000000000 --- a/gcc/config/frv/frvbegin.c +++ /dev/null @@ -1,150 +0,0 @@ -/* Frv initialization file linked before all user modules - Copyright (C) 1999, 2000 Free Software Foundation, Inc. - Contributed by Red Hat, 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 was originally taken from the file crtstuff.c in the - main compiler directory, and simplified. */ - -#include "defaults.h" -#include -#include "unwind-dw2-fde.h" -#include "gbl-ctors.h" - -/* Declare a pointer to void function type. */ -#define STATIC static - -#ifdef __FRV_UNDERSCORE__ -#define UNDERSCORE "_" -#else -#define UNDERSCORE "" -#endif - -#define INIT_SECTION_NEG_ONE(SECTION, FLAGS, NAME) \ -__asm__ (".section " SECTION "," FLAGS "\n\t" \ - ".globl " UNDERSCORE NAME "\n\t" \ - ".type " UNDERSCORE NAME ",@object\n\t" \ - ".p2align 2\n" \ - UNDERSCORE NAME ":\n\t" \ - ".word -1\n\t" \ - ".previous") - -#define INIT_SECTION(SECTION, FLAGS, NAME) \ -__asm__ (".section " SECTION "," FLAGS "\n\t" \ - ".globl " UNDERSCORE NAME "\n\t" \ - ".type " UNDERSCORE NAME ",@object\n\t" \ - ".p2align 2\n" \ - UNDERSCORE NAME ":\n\t" \ - ".previous") - -/* Beginning of .ctor/.dtor sections that provides a list of constructors and - destructors to run. */ - -INIT_SECTION_NEG_ONE (".ctors", "\"aw\"", "__CTOR_LIST__"); -INIT_SECTION_NEG_ONE (".dtors", "\"aw\"", "__DTOR_LIST__"); - -/* Beginning of .eh_frame section that provides all of the exception handling - tables. */ - -INIT_SECTION (".eh_frame", "\"aw\"", "__EH_FRAME_BEGIN__"); - -/* Beginning of .rofixup section that provides a list of pointers that we - need to adjust. */ - -INIT_SECTION (".rofixup", "\"a\"", "__ROFIXUP_LIST__"); - -extern void __frv_register_eh(void) __attribute__((__constructor__)); -extern void __frv_deregister_eh(void) __attribute__((__destructor__)); - -extern func_ptr __EH_FRAME_BEGIN__[]; - -/* Register the exeception handling table as the first constructor */ -void -__frv_register_eh (void) -{ - static struct object object; - if (__register_frame_info) - __register_frame_info (__EH_FRAME_BEGIN__, &object); -} - -/* Note, do not declare __{,de}register_frame_info weak as it seems - to interfere with the pic support. */ - -/* Unregister the exeception handling table as a deconstructor */ -void -__frv_deregister_eh (void) -{ - static int completed = 0; - - if (completed) - return; - - if (__deregister_frame_info) - __deregister_frame_info (__EH_FRAME_BEGIN__); - - completed = 1; -} - -/* Run the global destructors */ -void -__do_global_dtors () -{ - static func_ptr *p = __DTOR_LIST__ + 1; - while (*p) - { - p++; - (*(p-1)) (); - } -} - -/* Run the global constructors */ -void -__do_global_ctors () -{ - unsigned long nptrs = (unsigned long) __CTOR_LIST__[0]; - unsigned i; - - if (nptrs == (unsigned long)-1) - for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++); - - for (i = nptrs; i >= 1; i--) - __CTOR_LIST__[i] (); - - atexit (__do_global_dtors); -} - -/* Subroutine called automatically by `main'. - Compiling a global function named `main' - produces an automatic call to this function at the beginning. - - For many systems, this routine calls __do_global_ctors. - For systems which support a .init section we use the .init section - to run __do_global_ctors, so we need not do anything here. */ - -void -__main () -{ - /* Support recursive calls to `main': run initializers just once. */ - static int initialized; - if (! initialized) - { - initialized = 1; - __do_global_ctors (); - } -} diff --git a/gcc/config/frv/frvend.c b/gcc/config/frv/frvend.c deleted file mode 100644 index f1635cc1049..00000000000 --- a/gcc/config/frv/frvend.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Frv initialization file linked after all user modules - Copyright (C) 1999, 2000 Free Software Foundation, Inc. - Contributed by Red Hat, 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. */ - -#include "defaults.h" -#include -#include "unwind-dw2-fde.h" - -#ifdef __FRV_UNDERSCORE__ -#define UNDERSCORE "_" -#else -#define UNDERSCORE "" -#endif - -#define FINI_SECTION_ZERO(SECTION, FLAGS, NAME) \ -__asm__ (".section " SECTION "," FLAGS "\n\t" \ - ".globl " UNDERSCORE NAME "\n\t" \ - ".type " UNDERSCORE NAME ",@object\n\t" \ - ".p2align 2\n" \ - UNDERSCORE NAME ":\n\t" \ - ".word 0\n\t" \ - ".previous") - -#define FINI_SECTION(SECTION, FLAGS, NAME) \ -__asm__ (".section " SECTION "," FLAGS "\n\t" \ - ".globl " UNDERSCORE NAME "\n\t" \ - ".type " UNDERSCORE NAME ",@object\n\t" \ - ".p2align 2\n" \ - UNDERSCORE NAME ":\n\t" \ - ".previous") - -/* End of .ctor/.dtor sections that provides a list of constructors and - destructors to run. */ - -FINI_SECTION_ZERO (".ctors", "\"aw\"", "__CTOR_END__"); -FINI_SECTION_ZERO (".dtors", "\"aw\"", "__DTOR_END__"); - -/* End of .eh_frame section that provides all of the exception handling - tables. */ - -FINI_SECTION_ZERO (".eh_frame", "\"aw\"", "__FRAME_END__"); - -/* End of .rofixup section that provides a list of pointers that we - need to adjust. */ - -FINI_SECTION (".rofixup", "\"a\"", "__ROFIXUP_END__"); diff --git a/gcc/config/frv/lib1funcs.asm b/gcc/config/frv/lib1funcs.asm deleted file mode 100644 index 18a814235e0..00000000000 --- a/gcc/config/frv/lib1funcs.asm +++ /dev/null @@ -1,275 +0,0 @@ -/* Library functions. - Copyright (C) 2000 Free Software Foundation, Inc. - Contributed by Red Hat, 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. */ - -#include - - -#ifdef L_cmpll -/* icc0 = __cmpll (long long a, long long b) */ - - .file "_cmpll.s" - .globl EXT(__cmpll) - .type EXT(__cmpll),@function - .text - .p2align 4 -EXT(__cmpll): - cmp gr8, gr10, icc0 - ckeq icc0, cc4 - P(ccmp) gr9, gr11, cc4, 1 - ret -.Lend: - .size EXT(__cmpll),.Lend-EXT(__cmpll) -#endif /* L_cmpll */ - -#ifdef L_cmpf -/* icc0 = __cmpf (float a, float b) */ -/* Note, because this function returns the result in ICC0, it means it can't - handle NaNs. */ - - .file "_cmpf.s" - .globl EXT(__cmpf) - .type EXT(__cmpf),@function - .text - .p2align 4 -EXT(__cmpf): -#ifdef __FRV_HARD_FLOAT__ /* floating point instructions available */ - movgf gr8, fr0 - P(movgf) gr9, fr1 - setlos #1, gr8 - fcmps fr0, fr1, fcc0 - P(fcklt) fcc0, cc0 - fckeq fcc0, cc1 - csub gr0, gr8, gr8, cc0, 1 - cmov gr0, gr8, cc1, 1 - cmpi gr8, 0, icc0 - ret -#else /* no floating point instructions available */ - movsg lr, gr4 - addi sp, #-16, sp - sti gr4, @(sp, 8) - st fp, @(sp, gr0) - mov sp, fp - call EXT(__cmpsf2) - cmpi gr8, #0, icc0 - ldi @(sp, 8), gr4 - movgs gr4, lr - ld @(sp,gr0), fp - addi sp, #16, sp - ret -#endif -.Lend: - .size EXT(__cmpf),.Lend-EXT(__cmpf) -#endif - -#ifdef L_cmpd -/* icc0 = __cmpd (double a, double b) */ -/* Note, because this function returns the result in ICC0, it means it can't - handle NaNs. */ - - .file "_cmpd.s" - .globl EXT(__cmpd) - .type EXT(__cmpd),@function - .text - .p2align 4 -EXT(__cmpd): - movsg lr, gr4 - addi sp, #-16, sp - sti gr4, @(sp, 8) - st fp, @(sp, gr0) - mov sp, fp - call EXT(__cmpdf2) - cmpi gr8, #0, icc0 - ldi @(sp, 8), gr4 - movgs gr4, lr - ld @(sp,gr0), fp - addi sp, #16, sp - ret -.Lend: - .size EXT(__cmpd),.Lend-EXT(__cmpd) -#endif - -#ifdef L_addll -/* gr8,gr9 = __addll (long long a, long long b) */ -/* Note, gcc will never call this function, but it is present in case an - ABI program calls it. */ - - .file "_addll.s" - .globl EXT(__addll) - .type EXT(__addll),@function - .text - .p2align -EXT(__addll): - addcc gr9, gr11, gr9, icc0 - addx gr8, gr10, gr8, icc0 - ret -.Lend: - .size EXT(__addll),.Lend-EXT(__addll) -#endif - -#ifdef L_subll -/* gr8,gr9 = __subll (long long a, long long b) */ -/* Note, gcc will never call this function, but it is present in case an - ABI program calls it. */ - - .file "_subll.s" - .globl EXT(__subll) - .type EXT(__subll),@function - .text - .p2align 4 -EXT(__subll): - subcc gr9, gr11, gr9, icc0 - subx gr8, gr10, gr8, icc0 - ret -.Lend: - .size EXT(__subll),.Lend-EXT(__subll) -#endif - -#ifdef L_andll -/* gr8,gr9 = __andll (long long a, long long b) */ -/* Note, gcc will never call this function, but it is present in case an - ABI program calls it. */ - - .file "_andll.s" - .globl EXT(__andll) - .type EXT(__andll),@function - .text - .p2align 4 -EXT(__andll): - P(and) gr9, gr11, gr9 - P2(and) gr8, gr10, gr8 - ret -.Lend: - .size EXT(__andll),.Lend-EXT(__andll) -#endif - -#ifdef L_orll -/* gr8,gr9 = __orll (long long a, long long b) */ -/* Note, gcc will never call this function, but it is present in case an - ABI program calls it. */ - - .file "_orll.s" - .globl EXT(__orll) - .type EXT(__orll),@function - .text - .p2align 4 -EXT(__orll): - P(or) gr9, gr11, gr9 - P2(or) gr8, gr10, gr8 - ret -.Lend: - .size EXT(__orll),.Lend-EXT(__orll) -#endif - -#ifdef L_xorll -/* gr8,gr9 = __xorll (long long a, long long b) */ -/* Note, gcc will never call this function, but it is present in case an - ABI program calls it. */ - - .file "_xorll.s" - .globl EXT(__xorll) - .type EXT(__xorll),@function - .text - .p2align 4 -EXT(__xorll): - P(xor) gr9, gr11, gr9 - P2(xor) gr8, gr10, gr8 - ret -.Lend: - .size EXT(__xorll),.Lend-EXT(__xorll) -#endif - -#ifdef L_notll -/* gr8,gr9 = __notll (long long a) */ -/* Note, gcc will never call this function, but it is present in case an - ABI program calls it. */ - - .file "_notll.s" - .globl EXT(__notll) - .type EXT(__notll),@function - .text - .p2align 4 -EXT(__notll): - P(not) gr9, gr9 - P2(not) gr8, gr8 - ret -.Lend: - .size EXT(__notll),.Lend-EXT(__notll) -#endif - -#ifdef L_cmov -/* (void) __cmov (char *dest, const char *src, size_t len) */ -/* - * void __cmov (char *dest, const char *src, size_t len) - * { - * size_t i; - * - * if (dest < src || dest > src+len) - * { - * for (i = 0; i < len; i++) - * dest[i] = src[i]; - * } - * else - * { - * while (len-- > 0) - * dest[len] = src[len]; - * } - * } - */ - - .file "_cmov.s" - .globl EXT(__cmov) - .type EXT(__cmov),@function - .text - .p2align 4 -EXT(__cmov): - P(cmp) gr8, gr9, icc0 - add gr9, gr10, gr4 - P(cmp) gr8, gr4, icc1 - bc icc0, 0, .Lfwd - bls icc1, 0, .Lback -.Lfwd: - /* move bytes in a forward direction */ - P(setlos) #0, gr5 - cmp gr0, gr10, icc0 - P(subi) gr9, #1, gr9 - P2(subi) gr8, #1, gr8 - bnc icc0, 0, .Lret -.Lfloop: - /* forward byte move loop */ - addi gr5, #1, gr5 - P(ldsb) @(gr9, gr5), gr4 - cmp gr5, gr10, icc0 - P(stb) gr4, @(gr8, gr5) - bc icc0, 0, .Lfloop - ret -.Lbloop: - /* backward byte move loop body */ - ldsb @(gr9,gr10),gr4 - stb gr4,@(gr8,gr10) -.Lback: - P(cmpi) gr10, #0, icc0 - addi gr10, #-1, gr10 - bne icc0, 0, .Lbloop -.Lret: - ret -.Lend: - .size EXT(__cmov),.Lend-EXT(__cmov) -#endif diff --git a/gcc/config/frv/modi.c b/gcc/config/frv/modi.c deleted file mode 100644 index d5a91fc0f55..00000000000 --- a/gcc/config/frv/modi.c +++ /dev/null @@ -1,4 +0,0 @@ -int __modi (int a, int b) -{ - return a % b; -} diff --git a/gcc/config/frv/t-frv b/gcc/config/frv/t-frv deleted file mode 100644 index a92f63bb8da..00000000000 --- a/gcc/config/frv/t-frv +++ /dev/null @@ -1,93 +0,0 @@ -# Name of assembly file containing libgcc1 functions. -# This entry must be present, but it can be empty if the target does -# not need any assembler functions to support its code generation. -# -# Alternatively if assembler functions *are* needed then define the -# entries below: -CROSS_LIBGCC1 = libgcc1-asm.a -LIB1ASMSRC = frv/lib1funcs.asm -LIB1ASMFUNCS = _cmpll _cmpf _cmpd _addll _subll _andll _orll _xorll _notll _cmov -LIB2FUNCS_EXTRA = cmovh.c cmovw.c cmovd.c modi.c umodi.c uitof.c uitod.c ulltof.c ulltod.c - -# We want fine grained libraries, so use the new code to build the -# floating point emulation libraries. -FPBIT = fp-bit.c -DPBIT = dp-bit.c - -# If any special flags are necessary when building libgcc2 put them here. -TARGET_LIBGCC2_CFLAGS = - -fp-bit.c: $(srcdir)/config/fp-bit.c - echo '#define FLOAT' > fp-bit.c - echo '#include "frv/frv-abi.h"' >> fp-bit.c - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - -dp-bit.c: $(srcdir)/config/fp-bit.c - echo '#include "frv/frv-abi.h"' > dp-bit.c - cat $(srcdir)/config/fp-bit.c >> dp-bit.c - -cmovh.c: $(srcdir)/config/frv/cmovh.c - $(LN_S) $(srcdir)/config/frv/cmovh.c . - -cmovw.c: $(srcdir)/config/frv/cmovw.c - $(LN_S) $(srcdir)/config/frv/cmovw.c . - -cmovd.c: $(srcdir)/config/frv/cmovd.c - $(LN_S) $(srcdir)/config/frv/cmovd.c . - -modi.c: $(srcdir)/config/frv/modi.c - $(LN_S) $(srcdir)/config/frv/modi.c . - -umodi.c: $(srcdir)/config/frv/umodi.c - $(LN_S) $(srcdir)/config/frv/umodi.c . - -uitof.c: $(srcdir)/config/frv/uitof.c - $(LN_S) $(srcdir)/config/frv/uitof.c . - -uitod.c: $(srcdir)/config/frv/uitod.c - $(LN_S) $(srcdir)/config/frv/uitod.c . - -ulltof.c: $(srcdir)/config/frv/ulltof.c - $(LN_S) $(srcdir)/config/frv/ulltof.c . - -ulltod.c: $(srcdir)/config/frv/ulltod.c - $(LN_S) $(srcdir)/config/frv/ulltod.c . - -# Build frvbegin.o and frvend.o -EXTRA_MULTILIB_PARTS=frvbegin.o frvend.o - -# Compile two additional files that are linked with every program -# linked using GCC on systems using COFF or ELF, for the sake of C++ -# constructors. - -FRVSTUFF_CFLAGS = $(TARGET_LIBGCC2_CFLAGS) - -$(T)frvbegin$(objext): $(srcdir)/config/frv/frvbegin.c $(GCC_PASSES) \ - $(CONFIG_H) defaults.h unwind-dw2-fde.h gbl-ctors.h - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) $(FRVSTUFF_CFLAGS) \ - -c $(srcdir)/config/frv/frvbegin.c -o $(T)frvbegin$(objext) - -$(T)frvend$(objext): $(srcdir)/config/frv/frvend.c $(GCC_PASSES) \ - $(CONFIG_H) defaults.h unwind-dw2-fde.h gbl-ctors.h - $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) $(FRVSTUFF_CFLAGS) \ - -c $(srcdir)/config/frv/frvend.c -o $(T)frvend$(objext) - -# Enable the following if multilibs are needed. -# See gcc/genmultilib, gcc/gcc.texi and gcc/tm.texi for a -# description of the options and their values. -# -#MULTILIB_OPTIONS = mcpu=fr500/mcpu=tomcat/mcpu=simple/mcpu=frv msoft-float mdword/mno-dword -#MULTILIB_DIRNAMES = fr500 tomcat simple frv nof dw no-dw -#MULTILIB_MATCHES = mcpu?simple=mcpu?fr300 mno-double=mcpu?fr500 mcpu?frv=mdouble -#MULTILIB_EXCEPTIONS = *mcpu=simple/*msoft-float* *mcpu=frv/*msoft-float* -#MULTILIB_EXTRA_OPTS = mlibrary-pic - -MULTILIB_OPTIONS = mcpu=frv/mcpu=fr400/mcpu=simple mno-pack mlibrary-pic -MULTILIB_DIRNAMES = frv fr400 simple unpacked pic -MULTILIB_MATCHES = mcpu?simple=mcpu?fr300 mlibrary-pic=fpic mlibrary-pic=fPIC -MULTILIB_EXCEPTIONS = mcpu=frv/mno-pack* mcpu=simple/mno-pack* - -LIBGCC = stmp-multilib -INSTALL_LIBGCC = install-multilib - -EXTRA_HEADERS = $(srcdir)/config/frv/frv-asm.h $(srcdir)/config/frv/media.h diff --git a/gcc/config/frv/uitod.c b/gcc/config/frv/uitod.c deleted file mode 100644 index 14290ab6b04..00000000000 --- a/gcc/config/frv/uitod.c +++ /dev/null @@ -1,4 +0,0 @@ -double __uitod (unsigned int a) -{ - return a; -} diff --git a/gcc/config/frv/uitof.c b/gcc/config/frv/uitof.c deleted file mode 100644 index 059bc7c7417..00000000000 --- a/gcc/config/frv/uitof.c +++ /dev/null @@ -1,4 +0,0 @@ -float __uitof (unsigned int a) -{ - return a; -} diff --git a/gcc/config/frv/ulltod.c b/gcc/config/frv/ulltod.c deleted file mode 100644 index e6bee12081f..00000000000 --- a/gcc/config/frv/ulltod.c +++ /dev/null @@ -1,4 +0,0 @@ -double __ulltod (unsigned long long a) -{ - return a; -} diff --git a/gcc/config/frv/ulltof.c b/gcc/config/frv/ulltof.c deleted file mode 100644 index 29cdfd4d2a1..00000000000 --- a/gcc/config/frv/ulltof.c +++ /dev/null @@ -1,4 +0,0 @@ -float __ulltof (unsigned long long a) -{ - return a; -} diff --git a/gcc/config/frv/umodi.c b/gcc/config/frv/umodi.c deleted file mode 100644 index 4ffe5ad8132..00000000000 --- a/gcc/config/frv/umodi.c +++ /dev/null @@ -1,4 +0,0 @@ -unsigned int __umodi (unsigned int a, unsigned int b) -{ - return a % b; -} diff --git a/gcc/config/frv/xm-frv.h b/gcc/config/frv/xm-frv.h deleted file mode 100644 index 8f2ed66ccfc..00000000000 --- a/gcc/config/frv/xm-frv.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Definitions for Frv target - Copyright (C) 1999 Free Software Foundation, Inc. - Contributed by Red Hat, 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 - -/* 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 - -/* target machine dependencies. - tm.h is a symbolic link to the actual target specific file. */ -#include "tm.h" - -/* end of xm-frv.h */ diff --git a/gcc/config/i386/scodbx.h b/gcc/config/i386/scodbx.h deleted file mode 100644 index 7da93053256..00000000000 --- a/gcc/config/i386/scodbx.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Definitions for Intel 386 running SCO Unix System V, - using dbx-in-coff encapsulation. - Copyright (C) 1992, 1995, 1996, 1999 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. */ - -#include "i386/svr3dbx.h" - -/* Overridden defines for SCO systems from sco.h. */ - -/* By default, target has a 80387, uses IEEE compatible arithmetic, - and returns float values in the 387, ie, - (TARGET_80387 | TARGET_FLOAT_RETURNS_IN_80387) - - SCO's software emulation of a 387 fails to handle the `fucomp' - opcode. fucomp is only used when generating IEEE compliant code. - So don't make TARGET_IEEE_FP default for SCO. */ - -#undef TARGET_SUBTARGET_DEFAULT -#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS) - -/* Use crt1.o as a startup file and crtn.o as a closing file. */ - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{!r:%{!z:svr3.ifile%s}%{z:svr3z.ifile%s}}\ - %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}" - -/* Library spec, including SCO international language support. */ - -#undef LIB_SPEC -#define LIB_SPEC \ - "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} %{scointl:libintl.a%s} -lc" - -/* Specify predefined symbols in preprocessor. */ - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem=svr3" - -#undef CPP_SPEC -#define CPP_SPEC "%(cpp_cpu) %{scointl:-DM_INTERNAT}" - -/* This spec is used for telling cpp whether char is signed or not. */ - -#undef SIGNED_CHAR_SPEC -#if DEFAULT_SIGNED_CHAR -#define SIGNED_CHAR_SPEC \ - "%{funsigned-char:-D__CHAR_UNSIGNED__ -D_CHAR_UNSIGNED}" -#else -#define SIGNED_CHAR_SPEC \ - "%{!fsigned-char:-D__CHAR_UNSIGNED__ -D_CHAR_UNSIGNED}" -#endif - -/* caller has to pop the extra argument passed to functions that return - structures. */ - -#undef RETURN_POPS_ARGS -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE ? 0 \ - : (TARGET_RTD \ - && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ - || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ - == void_type_node))) ? (SIZE) \ - : 0) -/* On other 386 systems, the last line looks like this: - : (aggregate_value_p (TREE_TYPE (FUNTYPE))) ? GET_MODE_SIZE (Pmode) : 0) */ - -/* Handle #pragma pack. */ -#define HANDLE_SYSV_PRAGMA diff --git a/gcc/config/i386/xm-dgux.h b/gcc/config/i386/xm-dgux.h deleted file mode 100644 index 881c5c7be9d..00000000000 --- a/gcc/config/i386/xm-dgux.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Configuration for GCC for Intel i386 running DG/ux */ - -/* looks just like sysv4 for now */ -#include "xm-svr4.h" diff --git a/gcc/config/i386/xm-sun.h b/gcc/config/i386/xm-sun.h deleted file mode 100644 index 6c0f0a25630..00000000000 --- a/gcc/config/i386/xm-sun.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Configuration for GNU C-compiler for Intel 80386 running SunOS 4.0. - Copyright (C) 1988, 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. */ - -#define USG diff --git a/gcc/config/i386/xm-sysv3.h b/gcc/config/i386/xm-sysv3.h deleted file mode 100644 index 9a655443ff5..00000000000 --- a/gcc/config/i386/xm-sysv3.h +++ /dev/null @@ -1,3 +0,0 @@ -/* Configuration for GCC for Intel i386 running System V Release 3. */ - -#include "xm-svr3.h" diff --git a/gcc/config/ip2k/crt0.S b/gcc/config/ip2k/crt0.S deleted file mode 100644 index 131ccb6ec6e..00000000000 --- a/gcc/config/ip2k/crt0.S +++ /dev/null @@ -1,53 +0,0 @@ -; -; Copyright (C) 2000, 2001 Free Software Foundation, Inc. -; Contributed by Red Hat, Inc. -; -; This file is part of GNU CC. -; -; GNU CC is free software; you can redistribute it and/or modify -; it under the terms of the GNU General Public License as published by -; the Free Software Foundation; either version 2, or (at your option) -; any later version. -; -; In addition to the permissions in the GNU General Public License, the -; Free Software Foundation gives you unlimited permission to link the -; compiled version of this file 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.) -; -; 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. -; - - .file "crt0.S" - .text - .global __start - .func __start -__start: - clr $ff ; Insure we have a zero available - mov w,#%hi8data(__stack) ; set up stack - mov sph,w ; - mov w,#%lo8data(__stack) - mov spl,w - - push #0 ; Set argc/argv. - push #0 ; Only required for testing - push #0 ; purposes and "ansi" main. - push #0 - page _main - call _main - push $81 ; use return value to call exit() - push $80 - page _exit - call _exit - break ; Should never return - .endfunc diff --git a/gcc/config/ip2k/ip2k-protos.h b/gcc/config/ip2k/ip2k-protos.h deleted file mode 100644 index 2ec040007a1..00000000000 --- a/gcc/config/ip2k/ip2k-protos.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. - Contributed by Red Hat, Inc and Ubicom, 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. */ - -extern void asm_file_start PARAMS ((FILE *)); -extern void asm_file_end PARAMS ((FILE *)); - -extern void function_prologue PARAMS ((FILE *, HOST_WIDE_INT)); -extern void function_epilogue PARAMS ((FILE *, HOST_WIDE_INT)); -extern int find_one_set_bit_p PARAMS ((HOST_WIDE_INT)); -extern int find_one_clear_bit_p PARAMS ((HOST_WIDE_INT)); - -#ifdef TREE_CODE -extern void unique_section PARAMS ((tree, int)); -extern void encode_section_info PARAMS ((tree, int)); -extern void asm_output_section_name PARAMS ((FILE *, tree, const char *, - int)); -extern int valid_machine_type_attribute PARAMS ((tree, tree, tree, tree)); -extern int valid_machine_decl_attribute PARAMS ((tree, tree, tree, tree)); -extern int ip2k_return_pops_args PARAMS ((tree, tree, int)); -#endif /* TREE_CODE */ - -#ifdef RTX_CODE -extern int legitimate_address_p PARAMS ((enum machine_mode, rtx, int)); -extern void machine_dependent_reorg PARAMS ((rtx)); -extern int ip2k_address_cost PARAMS ((rtx)); -extern int ip2k_extra_constraint PARAMS ((rtx, int)); -extern rtx legitimize_address PARAMS ((rtx, rtx, enum machine_mode, rtx)); -extern int adjust_insn_length PARAMS ((rtx insn, int len)); -extern int default_rtx_costs PARAMS ((rtx, enum rtx_code, enum rtx_code)); -extern void asm_output_char PARAMS ((FILE *, rtx)); -extern void asm_output_short PARAMS ((FILE *, rtx)); -extern void asm_output_byte PARAMS ((FILE *, int)); -extern void print_operand PARAMS ((FILE *, rtx, int)); -extern void print_operand_address PARAMS ((FILE *, rtx)); -extern int ip2k_jump_mode PARAMS ((rtx, rtx)); -extern void ip2k_split_words PARAMS ((enum machine_mode, enum machine_mode, - rtx *)); -extern rtx ip2k_get_low_half PARAMS ((rtx, enum machine_mode)); -extern rtx ip2k_get_high_half PARAMS ((rtx, enum machine_mode)); -extern int ip2k_nonptr_operand PARAMS ((rtx, enum machine_mode)); -extern int ip2k_ptr_operand PARAMS ((rtx, enum machine_mode)); -extern int ip2k_ip_operand PARAMS ((rtx, enum machine_mode)); -extern int ip2k_short_operand PARAMS ((rtx, enum machine_mode)); -extern int ip2k_gen_operand PARAMS ((rtx, enum machine_mode)); -extern int ip2k_nonsp_reg_operand PARAMS ((rtx, enum machine_mode)); -extern int ip2k_symbol_ref_operand PARAMS ((rtx, enum machine_mode)); -extern const char *ip2k_set_compare PARAMS ((rtx, rtx)); -extern const char *ip2k_gen_sCOND PARAMS ((rtx, enum rtx_code, rtx)); -extern const char *ip2k_gen_signed_comp_branch PARAMS ((rtx, - enum rtx_code, - rtx)); -extern const char *ip2k_gen_unsigned_comp_branch PARAMS ((rtx, - enum rtx_code, - rtx)); -extern int is_regfile_address PARAMS ((rtx)); -extern int ip2k_mode_dependent_address PARAMS ((rtx)); -extern int ip2k_address_uses_reg_p PARAMS ((rtx, unsigned int)); -extern int ip2k_xexp_not_uses_reg_p PARAMS ((rtx, unsigned int, int)); -extern int ip2k_composite_xexp_not_uses_reg_p PARAMS ((rtx, unsigned int, int)); -extern int ip2k_composite_xexp_not_uses_cc0_p PARAMS ((rtx)); -extern int ip2k_signed_comparison_operator PARAMS ((rtx, - enum machine_mode)); -extern int ip2k_unsigned_comparison_operator PARAMS ((rtx, - enum machine_mode)); -extern int ip2k_unary_operator PARAMS ((rtx, enum machine_mode)); -extern int ip2k_binary_operator PARAMS ((rtx, enum machine_mode)); - -extern rtx ip2k_compare_operands[3]; -#endif /* RTX_CODE */ - -#ifdef HAVE_MACHINE_MODES -extern int class_max_nregs PARAMS ((enum reg_class, enum machine_mode)); -extern enum reg_class class_likely_spilled_p PARAMS ((int c)); -#endif /* HAVE_MACHINE_MODES */ - -#ifdef REAL_VALUE_TYPE -extern void asm_output_float PARAMS ((FILE *, REAL_VALUE_TYPE)); -#endif - -extern int ip2k_init_elim_offset PARAMS ((int, int)); -extern void ip2k_init_local_alloc PARAMS ((int *)); - diff --git a/gcc/config/ip2k/ip2k.c b/gcc/config/ip2k/ip2k.c deleted file mode 100644 index 6d715289e3e..00000000000 --- a/gcc/config/ip2k/ip2k.c +++ /dev/null @@ -1,6255 +0,0 @@ -/* Subroutines used for code generation on Ubicom IP2022 - Communications Controller. - Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. - Contributed by Red Hat, Inc and Ubicom, 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. */ - -#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 "insn-addr.h" -#include "flags.h" -#include "reload.h" -#include "tree.h" -#include "expr.h" -#include "toplev.h" -#include "obstack.h" -#include "function.h" -#include "recog.h" -#include "tm_p.h" -#include "target.h" -#include "target-def.h" -#include "basic-block.h" - -/* There are problems with 'frame_pointer_needed'. If we force it - on, we either end up not eliminating uses of FP, which results in - SPILL register failures or we may end up with calculation errors in - the stack offsets. Isolate the decision process into a simple macro. */ -#define CHAIN_FRAMES (frame_pointer_needed || FRAME_POINTER_REQUIRED) - -static int ip2k_naked_function_p PARAMS ((tree)); -#ifdef IP2K_MD_REORG_PASS -static void mdr_resequence_xy_yx PARAMS ((rtx)); -static void mdr_pres_replace_and_recurse PARAMS ((rtx, rtx, rtx)); -static void mdr_propagate_reg_equivs_sequence PARAMS ((rtx, rtx, rtx)); -static void mdr_propagate_reg_equivs PARAMS ((rtx)); -static int track_dp_reload PARAMS ((rtx , rtx *, int , int)); -static void mdr_try_dp_reload_elim PARAMS ((rtx)); -static void mdr_try_move_dp_reload PARAMS ((rtx)); -static void mdr_try_move_pushes PARAMS ((rtx)); -static void mdr_try_propagate_clr_sequence PARAMS ((rtx, unsigned int)); -static void mdr_try_propagate_clr PARAMS ((rtx)); -static void mdr_try_propagate_move_sequence PARAMS ((rtx, rtx, rtx)); -static void mdr_try_propagate_move PARAMS ((rtx)); -static void mdr_try_remove_redundant_insns PARAMS ((rtx)); -static int track_w_reload PARAMS ((rtx, rtx *, int , int)); -static void mdr_try_wreg_elim PARAMS ((rtx)); -#endif /* IP2K_MD_REORG_PASS */ -static int ip2k_check_can_adjust_stack_ref PARAMS ((rtx, int)); -static void ip2k_adjust_stack_ref PARAMS ((rtx *, int)); -static int ip2k_xexp_not_uses_reg_for_mem PARAMS ((rtx, unsigned int)); - - -/* Initialize the GCC target structure. */ -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" - -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE function_prologue - -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE function_epilogue - -#undef TARGET_ASM_UNIQUE_SECTION -#define TARGET_ASM_UNIQUE_SECTION unique_section - -#undef TARGET_ENCODE_SECTION_INFO -#define TARGET_ENCODE_SECTION_INFO encode_section_info - -struct gcc_target targetm = TARGET_INITIALIZER; - -/* Commands in the functions prologues in the compiled file. */ -static int commands_in_prologues; - -/* Commands in the functions epilogues in the compiled file. */ -static int commands_in_epilogues; - -/* Prologue/Epilogue size in words. */ -static int prologue_size; -static int epilogue_size; - -/* compare and test instructions for the IP2K are materialized by - the conditional branch that uses them. This is because conditional - branches are skips over unconditional branches. */ -rtx ip2k_compare_operands[3]; /* Additional operands for condition code. */ -int ip2k_test_flag; /* Indicates Z, WREG contain condition code - information. */ - -/* Some ip2k patterns push a byte onto the stack and then access - SP-relative addresses. Since reload doesn't know about these - pushes, we must track them internally with a %< (push) or %> (pop) - indicator. */ -static int ip2k_stack_delta; - -/* Track if or how far our ip2k reorganization pass has run. */ -int ip2k_reorg_in_progress = 0; -int ip2k_reorg_completed = 0; -int ip2k_reorg_split_dimode = 0; -int ip2k_reorg_split_simode = 0; -int ip2k_reorg_split_himode = 0; -int ip2k_reorg_split_qimode = 0; -int ip2k_reorg_merge_qimode = 0; - -/* Set up local allocation order. */ - -void -ip2k_init_local_alloc (rao) - int * rao; -{ - static const int alloc_order[] = REG_ALLOC_ORDER; - - memcpy (rao, alloc_order, sizeof (alloc_order)); -} - -/* Returns 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. */ - -int -ip2k_return_pops_args (fundecl, funtype, size) - tree fundecl ATTRIBUTE_UNUSED; - tree funtype; - int size; -{ - if (TREE_CODE (funtype) == IDENTIFIER_NODE) - return size; - - if (TYPE_ARG_TYPES (funtype) == NULL_TREE - || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node)) - return size; - - return 0; -} - -/* Return non-zero if FUNC is a naked function. */ - -static int -ip2k_naked_function_p (func) - tree func; -{ - tree a; - - if (TREE_CODE (func) != FUNCTION_DECL) - abort (); - - a = lookup_attribute ("naked", DECL_ATTRIBUTES (func)); - return a != NULL_TREE; -} - -/* Output function prologue. */ -void -function_prologue (file, size) - FILE *file; - HOST_WIDE_INT size; -{ - int leaf_func_p; - int main_p; - int reg; - rtx operands[2]; - - prologue_size = epilogue_size = 0; - - if (ip2k_naked_function_p (current_function_decl)) - { - fprintf (file, "/* prologue: naked */\n"); - return; - } - - leaf_func_p = leaf_function_p (); - main_p = ! strcmp ("main", current_function_name); - - /* For now, we compute all these facts about the function, but don't - take any action based on the information. */ - - prologue_size = 0; - fprintf (file, "/* prologue: frame size=%d */\n", size); - - /* Unless we're a leaf we need to save the return PC. */ - - if (! leaf_func_p) - { - OUT_AS1 (push, calll); - OUT_AS1 (push, callh); - prologue_size += 4; - } - - /* We need to save the old FP and set the new FP pointing at the - stack location where the old one is saved. Note that because of - post-decrement addressing, the SP is off-by-one after the - push, so we harvest the SP address BEFORE we push the MSBs of - the FP. */ - if (CHAIN_FRAMES) - { - OUT_AS1 (push, REG_FP+1); /* Save old LSBs. */ - OUT_AS2 (mov, w, spl); - OUT_AS2 (mov, REG_FP+1, w); /* SPL -> FPL */ - - OUT_AS2 (mov, w, sph); /* Freeze SP MSBs */ - OUT_AS1 (push, REG_FP); /* Save old MSBs */ - OUT_AS2 (mov, REG_FP, w); /* SPH -> FPH */ - prologue_size += 12; - } - - for (reg = (CHAIN_FRAMES) ? (REG_FP - 1) : (REG_FP + 1); - reg > 0; --reg) - { - if (regs_ever_live[reg] && ! call_used_regs[reg]) - { - fprintf (file, "\t" AS1 (push,%s) "\n", reg_names[reg]); - prologue_size += 2; - } - } - - if (size) - { - operands[0] = GEN_INT (size); - - switch (size & 0xff) - { - case 0: - break; - case 1: - OUT_AS1 (dec, spl); - prologue_size += 2; - break; - default: - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, spl, w); - prologue_size += 4; - } - - switch (size & 0xff00) - { - case 0: - break; - case 0x100: - OUT_AS1 (dec, sph); - prologue_size += 2; - break; - default: - if ((size & 0xff) != ((size >> 8) & 0xff)) - OUT_AS2 (mov, w, %H0); /* Otherwise W has value we want. */ - OUT_AS2 (sub, sph, w); - prologue_size += 4; - } - } - -/* XXX - change this to use the carry-propagating subtract trick. */ - if (flag_stack_check) - { - OUT_AS2 (mov, w, sph); - OUT_AS2 (cmp, w, #%%hi8data(_end)); - OUT_AS1 (sc, ); /* C == 0 -> hi8(edata) < sph */ - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (sz, ); /* Z == 1 -> look at low byte */ - OUT_AS1 (page,0f); - OUT_AS1 (jmp,0f); /* sp < edata, so raise stack fault */ - OUT_AS2 (mov, w, spl); - OUT_AS2 (cmp, w, #%%lo8data(_end)); - OUT_AS1 (sc,); /* C==1 -> lo8(edata) >= spl */ - OUT_AS1 (page,1f); - OUT_AS1 (jmp,1f); - OUT_AS1 (0:,); - output_asm_insn ("push\t$ff", operands); - OUT_AS1 (system,); - OUT_AS1 (1:, ); - prologue_size += 30; - } -} - -/* Output function epilogue. */ -void -function_epilogue (file, size) - FILE *file; - HOST_WIDE_INT size; -{ - int leaf_func_p; - int reg,savelimit; - rtx operands[2]; /* Dummy used by OUT_ASn */ - int need_ret = 1; - - /* Use this opportunity to reset the reorg flags! */ - ip2k_reorg_in_progress = 0; - ip2k_reorg_completed = 0; - ip2k_reorg_split_dimode = 0; - ip2k_reorg_split_simode = 0; - ip2k_reorg_split_himode = 0; - ip2k_reorg_split_qimode = 0; - ip2k_reorg_merge_qimode = 0; - - if (ip2k_naked_function_p (current_function_decl)) - { - fprintf (file, "/* epilogue: naked */\n"); - return; - } - - leaf_func_p = leaf_function_p (); - epilogue_size = 0; - fprintf (file, "/* epilogue: frame size=%d */\n", size); - - if (size) - { - operands[0] = GEN_INT (size); - - switch (size & 0xff) - { - default: - OUT_AS2 (mov, w, %L0); - OUT_AS2 (add, spl, w); - epilogue_size += 4; - /* fall-thru */ - case 0: - break; - case 1: - OUT_AS1 (inc, spl); - epilogue_size += 2; - } - - switch (size & 0xff00) - { - default: - if ((size & 0xff) != ((size >> 8) & 0xff)) - OUT_AS2 (mov, w, %H0); - OUT_AS2 (add, sph, w); - epilogue_size += 4; - /* fall-thru */ - case 0: - break; - case 1: - OUT_AS1 (inc, sph); - epilogue_size += 2; - } - } - - savelimit = (CHAIN_FRAMES) ? REG_FP : (REG_FP + 2); - - for (reg = 0; reg < savelimit; reg++) - { - if (regs_ever_live[reg] && ! call_used_regs[reg]) - { - fprintf (file, "\t" AS1 (pop,%s) "\n", reg_names[reg]); - prologue_size += 2; - } - } - - if (CHAIN_FRAMES - && ! (current_function_pops_args - && current_function_args_size >= 2 - && current_function_args_size < 0x100)) - { - OUT_AS1 (pop, REG_FP); - OUT_AS1 (pop, REG_FP+1); - epilogue_size += 4; - } - - if (! leaf_func_p) - { - if (current_function_pops_args - && current_function_args_size >= 2 - && current_function_args_size < 0x100) - { - if (current_function_args_size == 2) - { - if (CHAIN_FRAMES) - { - OUT_AS1 (page, __fp_pop2_args_ret); - OUT_AS1 (jmp, __fp_pop2_args_ret); - } - else - { - OUT_AS1 (page, __pop2_args_ret); - OUT_AS1 (jmp, __pop2_args_ret); - } - epilogue_size += 4; - } - else - { - operands[0] = GEN_INT (current_function_args_size); - OUT_AS2 (mov, w, %L0); - if (CHAIN_FRAMES) - { - OUT_AS1 (page, __fp_pop_args_ret); - OUT_AS1 (jmp, __fp_pop_args_ret); - } - else - { - OUT_AS1 (page, __pop_args_ret); - OUT_AS1 (jmp, __pop_args_ret); - } - epilogue_size += 6; - } - need_ret = 0; - } - else - { - OUT_AS1 (pop, callh); - OUT_AS1 (pop, calll); - epilogue_size += 4; - } - } - else - { - if (current_function_pops_args - && current_function_args_size >= 2 - && current_function_args_size < 0x100) - { - if (current_function_args_size == 2) - { - if (CHAIN_FRAMES) - { - OUT_AS1 (page, __leaf_fp_pop2_args_ret); - OUT_AS1 (jmp, __leaf_fp_pop2_args_ret); - epilogue_size += 4; - need_ret = 0; - } - } - else - { - operands[0] = GEN_INT (current_function_args_size); - if (CHAIN_FRAMES) - { - OUT_AS2 (mov, w, %L0); - OUT_AS1 (page, __leaf_fp_pop_args_ret); - OUT_AS1 (jmp, __leaf_fp_pop_args_ret); - epilogue_size += 6; - need_ret = 0; - } - } - } - } - - if (current_function_pops_args && current_function_args_size - && need_ret) - { - operands[0] = GEN_INT (current_function_args_size); - - switch (current_function_args_size & 0xff) - { - default: - OUT_AS2 (mov, w, %L0); - OUT_AS2 (add, spl, w); - epilogue_size += 4; - /* fall-thru */ - - case 0: - break; - - case 1: - OUT_AS1 (inc, spl); - epilogue_size += 2; - } - - switch (current_function_args_size & 0xff00) - { - default: - if ((current_function_args_size & 0xff) - != ((current_function_args_size >> 8) & 0xff)) - OUT_AS2 (mov, w, %H0); - OUT_AS2 (add, sph, w); - epilogue_size += 4; - /* fall-thru */ - - case 0: - break; - - case 1: - OUT_AS1 (inc, sph); - epilogue_size += 2; - } - } - - if (need_ret) - { - OUT_AS1 (ret,); - epilogue_size += 2; - } - - fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size); - commands_in_prologues += prologue_size; - commands_in_epilogues += epilogue_size; -} - -/* Return the difference between the registers after the function - prologue. - - Stack Frame grows down: - - ARGUMENTS - <------ AP ($102:$103) - RETURN PC (unless leaf function) - SAVEDFP (if needed) - <------ FP [HARD_FRAME_POINTER] ($FD:$FE) - SAVED REGS - <------ VFP [$100:$101] - STACK ALLOCATION - <------ SP ($6:$7) */ -int -ip2k_init_elim_offset (from, to) - int from; - int to; -{ - int leaf_func_p = leaf_function_p (); - int no_saved_pc = leaf_func_p - || ip2k_naked_function_p (current_function_decl); - int offset; - int reg; - int reglimit; - - if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) - return get_frame_size () + 1; - - if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) - return (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2); - - /* Count all the registers we had to preserve. */ - - reglimit = CHAIN_FRAMES ? REG_FP : (REG_FP + 2); - for (offset = 0,reg = 0; reg < reglimit; ++reg) - { - if ((regs_ever_live[reg] && ! call_used_regs[reg])) - { - ++offset; - } - } - - if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) - return -offset; - - if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) - /* Add in the stack-local variables. */ - return offset + get_frame_size () + 1; - - if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) - /* Add stack-locals plus saved FP and PC. */ - return offset + get_frame_size () + 1 - + (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2); - - abort (); /* Unanticipated elimination. */ -} - -/* Return nonzero if X (an RTX) is a legitimate memory address on the target - machine for a memory operand of mode MODE. */ - -int -legitimate_address_p (mode, x, strict) - enum machine_mode mode; - rtx x; - int strict; -{ - int off; - - if (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - switch (GET_CODE (x)) - { - case REG: - /* IP allows indirection without offset - only okay if - we don't require access to multiple bytes. */ - if (REGNO (x) == REG_IP) - return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0; - - /* We can indirect thru DP or SP register. */ - if (strict ? REG_OK_FOR_BASE_STRICT_P (x) - : REG_OK_FOR_BASE_NOSTRICT_P (x)) - return 'S'; - break; - - case PLUS: - /* Offsets from DP or SP are legal in the range 0..127 */ - { - rtx op1, op2; - - op1 = XEXP (x, 0); - op2 = XEXP (x, 1); - - if (REG_P (op2) && ! REG_P (op1)) - { - rtx tmp = op1; - op1 = op2; - op2 = tmp; - } - - /* Don't let anything but R+I thru.. */ - if (! REG_P (op1) - || REG_P (op2) - || GET_CODE (op2) != CONST_INT) - return 0; - - switch (REGNO (op1)) - { - case REG_DP: /* only 0..127 displacement */ - case REG_SP: - off = 2 * GET_MODE_SIZE (mode); - if (! off) - off = 1; - - if (INTVAL (op2) < 0 || INTVAL (op2) > (128 - off)) - return 0; /* Positive must be small enough that after - splitting all pieces are addressed. */ - return 'S'; /* Safe displacement. */ - - case REG_IP: - if (GET_MODE_SIZE (mode) <= 1 && INTVAL (op2) == 0) - return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0; - return 0; - - case REG_AP: - case REG_FP: - case REG_VFP: - default: - if (strict || ! REG_OK_FOR_BASE_NOSTRICT_P (op1)) - return 0; /* Allow until reload. */ - - return 'S'; - } - } - break; - - case CONST: - case SYMBOL_REF: - /* We always allow references to things in code space. */ - return is_regfile_address (x) ? 0 : 'C'; - - case LABEL_REF: - return 'L'; - - default: - return 0; - } - - return 0; -} - -/* Is ADDR mode dependent? */ -int -ip2k_mode_dependent_address (addr) - rtx addr; -{ - switch (GET_CODE (addr)) - { - case POST_INC: - case POST_DEC: - case PRE_INC: - case PRE_DEC: - return 1; - - case REG: - return (REGNO (addr) == REG_IP); /* Can't do IP displaced addresses. */ - - default: - return 0; /* Assume no dependency. */ - } -} - -/* Attempts to replace X with a valid - memory address for an operand of mode MODE. */ - -rtx -legitimize_address (x, oldx, mode, scratch) - rtx x; - rtx oldx ATTRIBUTE_UNUSED; - rtx scratch; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx reg; - - /* You might think that we could split up a symbolic address by - adding the HIGH 8 bits and doing a displacement off the dp. But - because we only have 7 bits of offset, that doesn't actually - help. So only constant displacements are likely to obtain an - advantage. */ - - if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) - && GET_CODE (XEXP (x, 1)) == CONST_INT - && ! CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'K')) - { - int offset = INTVAL (XEXP (x, 1)); - - reg = scratch ? scratch : gen_reg_rtx (Pmode); - - emit_insn (gen_rtx_SET (VOIDmode, reg, - gen_rtx_PLUS (Pmode, XEXP (x, 0), - GEN_INT (offset & 0xffc0)))); - x = gen_rtx_PLUS (Pmode, reg, GEN_INT (offset & 0x3f)); - } - - return x; /* We don't have any other tricks. */ -} - -/* Determine if X is a 'data' address or a code address. All static - data and stack variables reside in data memory. Only code is believed - to be in PRAM or FLASH. */ -int -is_regfile_address (x) - rtx x; -{ - while (1) - switch (GET_CODE (x)) - { - case SYMBOL_REF: - return ! SYMBOL_REF_FLAG (x); /* Declared as function. */ - case CONST: - case PLUS: - x = XEXP (x, 0); - break; - case CONST_INT: - case REG: - case SUBREG: - return 1; - case LABEL_REF: - return 0; - default: - return 0; - } - - return 0; -} - -/* Output ADDR to FILE as address. */ - -void -print_operand_address (file, addr) - FILE *file; - rtx addr; -{ - switch (GET_CODE (addr)) - { - case SUBREG: - addr = alter_subreg (&addr); - /* fall-thru */ - - case REG: - fprintf (file, "(%s)", - REGNO (addr) == REG_DP ? "DP" - : REGNO (addr) == REG_SP ? "SP" - : REGNO (addr) == REG_IP ? "IP" - : REGNO (addr) == REG_VFP ? "VFP" /* Should never see this */ - : REGNO (addr) == REG_AP ? "AP" /* or this, either. */ - : reg_names[REGNO (addr)]); - break; - - case PRE_DEC: - case POST_INC: - abort (); - break; - - case CONST: - addr = XEXP (addr, 0); - print_operand_address (file, XEXP (addr, 0)); - fprintf (file, "+"); - print_operand_address (file, XEXP (addr, 1)); - return; - - case LO_SUM: - if (is_regfile_address (XEXP (addr, 1))) - fprintf (file, "%%lo8data("); - else - fprintf (file, "%%lo8insn("); - print_operand_address (file, XEXP (addr, 1)); - fprintf (file, ")"); - print_operand_address (file, XEXP (addr, 0)); - break; - - case PLUS: /* Ought to be stack or dp references. */ - if (XEXP (addr, 1) == const0_rtx - && GET_CODE (XEXP (addr, 0)) == PLUS) - { - print_operand_address (file, XEXP (addr, 0)); - return; - } - - if (! REG_P (XEXP (addr, 0)) || REGNO (XEXP (addr, 0)) != REG_IP) - print_operand_address (file, XEXP (addr, 1)); /* const */ - print_operand_address (file, XEXP (addr, 0)); /* (reg) */ - break; - - case HIGH: - if (is_regfile_address (XEXP (addr, 0))) - fprintf (file, "%%hi8data("); - else - fprintf (file, "%%hi8insn("); - output_addr_const (file, XEXP (addr, 0)); - fprintf (file, ")"); - break; - - default: - output_addr_const (file, addr); - } -} - - -/* Output X as assembler operand to file FILE. */ - -void -print_operand (file, x, code) - FILE *file; - rtx x; - int code; -{ - int abcd = 0; - unsigned long value; - - switch (code) - { - case '<': /* Push */ - ip2k_stack_delta++; - return; - - case '>': /* Pop */ - ip2k_stack_delta--; - return; - - case 'A': - case 'B': - case 'C': - case 'D': - abcd = code - 'A'; - break; - - case 'H': - abcd = 0; - break; - - case 'L': - abcd = 1; - break; - - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': - abcd = code - 'S'; - - default: - break; - } - - if (ip2k_short_operand (x, GET_MODE (x)) - && ip2k_address_uses_reg_p (x, REG_SP)) - /* An SP-relative address needs to account for interior stack - pushes that reload didn't know about when it calculated the - stack offset. */ - abcd += ip2k_stack_delta; - - switch (GET_CODE (x)) - { - case SUBREG: - x = alter_subreg (&x); - /* fall-thru */ - - case REG: - fprintf (file, reg_names[true_regnum (x) + abcd]); - break; - - case CONST_INT: - switch (code) - { - case 'x': - fprintf (file, "$%x", INTVAL (x) & 0xffff); - break; - - case 'b': - fprintf (file, "%d", INTVAL (x)); /* bit selector */ - break; - - case 'e': /* "1 << n" - e.g. "exp" */ - fprintf (file, "#%d", 1 << INTVAL (x)); - break; - - case 'A': - case 'B': - case 'C': - case 'D': - value = INTVAL (x); - value >>= 8 * (3 - abcd); - value &= 0xff; - - fprintf (file, "#%ld", value); - break; - - case 'H': - fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff); - break; - - case 'L': - fprintf (file, "#%d", INTVAL (x) & 0xff); - break; - - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': - value = ((unsigned long long)INTVAL (x)) >> (8 * (7 - abcd)) & 0xff; - fprintf (file, "#%ld", value); - break; - - default: - fprintf (file, "#%d", INTVAL (x)); - } - break; - - case SYMBOL_REF: - case LABEL_REF: - case CODE_LABEL: - case CONST: - switch (code) - { - case 'A': - case 'B': - case 'C': - case 'D': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': - abort (); /* Probably an error. */ - break; - - case 'H': - fprintf (file, "#%s(", - is_regfile_address (x) ? "%hi8data" - : "%hi8insn"); - print_operand_address (file, x); - fputc (')', file); - break; - - case 'L': - fprintf (file, "#%s(", - is_regfile_address (x) ? "%lo8data" - : "%lo8insn"); - print_operand_address (file, x); - fputc (')', file); - break; - - default: - print_operand_address (file, x); - } - break; - - case MEM: - { - rtx addr = XEXP (x, 0); - - if (GET_CODE (addr) == SUBREG) - addr = alter_subreg (&x); - - if (CONSTANT_P (addr) && abcd) - { - fputc ('(', file); - print_operand_address (file, addr); - fprintf (file, ")+%d", abcd); - } - else if (abcd) - { - switch (GET_CODE (addr)) - { - case PLUS: - abcd += INTVAL (XEXP (addr, 1)); - - /* Worry about (plus (plus (reg DP) (const_int 10)) - (const_int 0)) */ - if (GET_CODE (XEXP (addr, 0)) == PLUS) - { - addr = XEXP (addr, 0); - abcd += INTVAL (XEXP (addr, 1)); - } - - fprintf (file, "%d", abcd); - print_operand_address (file, XEXP (addr, 0)); - break; - - case REG: - default: - fprintf (file, "%d", abcd); - print_operand_address (file, addr); - } - } - else if (GET_CODE (addr) == REG - && (REGNO (addr) == REG_DP || REGNO (addr) == REG_SP)) - { - fprintf (file, "0"); - print_operand_address (file, addr); - } - else - print_operand_address (file, addr); - } - break; - - case CONST_DOUBLE: - /* Is this an integer or a floating point value? */ - if (GET_MODE (x) == VOIDmode) - { - switch (code) - { - case 'S': - case 'T': - case 'U': - case 'V': - value = CONST_DOUBLE_HIGH (x); - value >>= 8 * (3 - abcd); - value &= 0xff; - - fprintf (file, "#%ld", value); - break; - - case 'W': - case 'X': - case 'Y': - case 'Z': - value = CONST_DOUBLE_LOW (x); - value >>= 8 * (7 - abcd); - value &= 0xff; - - fprintf (file, "#%ld", value); - break; - } - - } - else - { - REAL_VALUE_TYPE rv; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, value); - fprintf (file, "0x%lx", value); - } - break; - - default: - fatal_insn ("bad operand", x); - } -} - -/* Remember the operands for the compare. */ -const char * -ip2k_set_compare (x, y) - rtx x; - rtx y; -{ - ip2k_compare_operands[0] = x; - ip2k_compare_operands[1] = y; - return ""; -} - -/* Emit the code for sCOND instructions. */ -const char * -ip2k_gen_sCOND (insn, code, dest) - rtx insn ATTRIBUTE_UNUSED; - enum rtx_code code; - rtx dest; -{ -#define operands ip2k_compare_operands - enum machine_mode mode; - - operands[2] = dest; - - mode = GET_MODE (operands[0]); - if ((mode != QImode) && (mode != HImode) - && (mode != SImode) && (mode != DImode)) - mode = GET_MODE (operands[1]); - - /* We have a fast path for a specific type of QImode compare. We ought - to extend this for larger cases too but that wins less frequently and - introduces a lot of complexity. */ - if (mode == QImode - && !rtx_equal_p (operands[0], operands[2]) - && !rtx_equal_p (operands[1], operands[2]) - && (! REG_P (operands[2]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 1) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 1)))) - { - OUT_AS1 (clr, %2); - if (immediate_operand (operands[1], QImode) - && ((INTVAL (operands[1]) & 0xff) == 0xff)) - { - if (code == EQ) - OUT_AS2 (incsnz, w, %0); - else - OUT_AS2 (incsz, w, %0); - } - else if (immediate_operand (operands[1], QImode) - && ((INTVAL (operands[1]) & 0xff) == 0x01)) - { - if (code == EQ) - OUT_AS2 (decsnz, w, %0); - else - OUT_AS2 (decsz, w, %0); - } - else if (ip2k_compare_operands[1] == const0_rtx) - { - OUT_AS2 (mov, w, %0); - if (code == EQ) - OUT_AS1 (snz,); - else - OUT_AS1 (sz,); - } - else - { - OUT_AS2 (mov, w, %0); - if (code == EQ) - OUT_AS2 (csne, w, %1); - else - OUT_AS2 (cse, w, %1); - } - OUT_AS1 (inc, %2); - } - else - { - if (ip2k_compare_operands[1] == const0_rtx) - { - switch (mode) - { - case QImode: - OUT_AS2 (mov, w, %0); - break; - - case HImode: - OUT_AS2 (mov, w, %H0); - OUT_AS2 (or, w, %L0); - break; - - case SImode: - OUT_AS2 (mov, w, %A0); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); - break; - - case DImode: - OUT_AS2 (mov, w, %S0); - OUT_AS2 (or, w, %T0); - OUT_AS2 (or, w, %U0); - OUT_AS2 (or, w, %V0); - OUT_AS2 (or, w, %W0); - OUT_AS2 (or, w, %X0); - OUT_AS2 (or, w, %Y0); - OUT_AS2 (or, w, %Z0); - break; - - default: - abort (); - } - } - else - { - switch (mode) - { - case QImode: - OUT_AS2 (mov, w, %1); - OUT_AS2 (cmp, w, %0); - break; - - case HImode: - OUT_AS2 (mov, w, %H1); - OUT_AS2 (cmp, w, %H0); - OUT_AS1 (sz,); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %L1); - OUT_AS2 (cmp, w, %L0); - OUT_AS1 (2:,); - break; - - case SImode: - if (code == EQ) - { - OUT_AS2 (mov, w, #1); - OUT_AS2 (mov, mulh, w); - } - else - OUT_AS1 (clr, mulh); - OUT_AS2 (mov, w, %A1); - OUT_AS2 (cse, w, %A0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (cse, w, %B0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %C1); - OUT_AS2 (cse, w, %C0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %D1); - OUT_AS2 (cse, w, %D0); - OUT_AS1 (2:,); - if (code == EQ) - OUT_AS1 (dec, mulh); - else - OUT_AS1 (inc, mulh); - OUT_AS2 (mov, w, mulh); - OUT_AS2 (mov, %2, w); - return ""; - - case DImode: - if (code == EQ) - { - OUT_AS2 (mov, w, #1); - OUT_AS2 (mov, mulh, w); - } - else - OUT_AS1 (clr, mulh); - OUT_AS2 (mov, w, %S1); - OUT_AS2 (cse, w, %S0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (cse, w, %T0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %U1); - OUT_AS2 (cse, w, %U0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (cse, w, %V0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %W1); - OUT_AS2 (cse, w, %W0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (cse, w, %X0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %Y1); - OUT_AS2 (cse, w, %Y0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (cse, w, %Z0); - OUT_AS1 (2:,); - if (code == EQ) - OUT_AS1 (dec, mulh); - else - OUT_AS1 (inc, mulh); - OUT_AS2 (mov, w, mulh); - OUT_AS2 (mov, %2, w); - return ""; - - default: - abort (); - } - } - OUT_AS2 (mov, w, #0); - if (code == EQ) - OUT_AS1 (snz,); - else - OUT_AS1 (sz,); - OUT_AS1 (inc, wreg); - OUT_AS2 (mov, %2, w); - } - - return ""; -#undef operands -} - -const char * -ip2k_gen_signed_comp_branch (insn, code, label) - rtx insn; - enum rtx_code code; - rtx label; -{ -#define operands ip2k_compare_operands - enum machine_mode mode; - int can_use_skip = 0; - rtx ninsn; - - operands[2] = label; - - mode = GET_MODE (operands[0]); - if ((mode != QImode) && (mode != HImode) - && (mode != SImode) && (mode != DImode)) - mode = GET_MODE (operands[1]); - - /* Look for situations where we can just skip the next instruction instead - of skipping and then branching! */ - ninsn = next_real_insn (insn); - if (ninsn - && (recog_memoized (ninsn) >= 0) - && get_attr_skip (ninsn) == SKIP_YES) - { - rtx skip_tgt = next_nonnote_insn (next_real_insn (insn)); - - /* The first situation is where the target of the jump is one insn - after the jump insn and the insn being jumped is only one machine - opcode long. */ - if (label == skip_tgt) - can_use_skip = 1; - else - { - /* If our skip target is in fact a code label then we ignore the - label and move onto the next useful instruction. Nothing we do - here has any effect on the use of skipping instructions. */ - if (GET_CODE (skip_tgt) == CODE_LABEL) - skip_tgt = next_nonnote_insn (skip_tgt); - - /* The second situation is where we have something of the form: - - test_condition - skip_conditional - page/jump label - - optional_label (this may or may not exist): - skippable_insn - page/jump label - - In this case we can eliminate the first "page/jump label". */ - if (GET_CODE (skip_tgt) == JUMP_INSN) - { - rtx set = single_set (skip_tgt); - if (GET_CODE (XEXP (set, 0)) == PC - && GET_CODE (XEXP (set, 1)) == LABEL_REF - && label == JUMP_LABEL (skip_tgt)) - can_use_skip = 2; - } - } - } - - /* gcc is a little braindead and does some rather stateful things while - inspecting attributes - we have to put this state back to what it's - supposed to be. */ - extract_constrain_insn_cached (insn); - - if (ip2k_compare_operands[1] == const0_rtx) /* These are easier. */ - { - switch (code) - { - case LT: - if (can_use_skip) - { - OUT_AS2 (sb, %0, 7); - } - else - { - OUT_AS2 (snb, %0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GT: - switch (mode) - { - case DImode: - OUT_AS2 (rl, w, %S0); - OUT_AS2 (mov, w, %S0); - OUT_AS2 (or, w, %T0); - OUT_AS2 (or, w, %U0); - OUT_AS2 (or, w, %V0); - OUT_AS2 (or, w, %W0); - OUT_AS2 (or, w, %X0); - OUT_AS2 (or, w, %Y0); - OUT_AS2 (or, w, %Z0); - OUT_AS1 (snz, ); - OUT_AS2 (setb, status, 0); - OUT_AS2 (sb, status, 0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case SImode: - OUT_AS2 (rl, w, %A0); - OUT_AS2 (mov, w, %A0); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); - OUT_AS1 (snz, ); - OUT_AS2 (setb, status, 0); - OUT_AS2 (sb, status, 0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case HImode: - OUT_AS2 (rl, w, %H0); - OUT_AS2 (mov, w, %H0); - OUT_AS2 (or, w, %L0); - OUT_AS1 (snz, ); - OUT_AS2 (setb, status, 0); - OUT_AS2 (sb, status, 0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case QImode: - OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */ - OUT_AS1 (snz, ); - OUT_AS2 (setb, wreg, 7); - OUT_AS2 (sb, wreg, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - default: - abort (); - } - break; - - case LE: - switch (mode) - { - case DImode: - OUT_AS2 (mov, w, %S0); - OUT_AS2 (or, w, %T0); - OUT_AS2 (or, w, %U0); - OUT_AS2 (or, w, %V0); - OUT_AS2 (or, w, %W0); - OUT_AS2 (or, w, %X0); - OUT_AS2 (or, w, %Y0); - OUT_AS2 (or, w, %Z0); /* Z is correct. */ - OUT_AS1 (sz, ); - OUT_AS2 (snb, %S0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case SImode: - OUT_AS2 (mov, w, %A0); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); /* Z is correct. */ - OUT_AS1 (sz, ); - OUT_AS2 (snb, %A0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case HImode: - OUT_AS2 (mov, w, %H0); - OUT_AS2 (or, w, %L0); - OUT_AS1 (sz, ); - OUT_AS2 (snb, %H0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case QImode: - OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */ - OUT_AS1 (sz, ); - OUT_AS2 (snb, wreg, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - default: - abort (); - } - break; - - case GE: - if (can_use_skip) - { - OUT_AS2 (snb, %0, 7); - } - else - { - OUT_AS2 (sb, %0, 7); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - return ""; - } - - /* signed compares are out of line because we can't get - the hardware to compute the overflow for us. */ - - switch (mode) - { - case QImode: - OUT_AS1 (push, %1%<); - OUT_AS1 (push, %0%>); - OUT_AS1 (page, __cmpqi2); - OUT_AS1 (call, __cmpqi2); - break; - - case HImode: - OUT_AS1 (push, %L1%<); - OUT_AS1 (push, %H1%<); - OUT_AS1 (push, %L0%<); - OUT_AS1 (push, %H0%>%>%>); - OUT_AS1 (page, __cmphi2); - OUT_AS1 (call, __cmphi2); - break; - - case SImode: - OUT_AS1 (push, %D1%<); - OUT_AS1 (push, %C1%<); - OUT_AS1 (push, %B1%<); - OUT_AS1 (push, %A1%<); - OUT_AS1 (push, %D0%<); - OUT_AS1 (push, %C0%<); - OUT_AS1 (push, %B0%<); - OUT_AS1 (push, %A0%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpsi2); - OUT_AS1 (call, __cmpsi2); - break; - - case DImode: - if (GET_CODE (operands[0]) == MEM - && true_regnum (XEXP (operands[0], 0)) == REG_DP) - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2_dp); - OUT_AS1 (call, __cmpdi2_dp); - } - else - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%<); - OUT_AS1 (push, %Z0%<); - OUT_AS1 (push, %Y0%<); - OUT_AS1 (push, %X0%<); - OUT_AS1 (push, %W0%<); - OUT_AS1 (push, %V0%<); - OUT_AS1 (push, %U0%<); - OUT_AS1 (push, %T0%<); - OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2); - OUT_AS1 (call, __cmpdi2); - } - break; - - default: - abort (); - } - - switch (code) - { - case LT: - if (can_use_skip) - { - OUT_AS2 (cse, w, #0); - } - else - { - OUT_AS2 (csne, w, #0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GT: - if (can_use_skip) - { - OUT_AS2 (cse, w, #2); - } - else - { - OUT_AS2 (csne, w, #2); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LE: - if (can_use_skip) - { - OUT_AS2 (snb, wreg, 1); - } - else - { - OUT_AS2 (sb, wreg, 1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GE: - if (can_use_skip) - { - OUT_AS2 (csne, w, #0); - } - else - { - OUT_AS2 (cse, w, #0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - return ""; -#undef operands -} - -const char * -ip2k_gen_unsigned_comp_branch (insn, code, label) - rtx insn; - enum rtx_code code; - rtx label; -{ -#define operands ip2k_compare_operands - enum machine_mode mode; - int imm_sub = 0; - int imm_cmp = 0; - int can_use_skip = 0; - rtx ninsn; - HOST_WIDE_INT const_low; - HOST_WIDE_INT const_high; - - operands[2] = label; - - mode = GET_MODE (operands[0]); - if ((mode != QImode) && (mode != HImode) && (mode != SImode) - && (mode != DImode)) - { - mode = GET_MODE (operands[1]); - } - - /* Look for situations where we can just skip the next instruction instead - of skipping and then branching! */ - ninsn = next_real_insn (insn); - if (ninsn - && (recog_memoized (ninsn) >= 0) - && get_attr_skip (ninsn) == SKIP_YES) - { - rtx skip_tgt = next_nonnote_insn (next_real_insn (insn)); - - /* The first situation is where the target of the jump is one insn - after the jump insn and the insn being jumped is only one machine - opcode long. */ - if (label == skip_tgt) - can_use_skip = 1; - else - { - /* If our skip target is in fact a code label then we ignore the - label and move onto the next useful instruction. Nothing we do - here has any effect on the use of skipping instructions. */ - if (GET_CODE (skip_tgt) == CODE_LABEL) - skip_tgt = next_nonnote_insn (skip_tgt); - - /* The second situation is where we have something of the form: - - test_condition - skip_conditional - page/jump label - - optional_label (this may or may not exist): - skippable_insn - page/jump label - - In this case we can eliminate the first "page/jump label". */ - if (GET_CODE (skip_tgt) == JUMP_INSN) - { - rtx set = single_set (skip_tgt); - if (GET_CODE (XEXP (set, 0)) == PC - && GET_CODE (XEXP (set, 1)) == LABEL_REF - && label == JUMP_LABEL (skip_tgt)) - can_use_skip = 2; - } - } - } - - /* gcc is a little braindead and does some rather stateful things while - inspecting attributes - we have to put this state back to what it's - supposed to be. */ - extract_constrain_insn_cached (insn); - - if (ip2k_compare_operands[1] == const0_rtx) - { - switch (code) - { - case LEU: - code = EQ; /* Nothing is LTU 0. */ - goto zero; - - case GTU: - code = NE; /* Anything non-zero is GTU. */ - /* fall-thru */ - - case EQ: - case NE: /* Test all the bits, result in - Z AND WREG. */ - zero: - switch (mode) - { - case DImode: - OUT_AS2 (mov, w, %S0); - OUT_AS2 (or, w, %T0); - OUT_AS2 (or, w, %U0); - OUT_AS2 (or, w, %V0); - OUT_AS2 (or, w, %W0); - OUT_AS2 (or, w, %X0); - OUT_AS2 (or, w, %Y0); - OUT_AS2 (or, w, %Z0); - break; - - case SImode: - OUT_AS2 (mov, w, %A0); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); - break; - - case HImode: - OUT_AS2 (mov, w, %H0); - OUT_AS2 (or, w, %L0); - break; - - case QImode: - OUT_AS2 (mov, w, %0); - break; - - default: - abort (); - } - - if (can_use_skip) - { - if (code == EQ) - OUT_AS1 (sz, ); - else - OUT_AS1 (snz, ); - } - else - { - if (code == EQ) - OUT_AS1 (snz,); - else - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GEU: - /* Always succeed. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case LTU: - /* Always fail. */ - break; - - default: - abort (); - } - return ""; - } - - /* Look at whether we have a constant as one of our operands. If we do - and it's in the position that we use to subtract from during our - normal optimized comparison concept then we have to shuffle things - around! */ - if (mode != QImode) - { - if ((immediate_operand (operands[1], GET_MODE (operands[1])) - && ((code == LEU) || (code == GTU))) - || (immediate_operand (operands[0], GET_MODE (operands[0])) - && ((code == LTU) || (code == GEU)))) - { - imm_sub = 1; - } - } - - /* Same as above - look if we have a constant that we can compare - for equality or non-equality. If we know this then we can look - for common value eliminations. Note that we want to ensure that - any immediate value is operand 1 to simplify the code later! */ - if ((code == EQ) || (code == NE)) - { - imm_cmp = immediate_operand (operands[1], GET_MODE (operands[1])); - if (! imm_cmp) - { - imm_cmp = immediate_operand (operands[0], GET_MODE (operands[0])); - if (imm_cmp) - { - rtx tmp = operands[1]; - operands[1] = operands[0]; - operands[0] = tmp; - } - } - } - - switch (mode) - { - case QImode: - switch (code) - { - case EQ: - if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff)) - OUT_AS2 (incsnz, w, %0); - else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01)) - OUT_AS2 (decsnz, w, %0); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (csne, w, %0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case NE: - if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff)) - OUT_AS2 (incsz, w, %0); - else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01)) - OUT_AS2 (decsz, w, %0); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (cse, w, %0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case GTU: - OUT_AS2 (mov, w, %0); - OUT_AS2 (cmp, w, %1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case GEU: - OUT_AS2 (mov, w, %1); - OUT_AS2 (cmp, w, %0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case LTU: - OUT_AS2 (mov, w, %1); - OUT_AS2 (cmp, w, %0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - case LEU: - OUT_AS2 (mov, w, %0); - OUT_AS2 (cmp, w, %1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - - default: - abort (); - } - break; - - case HImode: - switch (code) - { - case EQ: - { - unsigned char h = 0, l = 1; - - if (imm_cmp) - { - h = (INTVAL (operands[1]) >> 8) & 0xff; - l = INTVAL (operands[1]) & 0xff; - - if ((h == 0xff) && (l == 0xff)) - { - /* We should be able to do the following, but the - IP2k simulator doesn't like it and we get a load - of failures in gcc-c-torture. */ - OUT_AS2 (incsnz, w, %L0); - OUT_AS2 (incsz, w, %H0); -/* OUT_AS1 (skip,); Should have this */ - OUT_AS1 (page, 1f);/* Shouldn't need this! */ - OUT_AS1 (jmp, 1f); /* Shouldn't need this either. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS1 (1:,); - break; - } - else if (h == 0) - { - if (l == 1) - OUT_AS2 (dec, w, %L0); - else - { - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, w, %L1); - } - OUT_AS2 (or, w, %H0); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - else if (l == 0) - { - if (h == 1) - OUT_AS2 (dec, w, %H0); - else - { - OUT_AS2 (mov, w, %H0); - OUT_AS2 (sub, w, %H1); - } - OUT_AS2 (or, w, %L0); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - } - - OUT_AS2 (mov, w, %H1); - OUT_AS2 (cse, w, %H0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - if (! imm_cmp || (h != l)) - OUT_AS2 (mov, w, %L1); - OUT_AS2 (csne, w, %L0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS1 (2:,); - } - break; - - case NE: - { - unsigned char h = 0, l = 1; - - if (imm_cmp) - { - h = (INTVAL (operands[1]) >> 8) & 0xff; - l = INTVAL (operands[1]) & 0xff; - - if ((h == 0xff) && (l == 0xff)) - { - OUT_AS2 (incsnz, w, %L0); - OUT_AS2 (incsz, w, %H0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - else if (h == 0) - { - if (l == 1) - OUT_AS2 (dec, w, %L0); - else - { - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, w, %L1); - } - OUT_AS2 (or, w, %H0); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - else if (l == 0) - { - if (h == 1) - OUT_AS2 (dec, w, %H0); - else - { - OUT_AS2 (mov, w, %H0); - OUT_AS2 (sub, w, %H1); - } - OUT_AS2 (or, w, %L0); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - break; - } - } - - OUT_AS2 (mov, w, %H1); - if (imm_cmp && (h == l)) - { - OUT_AS2 (csne, w, %H0); - OUT_AS2 (cse, w, %L0); - } - else - { - OUT_AS2 (cse, w, %H0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %L1); - OUT_AS2 (cse, w, %L0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GTU: - if (imm_sub) - { - /* > 0xffff never suceeds! */ - if ((INTVAL (operands[1]) & 0xffff) != 0xffff) - { - operands[3] = GEN_INT (INTVAL (operands[1]) + 1); - OUT_AS2 (mov, w, %L3); - OUT_AS2 (sub, w, %L0); - OUT_AS2 (mov, w, %H3); - OUT_AS2 (subc, w, %H0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, w, %L1); - OUT_AS2 (mov, w, %H0); - OUT_AS2 (subc, w, %H1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GEU: - if (imm_sub) - { - if (INTVAL (operands[0]) == 0) - { - OUT_AS2 (mov, w, %H1); - OUT_AS2 (or, w, %L1); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[0]) - 1); - OUT_AS2 (mov, w, %L3); - OUT_AS2 (sub, w, %L1); - OUT_AS2 (mov, w, %H3); - OUT_AS2 (subc, w, %H1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %L1); - OUT_AS2 (sub, w, %L0); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (subc, w, %H0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LTU: - if (imm_sub) - { - if (INTVAL (operands[0]) == 0) - { - OUT_AS2 (mov, w, %H1); - OUT_AS2 (or, w, %L1); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[0]) - 1); - OUT_AS2 (mov, w, %L3); - OUT_AS2 (sub, w, %L1); - OUT_AS2 (mov, w, %H3); - OUT_AS2 (subc, w, %H1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %L1); - OUT_AS2 (sub, w, %L0); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (subc, w, %H0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LEU: - if (imm_sub) - { - if ((INTVAL (operands[1]) & 0xffff) == 0xffff) - { - /* <= 0xffff always suceeds. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[1]) + 1); - OUT_AS2 (mov, w, %L3); - OUT_AS2 (sub, w, %L0); - OUT_AS2 (mov, w, %H3); - OUT_AS2 (subc, w, %H0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %L0); - OUT_AS2 (sub, w, %L1); - OUT_AS2 (mov, w, %H0); - OUT_AS2 (subc, w, %H1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - break; - - case SImode: - switch (code) - { - case EQ: - { - unsigned char a = 0, b = 1, c = 2, d = 3; - - if (imm_cmp) - { - a = (INTVAL (operands[1]) >> 24) & 0xff; - b = (INTVAL (operands[1]) >> 16) & 0xff; - c = (INTVAL (operands[1]) >> 8) & 0xff; - d = INTVAL (operands[1]) & 0xff; - } - - OUT_AS2 (mov, w, %A1); - if (imm_cmp && (b == a)) - { - OUT_AS2 (csne, w, %A0); - OUT_AS2 (cse, w, %B0); - } - else - { - OUT_AS2 (cse, w, %A0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (cse, w, %B0); - } - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - if (! imm_cmp || (c != b)) - OUT_AS2 (mov, w, %C1); - OUT_AS2 (cse, w, %C0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - if (! imm_cmp || (d != c)) - OUT_AS2 (mov, w, %D1); - OUT_AS2 (csne, w, %D0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS1 (2:,); - } - break; - - case NE: - { - unsigned char a = 0, b = 1, c = 2, d = 3; - - if (imm_cmp) - { - a = (INTVAL (operands[1]) >> 24) & 0xff; - b = (INTVAL (operands[1]) >> 16) & 0xff; - c = (INTVAL (operands[1]) >> 8) & 0xff; - d = INTVAL (operands[1]) & 0xff; - } - - OUT_AS2 (mov, w, %A1); - if (imm_cmp && (b == a)) - { - OUT_AS2 (csne, w, %A0); - OUT_AS2 (cse, w, %B0); - } - else - { - OUT_AS2 (cse, w, %A0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (cse, w, %B0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - if (! imm_cmp || (c != b)) - OUT_AS2 (mov, w, %C1); - if (imm_cmp && (d == c)) - { - OUT_AS2 (csne, w, %C0); - OUT_AS2 (cse, w, %D0); - } - else - { - OUT_AS2 (cse, w, %C0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %D1); - OUT_AS2 (cse, w, %D0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GTU: - if (imm_sub) - { - /* > 0xffffffff never suceeds! */ - if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff) - != 0xffffffff) - { - operands[3] = GEN_INT (INTVAL (operands[1]) + 1); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %D0); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %C0); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %B0); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %A0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %D0); - OUT_AS2 (sub, w, %D1); - OUT_AS2 (mov, w, %C0); - OUT_AS2 (subc, w, %C1); - OUT_AS2 (mov, w, %B0); - OUT_AS2 (subc, w, %B1); - OUT_AS2 (mov, w, %A0); - OUT_AS2 (subc, w, %A1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GEU: - if (imm_sub) - { - if (INTVAL (operands[0]) == 0) - { - OUT_AS2 (mov, w, %A1); - OUT_AS2 (or, w, %B1); - OUT_AS2 (or, w, %C1); - OUT_AS2 (or, w, %D1); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[0]) - 1); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %D1); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %C1); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %B1); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %A1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %D1); - OUT_AS2 (sub, w, %D0); - OUT_AS2 (mov, w, %C1); - OUT_AS2 (subc, w, %C0); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (subc, w, %B0); - OUT_AS2 (mov, w, %A1); - OUT_AS2 (subc, w, %A0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LTU: - if (imm_sub) - { - if (INTVAL (operands[0]) == 0) - { - OUT_AS2 (mov, w, %A1); - OUT_AS2 (or, w, %B1); - OUT_AS2 (or, w, %C1); - OUT_AS2 (or, w, %D1); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[0]) - 1); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %D1); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %C1); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %B1); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %A1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %D1); - OUT_AS2 (sub, w, %D0); - OUT_AS2 (mov, w, %C1); - OUT_AS2 (subc, w, %C0); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (subc, w, %B0); - OUT_AS2 (mov, w, %A1); - OUT_AS2 (subc, w, %A0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LEU: - if (imm_sub) - { - if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff) - == 0xffffffff) - { - /* <= 0xffffffff always suceeds. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (INTVAL (operands[1]) + 1); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %D0); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %C0); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %B0); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %A0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %D0); - OUT_AS2 (sub, w, %D1); - OUT_AS2 (mov, w, %C0); - OUT_AS2 (subc, w, %C1); - OUT_AS2 (mov, w, %B0); - OUT_AS2 (subc, w, %B1); - OUT_AS2 (mov, w, %A0); - OUT_AS2 (subc, w, %A1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - break; - - case DImode: - if (GET_CODE (operands[1]) == CONST_INT) - { - const_low = INTVAL (operands[1]); - const_high = (const_low >= 0) - 1; - } - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - { - const_low = CONST_DOUBLE_LOW (operands[1]); - const_high = CONST_DOUBLE_HIGH (operands[1]); - } - switch (code) - { - case EQ: - { - unsigned char s = 0, t = 1, u = 2, v = 3; - unsigned char w = 4, x = 5, y = 6, z = 7; - if (optimize_size) - { - if (GET_CODE (operands[0]) == MEM - && true_regnum (XEXP (operands[0], 0)) == REG_DP) - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2_dp); - OUT_AS1 (call, __cmpdi2_dp); - OUT_AS2 (csne, w, #1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%<); - OUT_AS1 (push, %Z0%<); - OUT_AS1 (push, %Y0%<); - OUT_AS1 (push, %X0%<); - OUT_AS1 (push, %W0%<); - OUT_AS1 (push, %V0%<); - OUT_AS1 (push, %U0%<); - OUT_AS1 (push, %T0%<); - OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2); - OUT_AS1 (call, __cmpdi2); - OUT_AS2 (csne, w, #1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - if (imm_cmp) - { - s = (const_high >> 24) & 0xff; - t = (const_high >> 16) & 0xff; - u = (const_high >> 8) & 0xff; - v = const_high & 0xff; - w = (const_low >> 24) & 0xff; - x = (const_low >> 16) & 0xff; - y = (const_low >> 8) & 0xff; - z = const_low & 0xff; - } - - OUT_AS2 (mov, w, %S1); - if (imm_cmp && (s == t)) - { - OUT_AS2 (csne, w, %S0); - OUT_AS2 (cse, w, %T0); - } - else - { - OUT_AS2 (cse, w, %S0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (cse, w, %T0); - } - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - - OUT_AS2 (mov, w, %U1); - if (imm_cmp && (u == v)) - { - OUT_AS2 (csne, w, %U0); - OUT_AS2 (cse, w, %V0); - } - else - { - OUT_AS2 (cse, w, %U0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (cse, w, %V0); - } - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - - OUT_AS2 (mov, w, %W1); - if (imm_cmp && (w == x)) - { - OUT_AS2 (csne, w, %W0); - OUT_AS2 (cse, w, %X0); - } - else - { - OUT_AS2 (cse, w, %W0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (cse, w, %X0); - } - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - - if (! imm_cmp || (x != y)) - OUT_AS2 (mov, w, %Y1); - OUT_AS2 (cse, w, %Y0); - OUT_AS1 (page, 2f); - OUT_AS1 (jmp, 2f); - if (! imm_cmp || (z != y)) - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (csne, w, %Z0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS1 (2:,); - } - } - break; - - case NE: - { - unsigned char s = 0, t = 1, u = 2, v = 3; - unsigned char w = 4, x = 5, y = 6, z = 7; - - if (optimize_size) - { - if (GET_CODE (operands[0]) == MEM - && true_regnum (XEXP (operands[0], 0)) == REG_DP) - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2_dp); - OUT_AS1 (call, __cmpdi2_dp); - OUT_AS2 (cse, w, #1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%<); - OUT_AS1 (push, %Z0%<); - OUT_AS1 (push, %Y0%<); - OUT_AS1 (push, %X0%<); - OUT_AS1 (push, %W0%<); - OUT_AS1 (push, %V0%<); - OUT_AS1 (push, %U0%<); - OUT_AS1 (push, %T0%<); - OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>); - OUT_AS1 (page, __cmpdi2); - OUT_AS1 (call, __cmpdi2); - OUT_AS2 (cse, w, #1); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - if (imm_cmp) - { - s = (const_high >> 24) & 0xff; - t = (const_high >> 16) & 0xff; - u = (const_high >> 8) & 0xff; - v = const_high & 0xff; - w = (const_low >> 24) & 0xff; - x = (const_low >> 16) & 0xff; - y = (const_low >> 8) & 0xff; - z = const_low & 0xff; - } - - OUT_AS2 (mov, w, %S1); - if (imm_cmp && (s == t)) - { - OUT_AS2 (csne, w, %S0); - OUT_AS2 (cse, w, %T0); - } - else - { - OUT_AS2 (cse, w, %S0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (cse, w, %T0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - - OUT_AS2 (mov, w, %U1); - if (imm_cmp && (u == v)) - { - OUT_AS2 (csne, w, %U0); - OUT_AS2 (cse, w, %V0); - } - else - { - OUT_AS2 (cse, w, %U0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (cse, w, %V0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - - OUT_AS2 (mov, w, %W1); - if (imm_cmp && (w == x)) - { - OUT_AS2 (csne, w, %W0); - OUT_AS2 (cse, w, %X0); - } - else - { - OUT_AS2 (cse, w, %W0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (cse, w, %X0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - - if (! imm_cmp || (y != x)) - OUT_AS2 (mov, w, %Y1); - if (imm_cmp && (z == y)) - { - OUT_AS2 (csne, w, %Y0); - OUT_AS2 (cse, w, %Z0); - } - else - { - OUT_AS2 (cse, w, %Y0); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (cse, w, %Z0); - } - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - break; - - case GTU: - if (imm_sub) - { - /* > 0xffffffffffffffff never suceeds! */ - if (((const_high & 0xffffffff) != 0xffffffff) - || ((const_low & 0xffffffff) != 0xffffffff)) - { - operands[3] = GEN_INT (const_low + 1); - operands[4] = GEN_INT (const_high - + (INTVAL (operands[3]) ? 0 : 1)); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %Z0); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %Y0); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %X0); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %W0); - OUT_AS2 (mov, w, %D4); - OUT_AS2 (subc, w, %V0); - OUT_AS2 (mov, w, %C4); - OUT_AS2 (subc, w, %U0); - OUT_AS2 (mov, w, %B4); - OUT_AS2 (subc, w, %T0); - OUT_AS2 (mov, w, %A4); - OUT_AS2 (subc, w, %S0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %Z0); - OUT_AS2 (sub, w, %Z1); - OUT_AS2 (mov, w, %Y0); - OUT_AS2 (subc, w, %Y1); - OUT_AS2 (mov, w, %X0); - OUT_AS2 (subc, w, %X1); - OUT_AS2 (mov, w, %W0); - OUT_AS2 (subc, w, %W1); - OUT_AS2 (mov, w, %V0); - OUT_AS2 (subc, w, %V1); - OUT_AS2 (mov, w, %U0); - OUT_AS2 (subc, w, %U1); - OUT_AS2 (mov, w, %T0); - OUT_AS2 (subc, w, %T1); - OUT_AS2 (mov, w, %S0); - OUT_AS2 (subc, w, %S1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case GEU: - if (imm_sub) - { - HOST_WIDE_INT const_low0; - HOST_WIDE_INT const_high0; - - if (GET_CODE (operands[0]) == CONST_INT) - { - const_low0 = INTVAL (operands[0]); - const_high0 = (const_low >= 0) - 1; - } - else if (GET_CODE (operands[0]) == CONST_DOUBLE) - { - const_low0 = CONST_DOUBLE_LOW (operands[0]); - const_high0 = CONST_DOUBLE_HIGH (operands[0]); - } - - if (const_high0 == 0 && const_low0 == 0) - { - OUT_AS2 (mov, w, %S1); - OUT_AS2 (or, w, %T1); - OUT_AS2 (or, w, %U1); - OUT_AS2 (or, w, %V1); - OUT_AS2 (or, w, %W1); - OUT_AS2 (or, w, %X1); - OUT_AS2 (or, w, %Y1); - OUT_AS2 (or, w, %Z1); - OUT_AS1 (snz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (const_low0 - 1); - operands[4] = GEN_INT (const_high0 - (const_low0 ? 1 : 0)); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %Z1); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %Y1); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %X1); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %W1); - OUT_AS2 (mov, w, %D4); - OUT_AS2 (subc, w, %V1); - OUT_AS2 (mov, w, %C4); - OUT_AS2 (subc, w, %U1); - OUT_AS2 (mov, w, %B4); - OUT_AS2 (subc, w, %T1); - OUT_AS2 (mov, w, %A4); - OUT_AS2 (subc, w, %S1); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (sub, w, %Z0); - OUT_AS2 (mov, w, %Y1); - OUT_AS2 (subc, w, %Y0); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (subc, w, %X0); - OUT_AS2 (mov, w, %W1); - OUT_AS2 (subc, w, %W0); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (subc, w, %V0); - OUT_AS2 (mov, w, %U1); - OUT_AS2 (subc, w, %U0); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (subc, w, %T0); - OUT_AS2 (mov, w, %S1); - OUT_AS2 (subc, w, %S0); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LTU: - if (imm_sub) - { - HOST_WIDE_INT const_low0; - HOST_WIDE_INT const_high0; - - if (GET_CODE (operands[0]) == CONST_INT) - { - const_low0 = INTVAL (operands[0]); - const_high0 = (const_low >= 0) - 1; - } - else if (GET_CODE (operands[0]) == CONST_DOUBLE) - { - const_low0 = CONST_DOUBLE_LOW (operands[0]); - const_high0 = CONST_DOUBLE_HIGH (operands[0]); - } - - if (const_high0 == 0 && const_low0 == 0) - { - OUT_AS2 (mov, w, %S1); - OUT_AS2 (or, w, %T1); - OUT_AS2 (or, w, %U1); - OUT_AS2 (or, w, %V1); - OUT_AS2 (or, w, %W1); - OUT_AS2 (or, w, %X1); - OUT_AS2 (or, w, %Y1); - OUT_AS2 (or, w, %Z1); - OUT_AS1 (sz,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (const_low0 - 1); - operands[4] = GEN_INT (const_high0 - (const_low0 ? 1 : 0)); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %Z1); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %Y1); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %X1); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %W1); - OUT_AS2 (mov, w, %D4); - OUT_AS2 (subc, w, %V1); - OUT_AS2 (mov, w, %C4); - OUT_AS2 (subc, w, %U1); - OUT_AS2 (mov, w, %B4); - OUT_AS2 (subc, w, %T1); - OUT_AS2 (mov, w, %A4); - OUT_AS2 (subc, w, %S1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %Z1); - OUT_AS2 (sub, w, %Z0); - OUT_AS2 (mov, w, %Y1); - OUT_AS2 (subc, w, %Y0); - OUT_AS2 (mov, w, %X1); - OUT_AS2 (subc, w, %X0); - OUT_AS2 (mov, w, %W1); - OUT_AS2 (subc, w, %W0); - OUT_AS2 (mov, w, %V1); - OUT_AS2 (subc, w, %V0); - OUT_AS2 (mov, w, %U1); - OUT_AS2 (subc, w, %U0); - OUT_AS2 (mov, w, %T1); - OUT_AS2 (subc, w, %T0); - OUT_AS2 (mov, w, %S1); - OUT_AS2 (subc, w, %S0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - case LEU: - if (imm_sub) - { - if (((const_high & 0xffffffff) == 0xffffffff) - && ((const_low & 0xffffffff) == 0xffffffff)) - { - /* <= 0xffffffffffffffff always suceeds. */ - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - else - { - operands[3] = GEN_INT (const_low + 1); - operands[4] = GEN_INT (const_high - + (INTVAL (operands[3]) ? 0 : 1)); - OUT_AS2 (mov, w, %D3); - OUT_AS2 (sub, w, %Z0); - OUT_AS2 (mov, w, %C3); - OUT_AS2 (subc, w, %Y0); - OUT_AS2 (mov, w, %B3); - OUT_AS2 (subc, w, %X0); - OUT_AS2 (mov, w, %A3); - OUT_AS2 (subc, w, %W0); - OUT_AS2 (mov, w, %D4); - OUT_AS2 (subc, w, %V0); - OUT_AS2 (mov, w, %C4); - OUT_AS2 (subc, w, %U0); - OUT_AS2 (mov, w, %B4); - OUT_AS2 (subc, w, %T0); - OUT_AS2 (mov, w, %A4); - OUT_AS2 (subc, w, %S0); - OUT_AS1 (sc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - } - else - { - OUT_AS2 (mov, w, %Z0); - OUT_AS2 (sub, w, %Z1); - OUT_AS2 (mov, w, %Y0); - OUT_AS2 (subc, w, %Y1); - OUT_AS2 (mov, w, %X0); - OUT_AS2 (subc, w, %X1); - OUT_AS2 (mov, w, %W0); - OUT_AS2 (subc, w, %W1); - OUT_AS2 (mov, w, %V0); - OUT_AS2 (subc, w, %V1); - OUT_AS2 (mov, w, %U0); - OUT_AS2 (subc, w, %U1); - OUT_AS2 (mov, w, %T0); - OUT_AS2 (subc, w, %T1); - OUT_AS2 (mov, w, %S0); - OUT_AS2 (subc, w, %S1); - OUT_AS1 (snc,); - OUT_AS1 (page, %2); - OUT_AS1 (jmp, %2); - } - break; - - default: - abort (); - } - break; - - default: - abort (); - } -#undef operands - return ""; -} - -/* Output rtx VALUE as .byte to file FILE. */ - -void -asm_output_char(file, value) - FILE *file; - rtx value; -{ - fprintf (file, "\t.byte "); - output_addr_const (file, value); - fprintf (file, "\n"); -} - - -/* Output VALUE as .byte to file FILE. */ - -void -asm_output_byte (file,value) - FILE *file; - int value; -{ - fprintf (file, "\t.byte 0x%x\n",value & 0xff); -} - - -/* Output rtx VALUE as .word to file FILE. */ - -void -asm_output_short (file, value) - FILE *file; - rtx value; -{ - fprintf (file, "\t.word "); - output_addr_const (file, (value)); - fprintf (file, "\n"); -} - - -/* Output real N to file FILE. */ - -void -asm_output_float (file, n) - FILE *file; - REAL_VALUE_TYPE n; -{ - long val; - char dstr[100]; - - REAL_VALUE_TO_TARGET_SINGLE (n, val); - REAL_VALUE_TO_DECIMAL (n, dstr, -1); - fprintf (file, "\t.long 0x%08lx\t/* %s */\n",val, dstr); -} - -/* Sets section name for declaration DECL. */ - -void -unique_section (decl, reloc) - tree decl; - int reloc ATTRIBUTE_UNUSED; -{ - int len; - const char *name; - char *string; - const char *prefix; - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - /* Strip off any encoding in name. */ - name = (* targetm.strip_name_encoding) (name); - - if (TREE_CODE (decl) == FUNCTION_DECL) - { - if (flag_function_sections) - prefix = ".text."; - else - prefix = ".text"; - } - else - abort (); - - if (flag_function_sections) - { - len = strlen (name) + strlen (prefix); - string = alloca (len + 1); - sprintf (string, "%s%s", prefix, name); - DECL_SECTION_NAME (decl) = build_string (len, string); - } -} - - -/* Output section name to file FILE. */ - -void -asm_output_section_name(file, decl, name, reloc) - FILE *file; - tree decl ATTRIBUTE_UNUSED; - const char *name; - int reloc ATTRIBUTE_UNUSED; -{ - fprintf (file, ".section %s\n", name); -} - -/* Return 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. */ - -enum reg_class -class_likely_spilled_p(c) - int c; -{ - return (c == IP_REGS - || c == IPL_REGS - || c == IPH_REGS - || c == DP_SP_REGS - || c == SP_REGS - || c == DP_REGS - || c == DPL_REGS - || c == DPH_REGS - || c == PTR_REGS); -} - -/* Only `progmem' attribute valid for type. */ - -int -valid_machine_type_attribute(type, attributes, identifier, args) - tree type ATTRIBUTE_UNUSED; - tree attributes ATTRIBUTE_UNUSED; - tree identifier; - tree args ATTRIBUTE_UNUSED; -{ - return is_attribute_p ("progmem", identifier); -} - -/* If IDENTIFIER with arguments ARGS is a valid machine specific - attribute for DECL return 1. - Valid attributes: - progmem - put data to program memory; - naked - don't generate function prologue/epilogue and `ret' command. */ - -int -valid_machine_decl_attribute (decl, attributes, attr, args) - tree decl; - tree attributes ATTRIBUTE_UNUSED; - tree attr; - tree args ATTRIBUTE_UNUSED; -{ - if (is_attribute_p ("naked", attr)) - return TREE_CODE (decl) == FUNCTION_DECL; - - if (is_attribute_p ("progmem", attr) - && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) - { - /* Data stored in program RAM or FLASH must be word aligned or - it won't be directly addressable. */ - if (DECL_ALIGN (decl) < FUNCTION_BOUNDARY) - DECL_ALIGN (decl) = FUNCTION_BOUNDARY; - - if (DECL_INITIAL (decl) == NULL_TREE) - { - warning ("Only initialized variables can be placed into " - "program memory area."); - return 0; - } - return 1; - } - return 0; -} - -/* Encode section information about tree DECL. */ - -void -encode_section_info (decl, first) - tree decl; - int first ATTRIBUTE_UNUSED; -{ - if (! DECL_P (decl)) - return; - - if (TREE_CODE (decl) == FUNCTION_DECL) - SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; -} - -/* Outputs to the stdio stream FILE some - appropriate text to go at the start of an assembler file. */ - -void -asm_file_start (file) - FILE *file; -{ - output_file_directive (file, main_input_filename); - - commands_in_prologues = 0; - commands_in_epilogues = 0; -} - -/* Outputs to the stdio stream FILE some - appropriate text to go at the end of an assembler file. */ - -void -asm_file_end (file) - FILE *file; -{ - fprintf - (file, - "/* File %s: prologues %3d, epilogues %3d */\n", - main_input_filename, commands_in_prologues, commands_in_epilogues); -} - -/* Cost functions. */ - -/* Calculate the cost of X code of the expression in which it is contained, - found in OUTER_CODE. */ - -int -default_rtx_costs (x, code, outer_code) - rtx x; - enum rtx_code code; - enum rtx_code outer_code; -{ - enum machine_mode mode = GET_MODE (x); - int extra_cost = 0; - int total; - - switch (code) - { - case MEM: - return ip2k_address_cost (XEXP (x, 0)); - - case ROTATE: - case ROTATERT: - case ASHIFT: - case LSHIFTRT: - case ASHIFTRT: - if (GET_CODE (XEXP (x, 1)) == CONST_INT) - { - int val = INTVAL (XEXP (x, 1)); - int cost; - - /* Shift by const instructions are proportional to - the shift count modulus 8. Note that we increase the mode - size multiplier by 1 to account for clearing the carry flag. */ - cost = COSTS_N_INSNS (abs (val) % 8); - cost += rtx_cost (XEXP (x, 0), code); - cost *= (GET_MODE_SIZE (mode) + 1); - - /* Sign-preserving shifts require 2 extra instructions. */ - if (code == ASHIFT) - cost += COSTS_N_INSNS (2); - return cost; - } - total = rtx_cost (XEXP (x, 0), code); - total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 8); - return total; - - case MINUS: - case PLUS: - case AND: - case XOR: - case IOR: - total = rtx_cost (XEXP (x, 0), code) - + rtx_cost (XEXP (x, 1), code); - total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3); - return total; - - case MOD: - case DIV: - if (mode == QImode) - return COSTS_N_INSNS (20); - if (mode == HImode) - return COSTS_N_INSNS (60); - else if (mode == SImode) - return COSTS_N_INSNS (180); - else - return COSTS_N_INSNS (540); - - case MULT: - /* These costs are OK, but should really handle subtle cases - where we're using sign or zero extended args as these are - *much* cheaper than those given below! */ - if (mode == QImode) - return COSTS_N_INSNS (4); - if (mode == HImode) - return COSTS_N_INSNS (12); - if (mode == SImode) - return COSTS_N_INSNS (36); - else - return COSTS_N_INSNS (108); - - case NEG: - case SIGN_EXTEND: - extra_cost = COSTS_N_INSNS (GET_MODE_SIZE (mode)); - - /* Fall through. */ - case NOT: - case COMPARE: - case ABS: - total = rtx_cost (XEXP (x, 0), code); - return total + extra_cost + COSTS_N_INSNS (GET_MODE_SIZE (mode) * 2); - - case TRUNCATE: - case ZERO_EXTEND: - if (outer_code == SET) - return rtx_cost (XEXP (x, 0), code) - + COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3 / 2); - else - return -(COSTS_N_INSNS (GET_MODE_SIZE (mode)) / 2); - - case IF_THEN_ELSE: - return rtx_cost (XEXP (x, 0), code) - + COSTS_N_INSNS (2); - - case EQ: - case NE: - case LTU: - case GTU: - case LEU: - case GEU: - case LT: - case GT: - case LE: - case GE: - return rtx_cost (XEXP (x, 0), code) - + rtx_cost (XEXP (x, 1), code); - - default: - return COSTS_N_INSNS (4); - } -} - -/* Calculate the cost of a memory address. */ - -int -ip2k_address_cost (x) - rtx x; -{ - switch (legitimate_address_p (VOIDmode, x, 0)) - { - case 'S': /* Very low cost - (IP), (SP+N) or (DP+N) */ - return 8; - - case 'R': /* Indirected through IP. */ - return 8; - - case 'L': /* Label references. */ - return 0; - - case 'C': /* Constants and symbol references. */ - return 4; - - default: - return 1000; /* Must reload. */ - } -} - -/* As part of the machine-dependent reorg we look for opcode sequences where - we do some operation and then move the results back to one of the original - source operands. With working on the source operand directly is probably - much cheaper and the move from this to the original source operand will be - no more expensive than the original move. */ - -#ifdef IP2K_MD_REORG_PASS -static void -mdr_resequence_xy_yx (first_insn) - rtx first_insn; -{ - rtx insn; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - rtx set; - - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Look for operations that tend to be very cheap to run when the source - * and dest args are the same because the IP2022 has opcodes that can - operate on the source directly. If we have to spill through the W - register then we've possibly not got a good case for doing this. */ - if ((GET_CODE (XEXP (set, 0)) == REG - || GET_CODE (XEXP (set, 0)) == MEM) - && (GET_CODE (XEXP (set, 1)) == ASHIFT - || GET_CODE (XEXP (set, 1)) == ASHIFTRT - || GET_CODE (XEXP (set, 1)) == LSHIFTRT - || GET_CODE (XEXP (set, 1)) == XOR - || GET_CODE (XEXP (set, 1)) == IOR - || GET_CODE (XEXP (set, 1)) == AND - || GET_CODE (XEXP (set, 1)) == PLUS - || GET_CODE (XEXP (set, 1)) == MINUS - || GET_CODE (XEXP (set, 1)) == MULT)) - { - rtx set2; - rtx next_insn; - - next_insn = next_nonnote_insn (insn); - if (! next_insn) - continue; - - if (GET_CODE (next_insn) != INSN) - continue; - - set2 = ((GET_CODE (PATTERN (next_insn)) == SET) - ? PATTERN (next_insn) : NULL_RTX); - if (set2 == NULL_RTX) - continue; - - if ((GET_CODE (XEXP (XEXP (set, 1), 0)) == REG - || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM) - && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 0)) - && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0))) - { - rtx next2_insn; - rtx b_insn; - - b_insn = gen_rtx_SET (VOIDmode, - XEXP (XEXP (set, 1), 0), - gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)), - GET_MODE (XEXP (set, 0)), - XEXP (XEXP (set, 1), 0), - XEXP (XEXP (set, 1), 1))); - - emit_insn_before (b_insn, insn); - b_insn = gen_rtx_SET (GET_MODE (XEXP (set, 0)), XEXP (set, 0), - XEXP (XEXP (set, 1), 0)); - next2_insn = emit_insn_before (b_insn, insn); - delete_insn (insn); - delete_insn (next_insn); - insn = next2_insn; - continue; - } - - /* Having tried with one operand of the expression, now, if - appropriate, try to do the same thing with the second operand. - Of course there are fewer operations that can match here - because they must be commutative. */ - if (GET_RTX_CLASS (GET_CODE (XEXP (set, 1))) == 'c' - && (GET_CODE (XEXP (XEXP (set, 1), 1)) == REG - || GET_CODE (XEXP (XEXP (set, 1), 1)) == MEM) - && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 1)) - && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0))) - { - rtx rtx_ee; - rtx next2_insn; - int swap_args; - - /* Try to ensure that we put things in a canonical form. */ - swap_args = (GET_CODE (XEXP (XEXP (set, 1), 0)) == REG - || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM); - rtx_ee = gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)), - GET_MODE (XEXP (set, 0)), - XEXP (XEXP (set, 1), swap_args ? 1 : 0), - XEXP (XEXP (set, 1), - swap_args ? 0 : 1)); - - emit_insn_before (gen_rtx_SET (VOIDmode, - XEXP (XEXP (set, 1), 1), - rtx_ee), - insn); - next2_insn = emit_insn_before (gen_rtx_SET - (GET_MODE (XEXP (set, 0)), - XEXP (set, 0), - XEXP (XEXP (set, 1), 1)), - insn); - delete_insn (insn); - delete_insn (next_insn); - insn = next2_insn; - } - } - } -} - -/* Replace and recurse until we've tried QImode pieces! */ - -static void -mdr_pres_replace_and_recurse (orig, with, insn) - rtx orig; - rtx with; - rtx insn; -{ - enum machine_mode new_mode; - - validate_replace_rtx (orig, with, insn); - - switch (GET_MODE (orig)) - { - case DImode: - case DFmode: - new_mode = SImode; - break; - - case SImode: - case SFmode: - new_mode = HImode; - break; - - case HImode: - new_mode = QImode; - break; - - default: - return; - } - - mdr_pres_replace_and_recurse (ip2k_get_low_half (orig, new_mode), - ip2k_get_low_half (with, new_mode), - insn); - mdr_pres_replace_and_recurse (ip2k_get_high_half (orig, new_mode), - ip2k_get_high_half (with, new_mode), - insn); -} - -/* Assist the following function, mdr_propagate_reg_equivs(). */ - -static void -mdr_propagate_reg_equivs_sequence (first_insn, orig, equiv) - rtx first_insn; - rtx orig; - rtx equiv; -{ - rtx try_insn; - rtx try_equiv = equiv; - - /* First scan the RTL looking for anything else that might clobber what - we're doing. If we find anything then we can't do the replacement. */ - for (try_insn = next_nonnote_insn (first_insn); - try_insn; try_insn = next_nonnote_insn (try_insn)) - { - rtx pattern; - - if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN) - continue; - - pattern = PATTERN (try_insn); - if (GET_CODE (pattern) == PARALLEL) - { - int j; - - for (j = 0; j < XVECLEN (pattern, 0); j++) - { - rtx px = XVECEXP (pattern, 0, j); - - if (GET_CODE (px) == SET) - if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (px, 0), - REGNO (orig), - GET_MODE_SIZE (GET_MODE (orig)))) - return; - } - } - else if (GET_CODE (pattern) == SET) - { - if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (pattern, 0), - REGNO (orig), - GET_MODE_SIZE (GET_MODE (orig)))) - return; - } - } - - /* Once we've decided that we're safe to do the replacement then make the - changes. */ - for (try_insn = next_nonnote_insn (first_insn); try_insn; - try_insn = next_nonnote_insn (try_insn)) - { - rtx set; - rtx new_equiv = NULL_RTX; - - if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN) - { - try_equiv = equiv; - continue; - } - - set = ((GET_CODE (PATTERN (try_insn)) == SET) - ? PATTERN (try_insn) : NULL_RTX); - if (set == NULL_RTX) - continue; - - /* We look for a special case of "push" operations screwing our - register equivalence when it's based on a stack slot. We can - track this one and replace the old equivalence expression with - a new one. */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && REG_P (XEXP (XEXP (XEXP (set, 0), 0), 0)) - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP) - { - /* XXX - need to ensure that we can track this without going - out of range! */ - HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (try_equiv, 0), 1)) - + GET_MODE_SIZE (GET_MODE (XEXP (set, 0)))); - new_equiv = gen_rtx_MEM (GET_MODE (try_equiv), - gen_rtx_PLUS (Pmode, - gen_rtx_REG (HImode, REG_SP), - GEN_INT (disp))); - } - - /* The replacement process is somewhat complicated by the fact that we - might be dealing with what were originally subregs and thus we have - to replace parts of our original expression! */ - mdr_pres_replace_and_recurse (orig, try_equiv, try_insn); - - if (new_equiv != NULL_RTX) - try_equiv = new_equiv; - } -} - -/* Try propagating register equivalences forwards. It may be that we can - replace a register use with an equivalent expression that already - holds the same value and thus allow one or more register loads to - be eliminated. */ - -static void -mdr_propagate_reg_equivs (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Have we found a stack slot equivalence for a register? */ - if (REG_P (XEXP (set, 0)) - && REGNO (XEXP (set, 0)) >= 0x88 - && GET_CODE (XEXP (set, 1)) == MEM - && GET_CODE (XEXP (XEXP (set, 1), 0)) == PLUS - && REG_P (XEXP (XEXP (XEXP (set, 1), 0), 0)) - && REGNO (XEXP (XEXP (XEXP (set, 1), 0), 0)) == REG_SP - && find_reg_note (insn, REG_EQUIV, NULL_RTX)) - { - mdr_propagate_reg_equivs_sequence (insn, XEXP (set, 0), - XEXP (set, 1)); - } - } -} - -/* Structure used to track jump targets. */ - -struct dpre_jump_targets -{ - int target; /* Is this a jump target? */ - int reach_count; /* Number of ways we can reach this insn. */ - int touch_count; /* Number of times we've touched this - insns during scanning. */ - rtx dp_equiv; /* DP-equivalence at this point. */ -}; - -struct dpre_jump_targets *ip2k_dpre_jump_targets; - -/* DP equivalence tracking used within DP reload elimination. */ - -static int -track_dp_reload (insn, dp_current, dp_current_ok, modifying) - rtx insn; - rtx *dp_current; - int dp_current_ok; - int modifying; -{ - rtx set; - - if (GET_CODE (insn) != INSN) - { - *dp_current = NULL_RTX; - return 1; - } - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - { - *dp_current = NULL_RTX; - return 1; - } - - /* If we're pushing a PLUS or MINUS then it's a win if we can replace - an expression for which DP is equivalent with DP. This happens - surprisingly often when we pass a pointer to a structure embedded - within another structure. */ - if (*dp_current != NULL_RTX - && GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && (GET_CODE (XEXP (set, 1)) == PLUS - || GET_CODE (XEXP (set, 1)) == MINUS) - && GET_CODE (*dp_current) != SYMBOL_REF - && GET_CODE (*dp_current) != LABEL_REF - && GET_CODE (*dp_current) != CONST) - { - if (modifying) - validate_replace_rtx (*dp_current, gen_rtx_REG (HImode, REG_DP), insn); - } - - /* Look for DP being modified. If it is, see if it's being changed - to what it already is! */ - if (GET_CODE (XEXP (set, 0)) == REG - && REGNO (XEXP (set, 0)) == REG_DP - && GET_MODE (XEXP (set, 0)) == HImode) - { - /* If this is an equivalence we can delete the new set operation. */ - if (*dp_current != NULL_RTX - && rtx_equal_p (XEXP (set, 1), *dp_current)) - { - if (modifying) - delete_insn (insn); - } - else - { - /* If we've not found an equivalence we can look for a special - case where an operand of the expression that sets DP is - already equivalent to DP and in that circumstance we simplify - by replacing that expression with DP. */ - if (*dp_current != NULL_RTX - && GET_CODE (*dp_current) != SYMBOL_REF - && GET_CODE (*dp_current) != LABEL_REF - && GET_CODE (*dp_current) != CONST - && modifying) - validate_replace_rtx (*dp_current, XEXP (set, 0), insn); - - /* Assuming that we're not loading DP from something that uses DP - itself then we mark the new equivalence for DP. If we did match - DP then we can't re-use this one. */ - if (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2)) - { - *dp_current = XEXP (set, 1); - return 1; - } - else - { - *dp_current = NULL_RTX; - return 1; - } - } - } - else if (GET_CODE (XEXP (set, 0)) == REG - && (REGNO (XEXP (set, 0)) == REG_DPL - || REGNO (XEXP (set, 0)) == REG_DPH)) - { - /* If we clobber part of DP then we've clobbered any equivalences! */ - *dp_current = NULL_RTX; - return 1; - } - else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2) - && *dp_current != NULL_RTX - && !ip2k_xexp_not_uses_reg_p (*dp_current, REG_SP, 2)) - { - /* We look for a special case of "push" operations screwing up the - setting of DP when it's based on the stack. We can track this one - and replace the old expression for DP with a new one. */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && GET_CODE (*dp_current) == MEM - && GET_CODE (XEXP (*dp_current, 0)) == PLUS) - { - /* XXX - need to ensure that we can track this without going - out of range! */ - HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (*dp_current, 0), 1)) - + GET_MODE_SIZE (GET_MODE (XEXP (set, 0)))); - *dp_current = gen_rtx_MEM (HImode, - gen_rtx_PLUS (Pmode, - gen_rtx_REG(HImode, REG_SP), - GEN_INT (disp))); - return 1; - } - - /* Now we look for writes to the stack. We can determine if these will - affect the equivalence we're tracking for DP and if not then we can - keep tracking it. */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (*dp_current) == MEM) - { - /* Look at the SP offsets and look for any overlaps. */ - int dp_cur_sp_offs = INTVAL (XEXP (XEXP (*dp_current, 0), 1)); - int set_sp_offs = INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1)); - - if (abs (dp_cur_sp_offs - set_sp_offs) < 2) - { - *dp_current = NULL_RTX; - return 1; - } - } - } - else if (GET_CODE (XEXP (set, 0)) == REG - && *dp_current != NULL_RTX - && !ip2k_xexp_not_uses_reg_p (*dp_current, REGNO (XEXP (set, 0)), - GET_MODE_SIZE (GET_MODE (XEXP (set, - 0))))) - { - /* If we've just clobbered all or part of a register reference that we - were sharing for DP then we can't share it any more! */ - *dp_current = NULL_RTX; - } - - return dp_current_ok; -} - -/* As part of the machine-dependent reorg we scan loads and reloads of - DP to see where any are redundant. This does happens because we - are able to subsequently transform things in interesting ways. Sometimes - gcc also does unecessary reloads too so we try to eliminate these too. */ - -static void -mdr_try_dp_reload_elim (first_insn) - rtx first_insn; -{ - rtx insn; - struct dpre_jump_targets *djt; - rtx dp_current; - int incomplete_scan; - int last_incomplete_scan; - - ip2k_dpre_jump_targets - = (struct dpre_jump_targets *) xcalloc (get_max_uid (), - sizeof (struct dpre_jump_targets)); - - /* First we scan to build up a list of all CODE_LABEL insns and we work out - how many different ways we can reach them. */ - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - djt = &ip2k_dpre_jump_targets[INSN_UID (insn)]; - djt->target = 1; - djt->reach_count = LABEL_NUSES (insn); - djt->touch_count = 0; - djt->dp_equiv = NULL_RTX; - if (! prev_nonnote_insn (insn) - || (prev_nonnote_insn (insn) - && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)) - djt->reach_count++; - } - } - - /* Next we scan all of the ways of reaching the code labels to see - what the DP register is equivalent to as we reach them. If we find - that they're the same then we keep noting the matched value. We - iterate around this until we reach a convergence on DP equivalences - at all code labels - we have to be very careful not to be too - optimistic! */ - incomplete_scan = -1; - do - { - int dp_current_ok = 0; - last_incomplete_scan = incomplete_scan; - dp_current = NULL_RTX; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - /* If we have a code label then we need to see if we already know - what the equivalence is at this point. If we do then we use it - immediately, but if we don't then we have a special case to track - when we hit a fallthrough-edge (label with no barrier preceding - it). Any other accesses to the label must be from jump insns - and so they're handled elsewhere. */ - if (GET_CODE (insn) == CODE_LABEL) - { - djt = &ip2k_dpre_jump_targets[INSN_UID (insn)]; - - /* If we're fully characterized the use the equivalence. */ - if (djt->touch_count == djt->reach_count) - { - dp_current = djt->dp_equiv; - dp_current_ok = 1; - continue; - } - - /* If we have a known equivalence for DP as we reach the - fallthrough-edge then track this into the code label. */ - if (dp_current_ok - && (! prev_nonnote_insn (insn) - || (prev_nonnote_insn (insn) - && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))) - { - if (djt->touch_count == 0) - djt->dp_equiv = dp_current; - - if (djt->touch_count < djt->reach_count) - { - djt->touch_count++; - if (! rtx_equal_p (djt->dp_equiv, dp_current)) - { - /* When we definitely know that we can't form an - equivalence for DP here we must clobber anything - that we'd started to track too. */ - djt->dp_equiv = NULL_RTX; - dp_current = NULL_RTX; - dp_current_ok = 1; - } - } - } - - /* If we've not completely characterized this code label then - be cautious and assume that we don't know what DP is - equivalent to. */ - if (djt->touch_count < djt->reach_count) - { - dp_current = NULL_RTX; - dp_current_ok = 0; - } - - continue; - } - - /* If we've hit a jump insn then we look for either an address - vector (jump table) or for jump label references. */ - if (GET_CODE (insn) == JUMP_INSN) - { - /* Don't attempt to track here if we don't have a known - equivalence for DP at this point. */ - if (dp_current_ok) - { - rtx pat = PATTERN (insn); - if (GET_CODE (pat) == ADDR_VEC) - { - int i; - int len = XVECLEN (pat, 0); - - for (i = 0; i < len; i++) - { - rtx vec_insn = XEXP (XVECEXP (pat, 0, i), 0); - djt = &ip2k_dpre_jump_targets [INSN_UID (vec_insn)]; - - if (djt->touch_count == 0) - djt->dp_equiv = dp_current; - - if (djt->touch_count < djt->reach_count) - { - djt->touch_count++; - if (! rtx_equal_p (djt->dp_equiv, dp_current)) - djt->dp_equiv = NULL_RTX; - } - } - } - else if (JUMP_LABEL (insn)) - { - rtx j_insn = JUMP_LABEL (insn); - djt = &ip2k_dpre_jump_targets[INSN_UID (j_insn)]; - - if (djt->touch_count == 0) - djt->dp_equiv = dp_current; - - if (djt->touch_count < djt->reach_count) - { - djt->touch_count++; - if (! rtx_equal_p (djt->dp_equiv, dp_current)) - djt->dp_equiv = NULL_RTX; - } - } - } - - continue; - } - - /* Anything other than a code labal or jump arrives here. - We try and track DP, but sometimes we might not be able to. */ - dp_current_ok = track_dp_reload (insn, &dp_current, - dp_current_ok, 0); - } - - /* When we're looking to see if we've finished we count the number of - paths throught the code labels where we weren't able to definitively - track DP. - This number is used to see if we're converging on a solution. - If this hits zero then we've fully converged, but if this stays the - same as last time then we probably can't make any further - progress. */ - incomplete_scan = 0; - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - djt = &ip2k_dpre_jump_targets[INSN_UID (insn)]; - if (djt->touch_count != djt->reach_count) - { - incomplete_scan += (djt->reach_count - djt->touch_count); - djt->dp_equiv = NULL_RTX; - djt->touch_count = 0; - } - } - } - } - while (incomplete_scan && incomplete_scan != last_incomplete_scan); - - /* Finally we scan the whole function and run DP elimination. When we hit - a CODE_LABEL we pick up any stored equivalence since we now know that - every path to this point entered with DP holding the same thing! If - we subsequently have a reload that matches then we can eliminate it. */ - dp_current = NULL_RTX; - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == JUMP_INSN) - continue; - - if (GET_CODE (insn) == CODE_LABEL) - { - djt = &ip2k_dpre_jump_targets[INSN_UID (insn)]; - dp_current = djt->dp_equiv; - continue; - } - - track_dp_reload (insn, &dp_current, 1, 1); - } - - free (ip2k_dpre_jump_targets); -} - -/* As part of the machine-dependent reorg we look for reloads of DP - that we can move to earlier points within the file. - Moving these out of the way allows more peepholes to match. */ - -static void -mdr_try_move_dp_reload (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - rtx orig_first; - - /* Don't try to match the first instruction because we can't move it - anyway. */ - orig_first = first_insn; - first_insn = next_nonnote_insn (first_insn); - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Look for DP being loaded. When we find this we start a rewind - scan looking for possible positions to move this to. */ - if (GET_CODE (XEXP (set, 0)) == REG - && REGNO (XEXP (set, 0)) == REG_DP - && GET_MODE (XEXP (set, 0)) == HImode) - { - int try_again; - rtx try_insn = insn; - - do - { - rtx rewind; - rtx check; - - try_again = 0; - - /* For now we do the *really* simple version of things and only - attempt to move the load of DP if it's very safe to do so. */ - rewind = prev_nonnote_insn (try_insn); - if (rewind != orig_first && rewind != NULL_RTX - && GET_CODE (rewind) == INSN) - { - check = ((GET_CODE (PATTERN (rewind)) == SET) - ? PATTERN (rewind) : NULL_RTX); - if (check != NULL_RTX - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 0)) - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 1))) - { - if (GET_CODE (XEXP (check, 0)) == REG - && REGNO (XEXP (check, 0)) != REG_DPH - && REGNO (XEXP (check, 0)) != REG_DPL - && (ip2k_composite_xexp_not_uses_reg_p - (XEXP (check, 1), REG_DP, 2)) - && (ip2k_composite_xexp_not_uses_reg_p - (XEXP (set, 1), - REGNO (XEXP (check, 0)), - GET_MODE_SIZE (GET_MODE (XEXP (check, 0)))))) - { - emit_insn_before (set, rewind); - if (try_insn == insn) - insn = prev_nonnote_insn (insn); - delete_insn (try_insn); - try_insn = prev_nonnote_insn (rewind); - try_again = 1; - } - else if (GET_CODE (XEXP (set, 1)) == REG - && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 1), REG_DP, 2) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REG_DP, 2) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REGNO (XEXP (set, 1)), - GET_MODE_SIZE (GET_MODE (XEXP (set, 1))))) - { - emit_insn_before (set, rewind); - if (try_insn == insn) - insn = prev_nonnote_insn (insn); - delete_insn (try_insn); - try_insn = prev_nonnote_insn (rewind); - try_again = 1; - } - } - } - } - while (try_again && try_insn); - } - } -} -#endif /* IP2K_MD_REORG_PASS */ - -/* Look to see if the expression, x, can have any stack references offset by - a fixed constant, offset. If it definitely can then returns non-zero. */ - -static int -ip2k_check_can_adjust_stack_ref (x, offset) - rtx x; - int offset; -{ - if (GET_RTX_CLASS (GET_CODE (x)) == '2' - || GET_RTX_CLASS (GET_CODE (x)) == 'c') - return (ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset) - && ip2k_check_can_adjust_stack_ref (XEXP (x, 1), offset)); - - if (GET_RTX_CLASS (GET_CODE (x)) == '1') - return ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset); - - switch (GET_CODE (x)) - { - case REG: - return (REGNO (x) != REG_SPH && REGNO (x) != REG_SPL); - - case MEM: - if (GET_CODE (XEXP (x, 0)) != PLUS) - return 1; - - if (GET_CODE (XEXP (XEXP (x, 0), 0)) != REG) - return 1; - - if (REGNO (XEXP (XEXP (x, 0), 0)) != REG_SP) - return 1; - - /* We can't allow this if the adjustment will create an - invalid address. */ - return (INTVAL (XEXP (XEXP (x, 0), 1)) - + offset <= (128 - 2 * GET_MODE_SIZE (GET_MODE (x)))); - - case CONST: - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case LABEL_REF: - return 1; - - default: - return 0; - } -} - -/* Adjusts all of the stack references in the expression pointed to by x by - a fixed offset. */ - -static void -ip2k_adjust_stack_ref (x, offset) - rtx *x; - int offset; -{ - if (GET_RTX_CLASS (GET_CODE (*x)) == '2' - || GET_RTX_CLASS (GET_CODE (*x)) == 'c') - { - ip2k_adjust_stack_ref (&XEXP (*x, 0), offset); - ip2k_adjust_stack_ref (&XEXP (*x, 1), offset); - return; - } - - if (GET_RTX_CLASS (GET_CODE (*x)) == '1') - { - ip2k_adjust_stack_ref (&XEXP (*x, 0), offset); - return; - } - - switch (GET_CODE (*x)) - { - case MEM: - if (GET_CODE (XEXP (*x, 0)) != PLUS) - return; - - if (GET_CODE (XEXP (XEXP (*x, 0), 0)) != REG) - return; - - if (REGNO (XEXP (XEXP (*x, 0), 0)) != REG_SP) - return; - - *x = copy_rtx (*x); - XEXP (XEXP (*x, 0), 1) = GEN_INT (INTVAL (XEXP (XEXP (*x, 0), 1)) - + offset); - break; - - default: - break; - } -} - -#ifdef IP2K_MD_REORG_PASS -/* As part of the machine-dependent reorg we look to move push instructions - to earlier points within the file. Moving these out of the way allows more - peepholes to match. */ - -static void -mdr_try_move_pushes (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - rtx orig_first; - - /* Don't try to match the first instruction because we can't move - it anyway. */ - orig_first = first_insn; - first_insn = next_nonnote_insn (first_insn); - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Have we found a push instruction? */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && GET_CODE (XEXP (set, 1)) == REG) - { - rtx try_insn = insn; - unsigned int regno = REGNO (XEXP (set, 1)); - int reg_range = GET_MODE_SIZE (GET_MODE (XEXP (set, 1))); - - while (1) - { - rtx rewind; - rtx check; - - rewind = prev_nonnote_insn (try_insn); - if (rewind == orig_first || rewind == NULL_RTX - || GET_CODE (rewind) != INSN) - break; - - check = (GET_CODE (PATTERN (rewind)) == SET) ? PATTERN (rewind) : NULL_RTX; - if (check == NULL_RTX) - break; - - if (! ip2k_check_can_adjust_stack_ref (XEXP (check, 0), - reg_range) - || ! ip2k_check_can_adjust_stack_ref (XEXP (check, 1), - reg_range)) - break; - - /* If we've hit another push instruction we can't go any - further. */ - if (GET_CODE (XEXP (check, 0)) == MEM - && GET_CODE (XEXP (XEXP (check, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG_SP) - break; - - /* If this is a register move then check that it doesn't clobber - SP or any part of the instruction we're trying to move. */ - if (GET_CODE (XEXP (check, 0)) == REG) - { - unsigned int check_reg = REGNO (XEXP (check, 0)); - int check_reg_range = GET_MODE_SIZE (GET_MODE (XEXP (check, - 0))); - - /* If we have a special case where what we want to push is - being loaded by this "clobbering" insn then we can just - push what is being used to load us and then do the load. - This may seem a little odd, but we may subsequently be - able to merge the load with another instruction as it - may only be used once now! Note though that we - specifically don't try this if the expression being - loaded is an HImode MEM using IP. */ - if (check_reg == regno - && check_reg_range == reg_range - && ((GET_CODE (XEXP (check, 1)) == REG - || (GET_CODE (XEXP (check, 1)) == MEM - && (GET_MODE (XEXP (check, 1)) != HImode - || ip2k_xexp_not_uses_reg_for_mem (XEXP (check, 1), REG_IP)))))) - { - switch (check_reg_range) - { - case 1: - emit_insn_before (gen_movqi (XEXP (set, 0), - XEXP (check, 1)), - rewind); - delete_insn (try_insn); - break; - - case 2: - emit_insn_before (gen_movhi (XEXP (set, 0), - XEXP (check, 1)), - rewind); - delete_insn (try_insn); - break; - - case 4: - emit_insn_before (gen_movsi (XEXP (set, 0), - XEXP (check, 1)), - rewind); - delete_insn (try_insn); - break; - - case 8: - emit_insn_before (gen_movdi (XEXP (set, 0), - XEXP (check, 1)), - rewind); - delete_insn (try_insn); - break; - } - - ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range); - ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range); - try_insn = prev_nonnote_insn (rewind); - /* XXX - should be a continue? */ - break; - } - - if ((check_reg == REG_SPL) - || (check_reg == REG_SPH) - || (((regno <= check_reg) - && (regno + reg_range - 1) >= check_reg) - || ((regno <= (check_reg + check_reg_range - 1)) - && ((regno + reg_range - 1) - >= (check_reg + check_reg_range - 1))))) - break; - } - - emit_insn_before (set, rewind); - delete_insn (try_insn); - ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range); - ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range); - try_insn = prev_nonnote_insn (rewind); - } - } - } -} - -/* Assist the following function, mdr_try_propagate_clr(). */ - -static void -mdr_try_propagate_clr_sequence (first_insn, regno) - rtx first_insn; - unsigned int regno; -{ - rtx try_insn; - - for (try_insn = next_nonnote_insn (first_insn); try_insn; - try_insn = next_nonnote_insn (try_insn)) - { - rtx new_insn = NULL_RTX; - rtx set2; - - if (GET_CODE (try_insn) == JUMP_INSN) - continue; - - if (GET_CODE (try_insn) != INSN) - break; - - set2 = ((GET_CODE (PATTERN (try_insn)) == SET) - ? PATTERN (try_insn) : NULL_RTX); - if (set2 == NULL_RTX) - continue; - - if (GET_CODE (XEXP (set2, 1)) == AND - && ((GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno) - || (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - && REGNO (XEXP (XEXP (set2, 1), 1)) == regno))) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - const0_rtx), try_insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == IOR - && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - XEXP (XEXP (set2, 1), 1)), - try_insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == IOR - && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - && REGNO (XEXP (XEXP (set2, 1), 1)) == regno) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - XEXP (XEXP (set2, 1), 0)), - try_insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == XOR - && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - XEXP (XEXP (set2, 1), 1)), - try_insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == XOR - && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - && REGNO (XEXP (XEXP (set2, 1), 1)) == regno) - { - rtx remove_insn = try_insn; - try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0), - XEXP (XEXP (set2, 1), 0)), - try_insn); - delete_insn (remove_insn); - } - - if (GET_CODE (XEXP (set2, 0)) == REG) - { - int reg2_range = GET_MODE_SIZE (GET_MODE (XEXP (set2, 0))); - unsigned int regno2 = REGNO (XEXP (set2, 0)); - - if (reg2_range == 1 - && regno == regno2 - && GET_CODE (XEXP (set2, 1)) == CONST_INT) - { - int iv = INTVAL (XEXP (set2, 1)); - if (iv == 0xff) - iv = -1; - if (iv == 1 || iv == -1) - { - new_insn = gen_rtx_SET (QImode, XEXP (set2, 0), - gen_rtx_PLUS (QImode, XEXP (set2, 0), - GEN_INT (iv))); - new_insn = emit_insn_before (new_insn, try_insn); - delete_insn (try_insn); - try_insn = new_insn; - } - break; - } - - if ((regno >= regno2) && (regno <= regno2 + reg2_range - 1)) - break; - - if (GET_CODE (XEXP (set2, 1)) == REG - && REGNO (XEXP (set2, 1)) == regno) - { - new_insn = emit_insn_before (gen_rtx_SET (QImode, - XEXP (set2, 0), - const0_rtx), - try_insn); - delete_insn (try_insn); - try_insn = new_insn; - } - } - - if (GET_CODE (XEXP (set2, 0)) == CC0) - { - if (GET_CODE (XEXP (set2, 1)) == REG - && GET_MODE_SIZE (GET_MODE (XEXP (set2, 1))) == 2 - && REGNO (XEXP (set2, 1)) == regno) - { - new_insn = gen_rtx_SET (VOIDmode, gen_rtx (CC0, VOIDmode), - gen_rtx_REG(QImode, regno + 1)); - new_insn = emit_insn_before (new_insn, try_insn); - } - else if (GET_CODE (XEXP (set2, 1)) == COMPARE - && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2 - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno - && GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (set2, 1), 1)) >= 0 - && INTVAL (XEXP (XEXP (set2, 1), 1)) < 256) - { - new_insn = gen_rtx_SET (VOIDmode, cc0_rtx, - gen_rtx_COMPARE(QImode, - gen_rtx_REG (QImode, - regno + 1), - XEXP (XEXP (set2, 1), - 1))); - new_insn = emit_insn_before (new_insn, try_insn); - } - - /* If we have inserted a replacement for a CC0 setter operation - then we need to delete the old one. */ - if (new_insn != NULL_RTX) - { - delete_insn (try_insn); - try_insn = new_insn; - - /* Now as we know that we have just done an unsigned compare - (remember we were zero-extended by the clr!) we also know - that we don't need a signed jump insn. If we find that - our next isns is a signed jump then make it unsigned! */ - if (GET_CODE (next_nonnote_insn (try_insn)) == JUMP_INSN) - { - rtx set3; - - try_insn = next_nonnote_insn (try_insn); - set3 = ((GET_CODE (PATTERN (try_insn)) == SET) - ? PATTERN (try_insn) : NULL_RTX); - if (set3 == NULL_RTX) - continue; - - /* If we discover that our jump target is only accessible - from here then we can continue our "clr" propagation to - it too! */ - if (LABEL_NUSES (JUMP_LABEL (try_insn)) == 1) - mdr_try_propagate_clr_sequence (JUMP_LABEL (try_insn), - regno); - - if (GET_CODE (XEXP (set3, 0)) == PC - && GET_CODE (XEXP (set3, 1)) == IF_THEN_ELSE - && (GET_CODE (XEXP (XEXP (set3, 1), 0)) == GT - || GET_CODE (XEXP (XEXP (set3, 1), 0)) == GE - || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LT - || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LE) - && GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 0)) == CC0 - && (GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 1)) - == CONST_INT) - && GET_CODE (XEXP (XEXP (set3, 1), 1)) == LABEL_REF - && GET_CODE (XEXP (XEXP (set3, 1), 2)) == PC) - { - enum rtx_code code; - rtx new_if; - rtx cmp; - - /* Replace our old conditional jump with a new one that - does the unsigned form of what was previously a - signed comparison. */ - code = GET_CODE (XEXP (XEXP (set3, 1), 0)); - cmp = gen_rtx_fmt_ee ((code == GT - ? GTU - : (code == GE - ? GEU - : (code == LT ? LTU : LEU))), - VOIDmode, - XEXP (XEXP (XEXP (set3, 1), 0), 0), - XEXP (XEXP (XEXP (set3, 1), 0), - 1)); - new_if - = gen_rtx_SET (GET_MODE (set3), - pc_rtx, - gen_rtx_IF_THEN_ELSE - (GET_MODE (XEXP (set3, 1)), cmp, - XEXP (XEXP (set3, 1), 1), - XEXP (XEXP (set3, 1), 2))); - new_insn = emit_jump_insn_before (new_if, try_insn); - LABEL_NUSES (JUMP_LABEL (try_insn))++; - delete_insn (try_insn); - try_insn = new_insn; - } - } - } - } - else if (GET_CODE (XEXP (set2, 1)) == PLUS - && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2 - && REGNO (XEXP (XEXP (set2, 1), 0)) == regno - && (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - || GET_CODE (XEXP (XEXP (set2, 1), 1)) == MEM - || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT - || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST - || GET_CODE (XEXP (XEXP (set2, 1), 1)) == SYMBOL_REF)) - { - rtx extend = gen_rtx_ZERO_EXTEND (HImode, - gen_rtx_REG (QImode, regno + 1)); - new_insn = gen_rtx_SET (HImode, XEXP (set2, 0), - gen_rtx_PLUS (HImode, extend, - XEXP (XEXP (set2, 1), 1))); - new_insn = emit_insn_before (new_insn, try_insn); - delete_insn (try_insn); - try_insn = new_insn; - } - else if (GET_CODE (XEXP (set2, 1)) == PLUS - && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG - && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 1))) == 2 - && REGNO (XEXP (XEXP (set2, 1), 1)) == regno - && (GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG - || GET_CODE (XEXP (XEXP (set2, 1), 0)) == MEM - || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST_INT - || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST - || GET_CODE (XEXP (XEXP (set2, 1), 0)) == SYMBOL_REF)) - { - rtx t_src = gen_rtx_PLUS (HImode, - gen_rtx_ZERO_EXTEND (HImode, - gen_rtx_REG (QImode, - regno - + 1)), - XEXP (XEXP (set2, 1), 0)); - new_insn = emit_insn_before (gen_rtx_SET (HImode, XEXP (set2, 0), - t_src), - try_insn); - delete_insn (try_insn); - try_insn = new_insn; - } - } -} - -/* One of the things that can quite often happen with an 8-bit CPU is that - we end up clearing the MSByte of a 16-bit value. Unfortunately, all too - often gcc doesn't have any way to realize that only half of the value is - useful and ends up doing more work than it should. We scan for such - occurrences here, track them and reduce compare operations to a smaller - size where possible. - - Note that this is somewhat different to move propagation as we may - actually change some instruction patterns when we're doing this whereas - move propagation is just about doing a search and replace. */ - -static void -mdr_try_propagate_clr (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Have we found a "clr" instruction? */ - if (GET_CODE (XEXP (set, 0)) == REG - && GET_CODE (XEXP (set, 1)) == CONST_INT - && GET_MODE_SIZE (GET_MODE (XEXP (set, 0))) == 1 - && INTVAL (XEXP (set, 1)) == 0) - { - mdr_try_propagate_clr_sequence (insn, REGNO (XEXP (set, 0))); - } - } -} -#endif /* IP2K_MD_REORG_PASS */ - -/* Look to see if the expression, x, does not make any memory references - via the specified register. This is very conservative and only returns - non-zero if we definitely don't have such a memory ref. */ - -static int -ip2k_xexp_not_uses_reg_for_mem (x, regno) - rtx x; - unsigned int regno; -{ - if (regno & 1) - regno &= 0xfffffffe; - - if (GET_RTX_CLASS (GET_CODE (x)) == 'b') - return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno) - && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno) - && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 2), regno)); - - if (GET_RTX_CLASS (GET_CODE (x)) == '2' - || GET_RTX_CLASS (GET_CODE (x)) == 'c' - || GET_RTX_CLASS (GET_CODE (x)) == '<') - return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno) - && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno)); - - if (GET_RTX_CLASS (GET_CODE (x)) == '1' - || GET_RTX_CLASS (GET_CODE (x)) == '3') - return ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno); - - switch (GET_CODE (x)) - { - case REG: - return 1; - - case MEM: - if ((GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG - && REGNO (XEXP (XEXP (x, 0), 0)) == regno) - || (GET_CODE (XEXP (x, 0)) == REG - && REGNO (XEXP (x, 0)) == regno)) - return 0; - else - return 1; - - case CONST: - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case LABEL_REF: - case CC0: - case PC: - return 1; - - default: - return 0; - } -} - -#ifdef IP2K_MD_REORG_PASS -/* Assist the following function, mdr_try_propagate_move(). */ - -static void -mdr_try_propagate_move_sequence (first_insn, orig, equiv) - rtx first_insn; - rtx orig; - rtx equiv; -{ - rtx try_insn; - - for (try_insn = next_nonnote_insn (first_insn); try_insn; - try_insn = next_nonnote_insn (try_insn)) - { - rtx set; - int range; - rtx new_equiv = NULL_RTX; - - if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN) - break; - - set = single_set (try_insn); - if (set == NULL_RTX) - break; - - range = MAX (GET_MODE_SIZE (GET_MODE (equiv)), - GET_MODE_SIZE (GET_MODE (XEXP (set, 0)))); - - if (GET_CODE (equiv) == REG - && REGNO (equiv) == REG_W - && (recog_memoized (try_insn) < 0 - || get_attr_clobberw (try_insn) != CLOBBERW_NO) - && (! (GET_CODE (XEXP (set, 0)) == REG - && REGNO (XEXP (set, 0)) == REG_W - && rtx_equal_p (XEXP (set, 1), orig)))) - break; - else if (GET_CODE (XEXP (set, 0)) == REG - && (REGNO (XEXP (set, 0)) == REG_SP - || ! ip2k_xexp_not_uses_reg_p (equiv, REGNO (XEXP (set, 0)), - range) - || ! ip2k_xexp_not_uses_reg_p (orig, REGNO (XEXP (set, 0)), - range)) - && ! rtx_equal_p (equiv, XEXP (set, 0)) - && ! rtx_equal_p (orig, XEXP (set, 0))) - break; - else if (GET_CODE (orig) == REG - && (REGNO (orig) == REG_IPL - || REGNO (orig) == REG_IPH - || REGNO (orig) == REG_DPL - || REGNO (orig) == REG_DPH) - && (! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 0), - REGNO (orig)) - || ! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 1), - REGNO (orig)))) - break; - else if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (equiv) == MEM) - { - if (! ip2k_xexp_not_uses_reg_p (equiv, REG_SP, 2)) - { - if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2)) - { - /* We look for a special case of "push" operations screwing - our register equivalence when it's based on a stack slot. - We can track this one and replace the old equivalence - expression with a new one. */ - if (GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && GET_CODE (XEXP (equiv, 0)) == PLUS - && REGNO (XEXP (XEXP (equiv, 0), 0)) == REG_SP) - { - int md_size = GET_MODE_SIZE (GET_MODE (XEXP (set, 0))); - int new_sp_offs = INTVAL (XEXP (XEXP (equiv, 0), 1)) - + md_size; - - /* Don't allow an invalid stack pointer offset to be - created. */ - if (new_sp_offs > (128 - 2 * md_size)) - break; - - new_equiv - = gen_rtx_MEM (GET_MODE (equiv), - gen_rtx_PLUS (Pmode, - gen_rtx_REG (HImode , - REG_SP), - GEN_INT (new_sp_offs))); - } - else if (! rtx_equal_p (equiv, XEXP (set, 0))) - { - /* Look at the SP offsets and look for any overlaps. */ - int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS - ? INTVAL (XEXP (XEXP (equiv, 0), 1)) - : 0; - int set_offs - = (GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS - ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1)) - : 0); - - if (abs (equiv_offs - set_offs) < range) - break; - } - } - } - - if (! ip2k_xexp_not_uses_reg_p (equiv, REG_IP, 2)) - break; - - if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_DP, 2) - && ! ip2k_xexp_not_uses_reg_p (equiv, REG_DP, 2) - && ! rtx_equal_p (equiv, XEXP (set, 0))) - { - /* Look at the DP offsets and look for any overlaps. */ - int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS - ? INTVAL (XEXP (XEXP (equiv, 0), 1)) - : 0; - int set_offs = GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS - ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1)) - : 0; - - if (abs (equiv_offs - set_offs) < range) - break; - } - } - - validate_replace_rtx_subexp (orig, equiv, try_insn, &XEXP (set, 1)); - - if (rtx_equal_p (equiv, XEXP (set, 0)) - || rtx_equal_p (orig, XEXP (set, 0))) - break; - - if (new_equiv != NULL_RTX) - equiv = new_equiv; - } -} - -/* Try propagating move instructions forwards. It may be that we can - replace a register use with an equivalent expression that already - holds the same value and thus allow one or more register loads to - be eliminated. */ - -static void -mdr_try_propagate_move (first_insn) - rtx first_insn; -{ - rtx insn; - rtx set; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) != INSN) - continue; - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - /* Have we found a simple move instruction? */ - if (GET_CODE (XEXP (set, 0)) == REG - && (REGNO (XEXP (set, 0)) >= 0x80 - || REGNO (XEXP (set, 0)) == REG_DPL - || REGNO (XEXP (set, 0)) == REG_DPH - || REGNO (XEXP (set, 0)) == REG_IPL - || REGNO (XEXP (set, 0)) == REG_IPH) - && ((GET_CODE (XEXP (set, 1)) == REG - && REGNO (XEXP (set, 1)) != REG_SP - && ip2k_xexp_not_uses_reg_p (XEXP (set, 0), - REGNO (XEXP (set, 1)), - GET_MODE_SIZE (GET_MODE (XEXP (set, - 0))))) - || (GET_CODE (XEXP (set, 1)) == MEM - && (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_IP, 2) - || GET_MODE (XEXP (set, 1)) == QImode) - && ((REGNO (XEXP (set, 0)) != REG_DPH - && REGNO (XEXP (set, 0)) != REG_DPL) - || ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2))) - || (GET_CODE (XEXP (set, 1)) == CONST_INT - && (GET_MODE (XEXP (set, 0)) != QImode - || INTVAL (XEXP (set, 1)) != 0)) - || GET_CODE (XEXP (set, 1)) == CONST_DOUBLE - || GET_CODE (XEXP (set, 1)) == CONST - || GET_CODE (XEXP (set, 1)) == SYMBOL_REF)) - { - mdr_try_propagate_move_sequence (insn, XEXP (set, 0), XEXP (set, 1)); - } - } -} - -/* Try to remove redundant instructions. */ - -static void -mdr_try_remove_redundant_insns (first_insn) - rtx first_insn; -{ - rtx insn; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - rtx set; - enum machine_mode mode; - int md_size; - HOST_WIDE_INT pattern; - int i; - - if (GET_CODE (insn) != INSN) - continue; - - if (GET_CODE (PATTERN (insn)) == CONST_INT) - { - /* We've found a dummy expression. */ - rtx remove_insn = insn; - insn = prev_nonnote_insn (insn); - delete_insn (remove_insn); - continue; - } - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - continue; - - mode = GET_MODE (XEXP (set, 0)); - md_size = GET_MODE_SIZE (mode); - if ((md_size < 1) || (md_size > 4)) - continue; - - pattern = 0; - for (i = 0; i < md_size; i++) - { - pattern <<= 8; - pattern |= 0xff; - } - - if ((GET_CODE (XEXP (set, 1)) == AND - && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (set, 1), 1)) == pattern) - || ((GET_CODE (XEXP (set, 1)) == IOR - || GET_CODE (XEXP (set, 1)) == XOR) - && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (set, 1), 1)) == 0x00)) - { - /* We've found an AND with all 1's, an XOR with all 0's or an - IOR with 0's. */ - rtx remove_insn = insn; - - /* Is it completely redundant or should it become a move insn? */ - if (! rtx_equal_p (XEXP (set, 0), XEXP (XEXP (set, 1), 0))) - { - emit_insn_before (gen_rtx_SET (mode, - XEXP (set, 0), - XEXP (XEXP (set, 1), 0)), - insn); - } - - insn = prev_nonnote_insn(insn); - delete_insn (remove_insn); - } - else if (GET_CODE (XEXP (set, 1)) == AND - && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT - && INTVAL (XEXP (XEXP (set, 1), 1)) == 0) - { - /* We've found an AND with all 0's. */ - rtx remove_insn = insn; - insn = emit_insn_before (gen_rtx_SET (mode, - XEXP (set, 0), - XEXP (XEXP (set, 1), 1)), - insn); - delete_insn (remove_insn); - } - } -} - -/* Structure used to track jump targets. */ - -struct we_jump_targets -{ - int target; /* Is this a jump target? */ - int reach_count; /* Number of ways we can reach this insn. */ - int touch_count; /* Number of times we've touched this insn - during scanning. */ - rtx w_equiv; /* WREG-equivalence at this point. */ -}; - -struct we_jump_targets *ip2k_we_jump_targets; - -/* WREG equivalence tracking used within DP reload elimination. */ - -static int -track_w_reload (insn, w_current, w_current_ok, modifying) - rtx insn; - rtx *w_current; - int w_current_ok; - int modifying; -{ - rtx set; - - if (GET_CODE (insn) != INSN) - { - *w_current = NULL_RTX; - return 1; - } - - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if (set == NULL_RTX) - { - *w_current = NULL_RTX; - return 1; - } - - /* Look for W being modified. If it is, see if it's being changed - to what it already is! */ - if (GET_CODE (XEXP (set, 0)) == REG - && REGNO (XEXP (set, 0)) == REG_W - && GET_MODE (XEXP (set, 0)) == QImode) - { - /* If this is an equivalence we can delete the new set operation. */ - if (*w_current != NULL_RTX - && rtx_equal_p (XEXP (set, 1), *w_current)) - { - if (modifying) - delete_insn (insn); - } - else - { - *w_current = XEXP (set, 1); - return 1; - } - } - else if (recog_memoized (insn) < 0 - || get_attr_clobberw (insn) != CLOBBERW_NO) - { - /* If we clobber W then we've clobbered any equivalences ! */ - *w_current = NULL_RTX; - return 1; - } - else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2) - && *w_current != NULL_RTX - && !ip2k_xexp_not_uses_reg_p (*w_current, REG_SP, 2)) - { - /* We look for a special case of "push" operations screwing up the - setting of DP when it's based on the stack. We can track this one - and replace the old expression for DP with a new one. */ - if (GET_CODE (XEXP (set, 0)) == MEM - && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC - && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP - && GET_CODE (*w_current) == MEM - && GET_CODE (XEXP (*w_current, 0)) == PLUS) - { - /* XXX - need to ensure that we can track this without going - out of range! */ - rtx val = GEN_INT (INTVAL (XEXP (XEXP (*w_current, 0), 1)) - + GET_MODE_SIZE (GET_MODE (XEXP (set, 0)))); - *w_current - = gen_rtx_MEM (HImode, gen_rtx_PLUS (Pmode, - gen_rtx_REG(HImode, REG_SP), - val)); - return 1; - } - } - else if (GET_CODE (XEXP (set, 0)) == REG - && *w_current != NULL_RTX - && !ip2k_xexp_not_uses_reg_p (*w_current, REGNO (XEXP (set, 0)), - GET_MODE_SIZE (GET_MODE (XEXP (set - , 0))))) - { - /* If we've just clobbered all or part of a register reference that we - were sharing for W then we can't share it any more! */ - *w_current = NULL_RTX; - } - - return w_current_ok; -} - -/* As part of the machine-dependent reorg we scan moves into w and track them - to see where any are redundant. */ - -static void -mdr_try_wreg_elim (first_insn) - rtx first_insn; -{ - rtx insn; - struct we_jump_targets *wjt; - rtx w_current; - int incomplete_scan; - int last_incomplete_scan; - - ip2k_we_jump_targets - = (struct we_jump_targets *) xcalloc (get_max_uid (), - sizeof (struct we_jump_targets)); - - /* First we scan to build up a list of all CODE_LABEL insns and we work out - how many different ways we can reach them. */ - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - wjt = &ip2k_we_jump_targets[INSN_UID (insn)]; - wjt->target = 1; - wjt->reach_count = LABEL_NUSES (insn); - wjt->touch_count = 0; - wjt->w_equiv = NULL_RTX; - if (! prev_nonnote_insn (insn) - || (prev_nonnote_insn (insn) - && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)) - wjt->reach_count++; - } - } - - /* Next we scan all of the ways of reaching the code labels to see - what the WREG register is equivalent to as we reach them. If we find - that they're the same then we keep noting the matched value. We - iterate around this until we reach a convergence on WREG equivalences - at all code labels - we have to be very careful not to be too - optimistic! */ - incomplete_scan = -1; - do - { - int w_current_ok = 0; - last_incomplete_scan = incomplete_scan; - w_current = NULL_RTX; - - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - /* If we have a code label then we need to see if we already know - what the equivalence is at this point. If we do then we use it - immediately, but if we don't then we have a special case to track - when we hit a fallthrough-edge (label with no barrier preceding - it). Any other accesses to the label must be from jump insns - and so they're handled elsewhere. */ - if (GET_CODE (insn) == CODE_LABEL) - { - wjt = &ip2k_we_jump_targets[INSN_UID (insn)]; - - /* If we're fully characterized the use the equivalence. */ - if (wjt->touch_count == wjt->reach_count) - { - w_current = wjt->w_equiv; - w_current_ok = 1; - continue; - } - - /* If we have a known equivalence for WREG as we reach the - fallthrough-edge then track this into the code label. */ - if (w_current_ok - && (! prev_nonnote_insn (insn) - || (prev_nonnote_insn (insn) - && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))) - { - if (wjt->touch_count == 0) - wjt->w_equiv = w_current; - - if (wjt->touch_count < wjt->reach_count) - { - wjt->touch_count++; - if (! rtx_equal_p (wjt->w_equiv, w_current)) - { - /* When we definitely know that we can't form an - equivalence for WREG here we must clobber anything - that we'd started to track too. */ - wjt->w_equiv = NULL_RTX; - w_current = NULL_RTX; - w_current_ok = 1; - } - } - } - - /* If we've not completely characterized this code label then - be cautious and assume that we don't know what WREG is - equivalent to. */ - if (wjt->touch_count < wjt->reach_count) - { - w_current = NULL_RTX; - w_current_ok = 0; - } - - continue; - } - - /* If we've hit a jump insn then we look for either an address - vector (jump table) or for jump label references. */ - if (GET_CODE (insn) == JUMP_INSN) - { - /* Don't attempt to track here if we don't have a known - equivalence for WREG at this point. */ - if (w_current_ok) - { - if (JUMP_LABEL (insn)) - { - wjt - = &ip2k_we_jump_targets[INSN_UID (JUMP_LABEL (insn))]; - - if (wjt->touch_count == 0) - wjt->w_equiv = w_current; - - if (wjt->touch_count < wjt->reach_count) - { - wjt->touch_count++; - if (! rtx_equal_p (wjt->w_equiv, w_current)) - wjt->w_equiv = NULL_RTX; - } - } - } - - continue; - } - - /* Anything other than a code labal or jump arrives here. We try and - track WREG, but sometimes we might not be able to. */ - w_current_ok = track_w_reload (insn, &w_current, w_current_ok, 0); - } - - /* When we're looking to see if we've finished we count the number of - paths throught the code labels where we weren't able to definitively - track WREG. This number is used to see if we're converging on a - solution. - If this hits zero then we've fully converged, but if this stays the - same as last time then we probably can't make any further - progress. */ - incomplete_scan = 0; - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - wjt = &ip2k_we_jump_targets[INSN_UID (insn)]; - if (wjt->touch_count != wjt->reach_count) - { - incomplete_scan += (wjt->reach_count - wjt->touch_count); - wjt->w_equiv = NULL_RTX; - wjt->touch_count = 0; - } - } - } - } - while (incomplete_scan && incomplete_scan != last_incomplete_scan); - - /* Finally we scan the whole function and run WREG elimination. When we hit - a CODE_LABEL we pick up any stored equivalence since we now know that - every path to this point entered with WREG holding the same thing! If - we subsequently have a reload that matches then we can eliminate it. */ - w_current = NULL_RTX; - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == JUMP_INSN) - continue; - - if (GET_CODE (insn) == CODE_LABEL) - { - wjt = &ip2k_we_jump_targets[INSN_UID (insn)]; - w_current = wjt->w_equiv; - continue; - } - - track_w_reload (insn, &w_current, 1, 1); - } - - free (ip2k_we_jump_targets); -} -#endif /* IP2K_MD_REORG_PASS */ - -/* We perform a lot of untangling of the RTL within the reorg pass since - the IP2k requires some really bizarre (and really undesireable) things - to happen in order to guarantee not aborting. This pass causes several - earlier passes to be re-run as it progressively transforms things, - making the subsequent runs continue to win. */ - -void -machine_dependent_reorg (first_insn) - rtx first_insn ATTRIBUTE_UNUSED; -{ -#ifdef IP2K_MD_REORG_PASS - rtx insn, set; -#endif - - CC_STATUS_INIT; - - if (optimize == 0) - { - ip2k_reorg_completed = 1; - ip2k_reorg_split_dimode = 1; - ip2k_reorg_split_simode = 1; - ip2k_reorg_split_himode = 1; - ip2k_reorg_split_qimode = 1; - ip2k_reorg_merge_qimode = 1; - return; - } -#ifndef IP2K_MD_REORG_PASS - ip2k_reorg_completed = 1; - ip2k_reorg_split_dimode = 1; - ip2k_reorg_split_simode = 1; - ip2k_reorg_split_himode = 1; - ip2k_reorg_split_qimode = 1; - ip2k_reorg_merge_qimode = 1; -#else - /* All optimizations below must be debugged and enabled one by one. - All of them commented now because of abort in GCC core. */ - - ip2k_reorg_in_progress = 1; - - /* Look for size effects of earlier optimizations - in particular look for - situations where we're saying "use" a register on one hand but immediately - tagging it as "REG_DEAD" at the same time! Seems like a bug in core-gcc - somewhere really but this is what we have to live with! */ - for (insn = first_insn; insn; insn = NEXT_INSN (insn)) - { - rtx body; - - if (GET_CODE (insn) == CODE_LABEL - || GET_CODE (insn) == NOTE - || GET_CODE (insn) == BARRIER) - continue; - - if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') - continue; - - body = PATTERN (insn); - if (GET_CODE (body) == USE) - if (GET_CODE (XEXP (body, 0)) == REG) - { - int reg; - - reg = REGNO (XEXP (body, 0)); - if (find_regno_note (insn, REG_DEAD, reg)) - { - delete_insn (insn); - } - } - } - - /* There's a good chance that since we last did CSE that we've rearranged - things in such a way that another go will win. Do so now! */ - reload_cse_regs (first_insn); - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_REG_INFO | PROP_DEATH_NOTES); - - /* Look for where absurd things are happening with DP. */ - mdr_try_dp_reload_elim (first_insn); - - ip2k_reorg_in_progress = 0; - ip2k_reorg_completed = 1; - - split_all_insns (0); - - reload_cse_regs (first_insn); - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_REG_INFO | PROP_DEATH_NOTES); - if (flag_peephole2) - peephole2_optimize (NULL); - - mdr_resequence_xy_yx (first_insn); - mdr_propagate_reg_equivs (first_insn); - - /* Look for redundant set instructions. These can occur when we split - instruction patterns and end up with the second half merging with - or being replaced by something that clobbers the first half. */ - for (insn = first_insn; insn; insn = next_nonnote_insn (insn)) - { - if (GET_CODE (insn) == INSN) - { - set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX; - if ((set != NULL_RTX) - && (GET_CODE (XEXP (set, 0)) == REG) - && (GET_MODE (XEXP (set, 0)) == QImode) - && (find_regno_note (insn, REG_UNUSED, REGNO (XEXP (set, 0))))) - delete_insn (insn); - } - } - - mdr_try_move_dp_reload (first_insn); - mdr_try_move_pushes (first_insn); - - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_FINAL); - - mdr_try_propagate_move (first_insn); - mdr_resequence_xy_yx (first_insn); - - ip2k_reorg_split_dimode = 1; - split_all_insns (0); - - mdr_try_remove_redundant_insns (first_insn); - - mdr_try_propagate_move (first_insn); - - reload_cse_regs (first_insn); - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_FINAL); - if (flag_peephole2) - peephole2_optimize (NULL); - - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_FINAL); - - ip2k_reorg_split_simode = 1; - split_all_insns (0); - - mdr_try_remove_redundant_insns (first_insn); - - mdr_try_propagate_move (first_insn); - - reload_cse_regs (first_insn); - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_FINAL); - if (flag_peephole2) - peephole2_optimize (NULL); - - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_FINAL); - - ip2k_reorg_split_himode = 1; - ip2k_reorg_merge_qimode = 1; - split_all_insns (0); - - mdr_try_remove_redundant_insns (first_insn); - mdr_try_propagate_clr (first_insn); - mdr_try_propagate_move (first_insn); - - mdr_try_dp_reload_elim (first_insn); - mdr_try_move_dp_reload (first_insn); - - rebuild_jump_labels (first_insn); - - /* Call to jump_optimize (...) was here, but now I removed it. */ - - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_FINAL); - if (flag_peephole2) - peephole2_optimize (NULL); - - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_FINAL); - mdr_try_remove_redundant_insns (first_insn); - - mdr_try_propagate_clr (first_insn); - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_FINAL); - - ip2k_reorg_split_qimode = 1; - split_all_insns (0); - - mdr_try_wreg_elim (first_insn); - mdr_try_propagate_move (first_insn); - - find_basic_blocks (first_insn, max_reg_num (), 0); - life_analysis (first_insn, 0, PROP_FINAL); -#endif -} - -/* Returns a bit position if mask contains only a single bit. Returns -1 if - there were zero or more than one set bits. */ -int -find_one_set_bit_p (mask) - HOST_WIDE_INT mask; -{ - int i; - unsigned HOST_WIDE_INT n = mask; - for (i = 0; i < 32; i++) - { - if (n & 0x80000000UL) - { - if (n & 0x7fffffffUL) - return -1; - else - return 31 - i; - } - n <<= 1; - } - return -1; -} - -/* Returns a bit position if mask contains only a single clear bit. - Returns -1 if there were zero or more than one clear bits. */ -int -find_one_clear_bit_p (mask) - HOST_WIDE_INT mask; -{ - int i; - unsigned HOST_WIDE_INT n = mask; - for (i = 0; i < 32; i++) - { - if ((n & 0x80000000UL) == 0UL) - { - if ((n & 0x7fffffffUL) != 0x7fffffffUL) - return -1; - else - return 31 - i; - } - n <<= 1; - n |= 1; - } - return -1; -} - - -/* Split a move into two smaller pieces. - MODE indicates the reduced mode. OPERANDS[0] is the original destination - OPERANDS[1] is the original src. The new destinations are - OPERANDS[2] and OPERANDS[4], while the new sources are OPERANDS[3] - and OPERANDS[5]. */ - -void -ip2k_split_words (nmode, omode, operands) - enum machine_mode nmode; - enum machine_mode omode; - rtx *operands; -{ - rtx dl, dh; /* src/dest pieces. */ - rtx sl, sh; - int move_high_first = 0; /* Assume no overlap. */ - int pushflag = 0; - - switch (GET_CODE (operands[0])) /* DEST */ - { - case SUBREG: - case REG: - if ((GET_CODE (operands[1]) == REG - || GET_CODE (operands[1]) == SUBREG) - && (true_regnum (operands[0]) <= true_regnum (operands[1]) - || (true_regnum (operands[1]) - + GET_MODE_SIZE (omode) - 1 < true_regnum (operands[0])))) - move_high_first = 1; - - if (GET_CODE (operands[0]) == SUBREG) - { - dl = simplify_gen_subreg (nmode, operands[0], omode, - GET_MODE_SIZE (nmode)); - dh = simplify_gen_subreg (nmode, operands[0], omode, 0); - } - else if (GET_CODE (operands[0]) == REG && ! IS_PSEUDO_P (operands[0])) - { - int r = REGNO (operands[0]); - dh = gen_rtx_REG (nmode, r); - dl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode)); - } - else - { - dh = gen_rtx_SUBREG (nmode, operands[0], 0); - dl = gen_rtx_SUBREG (nmode, operands[0], GET_MODE_SIZE (nmode)); - } - break; - - case MEM: - switch (GET_CODE (XEXP (operands[0], 0))) - { - case POST_INC: - abort (); - case POST_DEC: - dl = dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0)); - pushflag = 1; - break; - default: - dl = change_address (operands[0], nmode, - plus_constant (XEXP (operands[0], 0), - GET_MODE_SIZE (nmode))); - dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0)); - } - break; - default: - abort (); - } - - switch (GET_CODE (operands[1])) - { - case REG: - if (! IS_PSEUDO_P (operands[1])) - { - int r = REGNO (operands[1]); - - sh = gen_rtx_REG (nmode, r); - sl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode)); - } - else - { - sh = gen_rtx_SUBREG (nmode, operands[1], 0); - sl = gen_rtx_SUBREG (nmode, operands[1], GET_MODE_SIZE (nmode)); - } - break; - - case CONST_DOUBLE: - if (operands[1] == const0_rtx) - sh = sl = const0_rtx; - else - { - if (GET_MODE (operands[0]) != DImode) - { - REAL_VALUE_TYPE rv; - long value; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_SINGLE (rv, value); - - sh = gen_int_mode ((value >> 16) & 0xffff, nmode); - sl = gen_int_mode (value & 0xffff, nmode); - } - else - { - sh = gen_int_mode (CONST_DOUBLE_HIGH (operands[1]), nmode); - sl = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), nmode); - } - } - break; - - case CONST_INT: - if (operands[1] == const0_rtx) - sh = sl = const0_rtx; - else - { - int val = INTVAL (operands[1]); - int vl, vh; - - switch (nmode) - { - case QImode: - vh = (val >> 8) & 0xff; - vl = val & 0xff; - break; - - case HImode: - vh = (val >> 16) & 0xffff; - vl = val & 0xffff; - break; - - case SImode: - if (val < 0) /* sign extend */ - vh = -1; - else - vh = 0; - vl = val; /* Give low 32 bits back. */ - break; - - default: - abort (); - } - - sl = gen_int_mode (vl, nmode); - sh = gen_int_mode (vh, nmode); - } - break; - - case SUBREG: - sl = simplify_gen_subreg (nmode, operands[1], omode, - GET_MODE_SIZE (nmode)); - sh = simplify_gen_subreg (nmode, operands[1], omode, 0); - break; - - case MEM: - switch (GET_CODE (XEXP (operands[1], 0))) - { - case POST_DEC: - case POST_INC: - abort (); - break; - - default: - /* Worry about splitting stack pushes. */ - if (pushflag && ip2k_address_uses_reg_p (operands[1], REG_SP)) - sl = sh = change_address (operands[1], nmode, - plus_constant (XEXP (operands[1], 0), - GET_MODE_SIZE (nmode))); - else - { - sl = change_address (operands[1], nmode, - plus_constant (XEXP (operands[1], 0), - GET_MODE_SIZE (nmode))); - sh = gen_rtx_MEM (nmode, XEXP (operands[1], 0)); - } - } - break; - - default: - abort (); - } - - if (move_high_first) - { - operands[2] = dh; - operands[3] = sh; - operands[4] = dl; - operands[5] = sl; - } - else - { - operands[2] = dl; - operands[3] = sl; - operands[4] = dh; - operands[5] = sh; - } - return; -} - -/* Get the low half of an operand. */ -rtx -ip2k_get_low_half (x, mode) - rtx x; - enum machine_mode mode; -{ - switch (GET_CODE (x)) - { - case REG: - if (! IS_PSEUDO_P (x)) - { - unsigned int r = REGNO (x); - - return gen_rtx_REG (mode, r + HARD_REGNO_NREGS (r, mode)); - } - else - { - return gen_rtx_SUBREG (mode, x, GET_MODE_SIZE (mode)); - } - break; - - case CONST_DOUBLE: - if (x == const0_rtx) - return const0_rtx; - else - { - if (mode != SImode) - { - REAL_VALUE_TYPE rv; - long value; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, value); - - return gen_int_mode (value & 0xffff, mode); - } - else - return gen_int_mode (CONST_DOUBLE_LOW (x), mode); - } - break; - - case CONST_INT: - if (x == const0_rtx) - return const0_rtx; - else - { - int val = INTVAL (x); - int vl, vh; - - switch (mode) - { - case QImode: - vh = (val >> 8) & 0xff; - vl = val & 0xff; - break; - - case HImode: - vh = (val >> 16) & 0xffff; - vl = val & 0xffff; - break; - - case SImode: - if (val < 0) /* sign extend */ - vh = -1; - else - vh = 0; - vl = val; /* Give low 32 bits back. */ - break; - - default: - abort (); - } - - return gen_int_mode (vl, mode); - } - break; - - case SUBREG: - return simplify_gen_subreg (mode, x, GET_MODE (x), GET_MODE_SIZE (mode)); - - case MEM: - switch (GET_CODE (XEXP (x, 0))) - { - case POST_DEC: - case POST_INC: - abort (); - break; - - default: - return change_address (x, mode, - plus_constant (XEXP (x, 0), - GET_MODE_SIZE (mode))); - } - break; - - default: - abort (); - } - return NULL_RTX; -} - -/* Get the high half of an operand. */ -rtx -ip2k_get_high_half (x, mode) - rtx x; - enum machine_mode mode; -{ - switch (GET_CODE (x)) - { - case REG: - if (! IS_PSEUDO_P (x)) - { - unsigned int r = REGNO (x); - - return gen_rtx_REG (mode, r); - } - else - { - return gen_rtx_SUBREG (mode, x, 0); - } - break; - - case CONST_DOUBLE: - if (x == const0_rtx) - return const0_rtx; - else - { - if (mode != SImode) - { - REAL_VALUE_TYPE rv; - long value; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, value); - - return gen_int_mode ((value >> 16) & 0xffff, mode); - } - else - return gen_int_mode (CONST_DOUBLE_HIGH (x), mode); - } - break; - - case CONST_INT: - if (x == const0_rtx) - return const0_rtx; - else - { - int val = INTVAL (x); - int vl, vh; - - switch (mode) - { - case QImode: - vh = (val >> 8) & 0xff; - vl = val & 0xff; - break; - - case HImode: - vh = (val >> 16) & 0xffff; - vl = val & 0xffff; - break; - - case SImode: - if (val < 0) /* sign extend */ - vh = -1; - else - vh = 0; - vl = val; /* Give low 32 bits back. */ - break; - - default: - abort (); - } - - return gen_int_mode (vh, mode); - } - break; - - case SUBREG: - return simplify_gen_subreg (mode, x, GET_MODE (x), 0); - break; - - case MEM: - switch (GET_CODE (XEXP (x, 0))) - { - case POST_DEC: - case POST_INC: - abort (); - break; - - default: - return change_address (x, mode, plus_constant (XEXP (x, 0), 0)); - } - break; - - default: - abort (); - } - return NULL_RTX; -} - -/* Does address X use register R. Only valid for REG_SP, REG_DP, REG_IP - or REG_FP. */ - -int -ip2k_address_uses_reg_p (x, r) - rtx x; - unsigned int r; -{ - if (GET_CODE (x) != MEM) - return 0; - - x = XEXP (x, 0); - - while (1) - switch (GET_CODE (x)) - { - case POST_DEC: - case POST_INC: - case PRE_DEC: - case PRE_INC: - x = XEXP (x, 0); - break; - - case PLUS: - if (ip2k_address_uses_reg_p (XEXP (x, 1), r)) - return 1; - - x = XEXP (x, 0); - break; - - case SUBREG: - /* Ignore subwords. */ - x = SUBREG_REG (x); - break; - - case REG: - /* Have to consider that r might be LSB of a pointer reg. */ - return ((REGNO (x) == r) || (REGNO (x) == (r - 1))) ? 1 : 0; - - case MEM: - /* We might be looking at a (mem:BLK (mem (...))) */ - x = XEXP (x, 0); - break; - - default: - return 0; - }; -} - -/* Does the queried XEXP not use a particular register? If we're certain - that it doesn't then we return TRUE otherwise we assume FALSE. */ - -int -ip2k_xexp_not_uses_reg_p (x, r, rsz) - rtx x; - unsigned int r; - int rsz; -{ - switch (GET_CODE (x)) - { - case REG: - { - int msz = GET_MODE_SIZE (GET_MODE (x)); - - return (((REGNO (x) + msz - 1) < r) - || (REGNO (x) > (r + rsz - 1))); - } - - case MEM: - return !ip2k_address_uses_reg_p (x, r); - - case LABEL_REF: - case SYMBOL_REF: - case CONST: - case CONST_INT: - case CONST_DOUBLE: - case CC0: - case PC: - return 1; - - default: - return 0; - } -} - -/* Does the queried XEXP not use a particular register? If we're certain - that it doesn't then we return TRUE otherwise we assume FALSE. */ - -int -ip2k_composite_xexp_not_uses_reg_p (x, r, rsz) - rtx x; - unsigned int r; - int rsz; -{ - if (GET_RTX_CLASS (GET_CODE (x)) == 'b') - return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 2), r, rsz)); - - if (GET_RTX_CLASS (GET_CODE (x)) == '2' - || GET_RTX_CLASS (GET_CODE (x)) == 'c' - || GET_RTX_CLASS (GET_CODE (x)) == '<') - return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz) - && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz)); - - if (GET_RTX_CLASS (GET_CODE (x)) == '1' - || GET_RTX_CLASS (GET_CODE (x)) == '3') - return ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz); - - return ip2k_xexp_not_uses_reg_p (x, r, rsz); -} - -/* Does the queried XEXP not use CC0? If we're certain that - it doesn't then we return TRUE otherwise we assume FALSE. */ - -int -ip2k_composite_xexp_not_uses_cc0_p (x) - rtx x; -{ - if (GET_RTX_CLASS (GET_CODE (x)) == 'b') - return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0)) - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1)) - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 2))); - - if (GET_RTX_CLASS (GET_CODE (x)) == '2' - || GET_RTX_CLASS (GET_CODE (x)) == 'c' - || GET_RTX_CLASS (GET_CODE (x)) == '<') - return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0)) - && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1))); - - if (GET_RTX_CLASS (GET_CODE (x)) == '1' - || GET_RTX_CLASS (GET_CODE (x)) == '3') - return ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0)); - - return GET_CODE (x) != CC0; -} - -int -ip2k_split_dest_operand (x, mode) - rtx x; - enum machine_mode mode; -{ - return nonimmediate_operand (x, mode) || push_operand (x, mode); -} - -int -ip2k_nonptr_operand (x, mode) - rtx x; - enum machine_mode mode; -{ - return register_operand (x, mode) && !ip2k_ptr_operand (x, mode); -} - -/* Is X a reference to IP or DP or SP? */ - -int -ip2k_ptr_operand (x, mode) - rtx x; - enum machine_mode mode; - -{ - if (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - return (REG_P (x) - && (mode == HImode || mode == VOIDmode) - && (REGNO (x) == REG_IP - || REGNO (x) == REG_DP - || REGNO (x) == REG_SP)); -} - -int -ip2k_sp_operand (x, mode) - rtx x; - enum machine_mode mode ATTRIBUTE_UNUSED; - -{ - return REG_P (x) && REGNO (x) == REG_SP; -} - -int -ip2k_ip_operand (x, mode) - rtx x; - enum machine_mode mode; - -{ - if (GET_CODE (x) != MEM) - return 0; - - x = XEXP (x, 0); - - if (GET_CODE (x) == PLUS && XEXP (x, 1) == const0_rtx) - x = XEXP (x, 0); - - if (! REG_P (x)) - return 0; - - if (GET_MODE_SIZE (mode) > 1) - return 0; /* Can't access offset bytes. */ - - return REGNO (x) == REG_IP; -} - -/* Is X a memory address suitable for SP or DP relative addressing? */ -int -ip2k_short_operand (x, mode) - rtx x; - enum machine_mode mode; -{ - int r; - unsigned int offs = 0; - - if (! memory_operand (x, mode)) - return 0; /* Got to be a memory address. */ - - x = XEXP (x, 0); - switch (GET_CODE (x)) - { - default: - return 0; - - case PLUS: - if (! REG_P (XEXP (x, 0)) - || GET_CODE (XEXP (x, 1)) != CONST_INT) - return 0; - - offs = INTVAL (XEXP (x, 1)); - - if (128 <= offs) - return 0; - - x = XEXP (x, 0); - - /* fall thru */ - - case REG: - if (IS_PSEUDO_P (x)) - return 0; /* Optimistic - doesn't work. */ - - r = REGNO (x); - - /* For 'S' constraint, we presume that no IP adjustment - simulation is performed - so only QI mode allows IP to be a - short offset address. All other IP references must be - handled by 'R' constraints. */ - if (r == REG_IP && offs == 0 && GET_MODE_SIZE (mode) <= 1) - return 1; - - return (r == REG_SP || r == REG_DP); - } -} - -int -ip2k_nonsp_reg_operand (x, mode) - rtx x; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (x) == SUBREG) - x = SUBREG_REG (x); - - return (REG_P (x) && REGNO (x) != REG_SP); -} - -int -ip2k_gen_operand (x, mode) - rtx x; - enum machine_mode mode; -{ - return ip2k_short_operand (x, mode) - || (GET_CODE (x) == SUBREG - && REG_P (SUBREG_REG (x))) - || (ip2k_nonsp_reg_operand (x, mode)); -} - -int -ip2k_extra_constraint (x, c) - rtx x; - int c; -{ - switch (c) - { - case 'S': /* Allow offset in stack frame... */ - return ip2k_short_operand (x, GET_MODE (x)); - - case 'R': - return ip2k_ip_operand (x, GET_MODE (x)); - - case 'T': /* Constant int or .data address. */ - return CONSTANT_P (x) && is_regfile_address (x); - - default: - return 0; - } -} - -int -ip2k_unary_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - return ((mode == VOIDmode || GET_MODE (op) == mode) - && GET_RTX_CLASS (GET_CODE (op)) == '1'); -} - -int -ip2k_binary_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - return ((mode == VOIDmode || GET_MODE (op) == mode) - && (GET_RTX_CLASS (GET_CODE (op)) == 'c' - || GET_RTX_CLASS (GET_CODE (op)) == '2')); -} - -int -ip2k_symbol_ref_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - /* We define an IP2k symbol ref to be either a direct reference or one - with a constant offset. */ - return (GET_CODE (op) == SYMBOL_REF) - || (GET_CODE (op) == CONST - && GET_CODE (XEXP (op, 0)) == PLUS - && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF); -} - -int -ip2k_signed_comparison_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - return (comparison_operator (op, mode) - && signed_condition (GET_CODE (op)) == GET_CODE (op)); -} - -int -ip2k_unsigned_comparison_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - return (comparison_operator (op, mode) - && unsigned_condition (GET_CODE (op)) == GET_CODE (op)); -} diff --git a/gcc/config/ip2k/ip2k.h b/gcc/config/ip2k/ip2k.h deleted file mode 100644 index cda748744d2..00000000000 --- a/gcc/config/ip2k/ip2k.h +++ /dev/null @@ -1,2523 +0,0 @@ -/* Definitions of target machine for GNU compiler, - For Ubicom IP2022 Communications Controller - - Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. - Contributed by Red Hat, Inc and Ubicom, 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. */ - - -/* Set up System V.4 (aka ELF) defaults. */ - -#include "elfos.h" -#undef ASM_SPEC /* But we have a GAS assembler. */ - -#define CPP_PREDEFINES \ - "-DIP2K -D_DOUBLE_IS_32BITS -D__BUFSIZ__=512 -D__FILENAME_MAX__=128" -/* 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. */ - - -/* This declaration should be present. */ -extern int target_flags; - -/* `TARGET_...' - 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 TARGET_SWITCHES {{"",0, NULL}} -/* 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}} */ - - -/* 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_VERSION fprintf (stderr, " (ip2k, GNU assembler syntax)") -/* 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 */ - -/* Caller-saves is not a win for the IP2K. Pretty much anywhere that - a register is permitted allows SP-relative addresses too. - - This machine doesn't have PIC addressing modes, so disable that also. */ - -#define OVERRIDE_OPTIONS \ - do { \ - flag_caller_saves = 0; \ - flag_pic = 0; \ - } while (0) - -/* `OVERRIDE_OPTIONS' - 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. */ - -/* Put each function in its own section so that PAGE-instruction - relaxation can do its best. */ -#define OPTIMIZATION_OPTIONS(LEVEL, SIZEFLAG) \ - do { \ - if ((LEVEL) || (SIZEFLAG)) \ - flag_function_sections = 1; \ - } while (0) - -/* Define this if most significant byte of a word is the lowest numbered. */ -#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 the lowest - numbered. */ -#define WORDS_BIG_ENDIAN 1 - -/* Number of bits in an addressable storage unit. */ -#define BITS_PER_UNIT 8 - -/* Width in bits of a "word", which is the contents of a machine register. - Note that this is not necessarily the width of data type `int'; */ -#define BITS_PER_WORD 8 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD (BITS_PER_WORD / BITS_PER_UNIT) - -/* Width in bits of a pointer. - See also the macro `Pmode' defined below. */ -#define POINTER_SIZE 16 - -/* Maximum sized of reasonable data type DImode or Dfmode ... */ -#define MAX_FIXED_MODE_SIZE 64 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 8 - -/* 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 8 - -/* No data type wants to be aligned rounder than this. */ - -#define BIGGEST_ALIGNMENT 8 - -#define STRICT_ALIGNMENT 0 - -#define PCC_BITFIELD_TYPE_MATTERS 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. */ -#undef INT_TYPE_SIZE -#define INT_TYPE_SIZE 16 - - -/* 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.) */ -#undef SHORT_TYPE_SIZE -#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. */ -#undef LONG_TYPE_SIZE -#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. */ -#undef LONG_LONG_TYPE_SIZE -#define LONG_LONG_TYPE_SIZE 64 - -#undef CHAR_TYPE_SIZE -#define CHAR_TYPE_SIZE 8 -/* 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.) */ - -#undef FLOAT_TYPE_SIZE -#define FLOAT_TYPE_SIZE 32 -/* 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. */ - -#undef DOUBLE_TYPE_SIZE -#define DOUBLE_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. */ - - -/* 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. */ -#undef LONG_DOUBLE_TYPE_SIZE -#define LONG_DOUBLE_TYPE_SIZE 32 - -#define DEFAULT_SIGNED_CHAR 1 -/* 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_SHORT_ENUMS 1 - This was the default for the IP2k but gcc has a bug (as of 17th May - 2001) in the way that library calls to the memory checker functions - are issues that screws things up if an enum is not equivalent to - an int. */ -/* `DEFAULT_SHORT_ENUMS' - 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 SIZE_TYPE "unsigned int" -/* 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"'. */ - -#define PTRDIFF_TYPE "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 WCHAR_TYPE -#define WCHAR_TYPE "int" -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 -/* 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'. */ - -#define HARD_REG_SIZE (UNITS_PER_WORD) -/* Standard register usage. - - for the IP2K, we are going to have a LOT of registers, but only some of them - are named. */ - -#define FIRST_PSEUDO_REGISTER (0x104) /* Skip over physical regs, VFP, AP. */ - -/* 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 REG_IP 0x4 -#define REG_IPH REG_IP -#define REG_IPL 0x5 - -#define REG_SP 0x6 -#define REG_SPH REG_SP -#define REG_SPL 0x7 - -#define REG_PCH 0x8 -#define REG_PCL 0x9 - -#define REG_W 0xa -#define REG_STATUS 0xb - -#define REG_DP 0xc -#define REG_DPH REG_DP -#define REG_DPL 0xd - -#define REG_MULH 0xf - -#define REG_CALLH 0x7e /* Call-stack readout. */ -#define REG_CALLL 0x7f - - -#define REG_RESULT 0x80 /* Result register (upto 8 bytes). */ -#define REG_FP 0xfd /* 2 bytes for FRAME chain */ - -#define REG_ZERO 0xff /* Initialized to zero by runtime. */ - -#define REG_VFP 0x100 /* Virtual frame pointer. */ -#define REG_AP 0x102 /* Virtual arg pointer. */ - -/* Status register bits. */ -#define Z_FLAG 0x2 -#define DC_FLAG 0x1 -#define C_FLAG 0x0 - -#define FIXED_REGISTERS {\ -1,1,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r0.. r31*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r32.. r63*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r64.. r95*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r96..r127*/\ -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,/*r128..r159*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r160..r191*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r192..r223*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r224..r255*/\ -1,1,1,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 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,/* r0.. r31*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r32.. r63*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r64.. r95*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/* r96..r127*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r128..r159*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r160..r191*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r192..r223*/\ -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,/*r224..r255*/\ -1,1,1,1} - -/* 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 NON_SAVING_SETJMP 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 REG_ALLOC_ORDER { \ - 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, \ - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, \ - 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ - 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7, \ - 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, \ - 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7, \ - 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, \ - 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, \ - 0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, \ - 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7, \ - 0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, \ - 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7, \ - 0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, \ - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, \ - 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, \ - 0x00,0x01,0x02,0x03,0x0c,0x0d,0x06,0x07, \ - 0x08,0x09,0x0a,0x0b,0x04,0x05,0x0e,0x0f, \ - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, \ - 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, \ - 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, \ - 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, \ - 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, \ - 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, \ - 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, \ - 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, \ - 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, \ - 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, \ - 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, \ - 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, \ - 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, \ - 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, \ - 0x100,0x101,0x102,0x103} - -/* 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 ORDER_REGS_FOR_LOCAL_ALLOC ip2k_init_local_alloc (reg_alloc_order) -/* 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. */ - -/* Are we allowed to rename registers? For some reason, regrename was - changing DP to IP (when it appeared in addresses like (plus:HI - (reg: DP) (const_int 37)) - and that's bad because IP doesn't - permit offsets! */ - -#define HARD_REGNO_RENAME_OK(REG, NREG) \ - (((REG) == REG_DPH) ? 0 \ - : ((REG) == REG_IPH) ? ((NREG) == REG_DPH) \ - : (((NREG) == REG_IPL) || ((NREG) == REG_DPL)) ? 0 : 1) - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* 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_MODE_OK(REGNO, MODE) 1 -/* 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. */ - -#define MODES_TIEABLE_P(MODE1, MODE2) \ - (((MODE1) == QImode && (MODE2) == HImode) \ - || ((MODE2) == QImode && (MODE1) == HImode)) -/* We originally had this as follows - this isn't a win on the IP2k - though as registers just get in our way! - - #define MODES_TIEABLE_P(MODE1, MODE2) \ - (((MODE1) > HImode && (MODE2) == HImode) - || ((MODE1) == HImode && (MODE2) > HImode)) */ - -/* 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. */ - -enum reg_class { - NO_REGS, - DPH_REGS, - DPL_REGS, - DP_REGS, - SP_REGS, - IPH_REGS, - IPL_REGS, - IP_REGS, - DP_SP_REGS, - PTR_REGS, - NONPTR_REGS, - NONSP_REGS, - GENERAL_REGS, - ALL_REGS = GENERAL_REGS, - LIM_REG_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. */ - - -#define N_REG_CLASSES (int)LIM_REG_CLASSES -/* The number of distinct register classes, defined as follows: - - #define N_REG_CLASSES (int) LIM_REG_CLASSES */ - -#define REG_CLASS_NAMES { \ - "NO_REGS", \ - "DPH_REGS", \ - "DPL_REGS", \ - "DP_REGS", \ - "SP_REGS", \ - "IPH_REGS", \ - "IPL_REGS", \ - "IP_REGS", \ - "DP_SP_REGS", \ - "PTR_REGS", \ - "NONPTR_REGS", \ - "NONSP_REGS", \ - "GENERAL_REGS" \ - } -/* An initializer containing the names of the register classes as C - string constants. These names are used in writing some of the - debugging dumps. */ - - -#define REG_CLASS_CONTENTS { \ -{0x00000000, 0, 0, 0, 0, 0, 0, 0, 0}, /* NO_REGS */ \ -{0x00001000, 0, 0, 0, 0, 0, 0, 0, 0}, /* DPH_REGS */ \ -{0x00002000, 0, 0, 0, 0, 0, 0, 0, 0}, /* DPL_REGS */ \ -{0x00003000, 0, 0, 0, 0, 0, 0, 0, 0}, /* DP_REGS */ \ -{0x000000c0, 0, 0, 0, 0, 0, 0, 0, 0}, /* SP_REGS */ \ -{0x00000010, 0, 0, 0, 0, 0, 0, 0, 0}, /* IPH_REGS */ \ -{0x00000020, 0, 0, 0, 0, 0, 0, 0, 0}, /* IPL_REGS */ \ -{0x00000030, 0, 0, 0, 0, 0, 0, 0, 0}, /* IP_REGS */ \ -{0x000030c0, 0, 0, 0, 0, 0, 0, 0, 0}, /* DP_SP_REGS */ \ -{0x000030f0, 0, 0, 0, 0, 0, 0, 0, 0}, /* PTR_REGS */ \ -{0xffffcf0f,-1,-1,-1,-1,-1,-1,-1, 0}, /* NONPTR_REGS */ \ -{0xffffff3f,-1,-1,-1,-1,-1,-1,-1, 0}, /* NONSP_REGS */ \ -{0xffffffff,-1,-1,-1,-1,-1,-1,-1,15} /* GENERAL_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 REGNO_REG_CLASS(R) \ - ( (R) == REG_IPH ? IPH_REGS \ - : (R) == REG_IPL ? IPL_REGS \ - : (R) == REG_DPH ? DPH_REGS \ - : (R) == REG_DPL ? DPL_REGS \ - : (R) == REG_SPH ? SP_REGS \ - : (R) == REG_SPL ? SP_REGS \ - : NONPTR_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. */ - -#define MODE_BASE_REG_CLASS(MODE) ((MODE) == QImode ? PTR_REGS : DP_SP_REGS) -/* This is a variation of the BASE_REG_CLASS macro which allows - the selection of a base register in a mode depenedent manner. - If MODE is VOIDmode then it should return the same value as - BASE_REG_CLASS. */ - -#define BASE_REG_CLASS PTR_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 INDEX_REG_CLASS NO_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 REG_CLASS_FROM_LETTER(C) \ - ( (C) == 'j' ? IPH_REGS \ - : (C) == 'k' ? IPL_REGS \ - : (C) == 'f' ? IP_REGS \ - : (C) == 'y' ? DPH_REGS \ - : (C) == 'z' ? DPL_REGS \ - : (C) == 'b' ? DP_REGS \ - : (C) == 'u' ? NONSP_REGS \ - : (C) == 'q' ? SP_REGS \ - : (C) == 'c' ? DP_SP_REGS \ - : (C) == 'a' ? PTR_REGS \ - : (C) == 'd' ? NONPTR_REGS \ - : NO_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. */ - - -#define REGNO_OK_FOR_BASE_P(R) \ - ((R) == REG_DP || (R) == REG_IP || (R) == REG_SP) -/* A C expression which is nonzero if register number R 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_MODE_OK_FOR_BASE_P(R,M) \ - ((R) == REG_DP || (R) == REG_SP \ - || ((R) == REG_IP && GET_MODE_SIZE (M) <= 1)) -/* A C expression that is just like `REGNO_OK_FOR_BASE_P', except that - that expression may examine the mode of the memory reference in - MODE. You should define this macro if the mode of the memory - reference affects whether a register may be used as a base - register. If you define this macro, the compiler will use it - instead of `REGNO_OK_FOR_BASE_P'. */ - -#define REGNO_OK_FOR_INDEX_P(NUM) 0 -/* 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 PREFERRED_RELOAD_CLASS(X, CLASS) (CLASS) -/* 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. */ - -/* `PREFERRED_OUTPUT_RELOAD_CLASS (X, 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. */ - -/* `LIMIT_RELOAD_CLASS (MODE, 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. */ - -/* SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) - `SECONDARY_RELOAD_CLASS (CLASS, MODE, X)' - `SECONDARY_OUTPUT_RELOAD_CLASS (CLASS, MODE, X)' - 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. */ - -/* `SECONDARY_MEMORY_NEEDED (CLASS1, CLASS2, M)' - 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. - - `SECONDARY_MEMORY_NEEDED_RTX (MODE)' - 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 SMALL_REGISTER_CLASSES 1 -/* 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 CLASS_LIKELY_SPILLED_P(CLASS) class_likely_spilled_p(CLASS) -/* 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_MAX_NREGS(CLASS, MODE) GET_MODE_SIZE (MODE) -/* 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 CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (VALUE) >= -255 && (VALUE) <= -1 : \ - (C) == 'J' ? (VALUE) >= 0 && (VALUE) <= 7 : \ - (C) == 'K' ? (VALUE) >= 0 && (VALUE) <= 127 : \ - (C) == 'L' ? (VALUE) > 0 && (VALUE) < 128: \ - (C) == 'M' ? (VALUE) == -1: \ - (C) == 'N' ? (VALUE) == 1: \ - (C) == 'O' ? (VALUE) == 0: \ - (C) == 'P' ? (VALUE) >= 0 && (VALUE) <= 255: \ - 0) - -/* 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_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 - -/* `CONST_DOUBLE_OK_FOR_LETTER_P (VALUE, C)' - A C expression that defines the machine-dependent operand - constraint letters that specify particular ranges of - `const_double' values (`G' or `H'). - - 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 EXTRA_CONSTRAINT(X, C) ip2k_extra_constraint (X, C) - -/* A C expression that defines the optional machine-dependent - constraint letters (``Q', `R', `S', `T', `U') that can' - be used to segregate specific types of operands, usually memory - references, for the target machine. 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. */ - -/* This is an undocumented variable which describes - how GCC will pop a data. */ -#define STACK_POP_CODE PRE_INC - -#define STACK_PUSH_CODE POST_DEC -/* This macro defines the operation used when something is pushed on - the stack. In RTL, a push operation will be `(set (mem - (STACK_PUSH_CODE (reg sp))) ...)' - - The choices are `PRE_DEC', `POST_DEC', `PRE_INC', and `POST_INC'. - Which of these is correct depends on the stack direction and on - whether the stack pointer points to the last item on the stack or - whether it points to the space for the next item on the stack. - - The default is `PRE_DEC' when `STACK_GROWS_DOWNWARD' is defined, - which is almost always right, and `PRE_INC' otherwise, which is - often wrong. */ - - -#define STACK_CHECK_BUILTIN 1 -/* Prologue code will do stack checking as necessary. */ - -#define STARTING_FRAME_OFFSET (0) -/* 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 FRAME_GROWS_DOWNWARD 1 -#define STACK_GROWS_DOWNWARD 1 - -/* On IP2K arg pointer is virtual and resolves to either SP or FP - after we've resolved what registers are saved (fp chain, return - pc, etc. */ - -#define FIRST_PARM_OFFSET(FUNDECL) 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. */ - -/* `STACK_DYNAMIC_OFFSET (FUNDECL)' - 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_POINTER_OFFSET 1 -/* IP2K stack is post-decremented, so 0(sp) is address of open space - and 1(sp) is offset to the location avobe the forst location at which - outgoing arguments are placed. */ - -#define STACK_BOUNDARY 8 -/* Define this macro if there is a guaranteed alignment for the stack - pointer on this machine. The definition is a C expression for the - desired alignment (measured in bits). This value is used as a - default if PREFERRED_STACK_BOUNDARY is not defined. */ - -#define STACK_POINTER_REGNUM REG_SP -/* 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 FRAME_POINTER_REGNUM REG_VFP -/* 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 HARD_FRAME_POINTER_REGNUM REG_FP - -#define ARG_POINTER_REGNUM REG_AP -/* 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::.). */ - -/* We don't really want to support nested functions. But we'll crash - in various testsuite tests if we don't at least define the register - to contain the static chain. The return value register is about as - bad a place as any for this. */ - -#define STATIC_CHAIN_REGNUM REG_RESULT -/* 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 FRAME_POINTER_REQUIRED (!flag_omit_frame_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 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}, \ - {HARD_FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ -} -/* 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 CAN_ELIMINATE(FROM, TO) \ - ((FROM) == HARD_FRAME_POINTER_REGNUM \ - ? (flag_omit_frame_pointer && !frame_pointer_needed) : 1) -/* Don't eliminate FP unless we EXPLICITLY_ASKED */ - -/* 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 INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ - ((OFFSET) = ip2k_init_elim_offset ((FROM), (TO))) - -/* 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 RETURN_ADDR_RTX(COUNT, X) \ - (((COUNT) == 0) ? gen_rtx_REG (HImode, REG_CALLH) : NULL_RTX) -/* 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 PUSH_ROUNDING(NPUSHED) (NPUSHED) -/* 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 RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - ip2k_return_pops_args ((FUNDECL), (FUNTYPE), (SIZE)) -/* 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 you can 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, FUNDECL - 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 FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0 -/* 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 is usually either 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 value of the expression can also be a `parallel' RTX. This is - used when an argument is passed in multiple locations. The mode - of the of the `parallel' should be the mode of the entire - argument. The `parallel' holds any number of `expr_list' pairs; - each one describes where part of the argument is passed. In each - `expr_list', the first operand can be either a `reg' RTX for the - hard register in which to pass this part of the argument, or zero - to pass the argument on the stack. If this operand is a `reg', - then the mode indicates how large this part of the argument is. - The second operand of the `expr_list' is a `const_int' which gives - the offset in bytes into the entire argument where this part - starts. - - 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 CUMULATIVE_ARGS int - -/* A C type for declaring a variable that is used as the first - argument of `FUNCTION_ARG' and other related values. For some - target machines, the type `int' suffices and can hold the number - of bytes of argument so far. - - There is no need to record in `CUMULATIVE_ARGS' anything about the - arguments that have been passed on the stack. The compiler has - other variables to keep track of that. For target machines on - which all arguments are passed on the stack, there is no need to - store anything in `CUMULATIVE_ARGS'; however, the data structure - must exist and should not be empty, so use `int'. */ - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ - ((CUM) = 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. */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) - -/* All arguments are passed on stack - do nothing here. */ - -/* 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_REGNO_P(R) 0 -/* 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_VALUE(VALTYPE, FUNC) \ - ((TYPE_MODE (VALTYPE) == QImode) \ - ? gen_rtx_REG (TYPE_MODE (VALTYPE), REG_RESULT + 1) \ - : gen_rtx_REG (TYPE_MODE (VALTYPE), REG_RESULT)) - -/* Because functions returning 'char' actually widen to 'int', we have to - use $81 as the return location if we think we only have a 'char'. */ - -/* 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). - - The value of the expression is usually a `reg' RTX for the hard - register where the return value is stored. The value can also be a - `parallel' RTX, if the return value is in multiple places. See - `FUNCTION_ARG' for an explanation of the `parallel' form. - - 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 LIBCALL_VALUE(MODE) gen_rtx_REG ((MODE), REG_RESULT) -/* 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 FUNCTION_VALUE_REGNO_P(N) ((N) == REG_RESULT) -/* 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 RETURN_IN_MEMORY(TYPE) \ - ((TYPE_MODE (TYPE) == BLKmode) ? int_size_in_bytes (TYPE) > 8 : 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. - - 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. */ - -/* Indicate that large structures are passed by reference. */ -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM,MODE,TYPE,NAMED) 0 - - -#define DEFAULT_PCC_STRUCT_RETURN 0 -/* 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 STRUCT_VALUE 0 -/* 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_INCOMING 0 -/* 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 EPILOGUE_USES(REGNO) 0 -/* 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 SETUP_INCOMING_VARARGS(ARGS_SO_FAR,MODE,TYPE, \ - PRETEND_ARGS_SIZE,SECOND_TIME) \ - ((PRETEND_ARGS_SIZE) = (0)) - - -/* Hmmm. We don't actually like constants as addresses - they always need - to be loaded to a register, except for function calls which take an - address by immediate value. But changing this to zero had negative - effects, causing the compiler to get very confused.... */ - -#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) - -/* 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 MAX_REGS_PER_ADDRESS 1 -/* 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. */ - -#ifdef REG_OK_STRICT -# define GO_IF_LEGITIMATE_ADDRESS(MODE, OPERAND, ADDR) \ -{ \ - if (legitimate_address_p ((MODE), (OPERAND), 1)) \ - goto ADDR; \ -} -#else -# define GO_IF_LEGITIMATE_ADDRESS(MODE, OPERAND, ADDR) \ -{ \ - if (legitimate_address_p ((MODE), (OPERAND), 0)) \ - goto ADDR; \ -} -#endif -/* 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'. */ - -/* 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. */ - -#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#define REG_OK_FOR_BASE_NOSTRICT_P(X) \ - (REGNO (X) >= FIRST_PSEUDO_REGISTER \ - || (REGNO (X) == REG_FP) \ - || (REGNO (X) == REG_VFP) \ - || (REGNO (X) == REG_AP) \ - || REG_OK_FOR_BASE_STRICT_P(X)) - -#ifdef REG_OK_STRICT -# define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P (X) -#else -# define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NOSTRICT_P (X) -#endif - -#define REG_OK_FOR_INDEX_P(X) 0 -/* 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. */ - - -/* 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 orig_x = (X); \ - (X) = legitimize_address ((X), (OLDX), (MODE), 0); \ - if ((X) != orig_x && memory_address_p ((MODE), (X))) \ - goto WIN; \ -} while (0) - -/* Is X a legitimate register to reload, or is it a pseudo stack-temp - that is problematic for push_reload() ? */ - -#define LRA_REG(X) \ - (! (reg_equiv_memory_loc[REGNO (X)] \ - && (reg_equiv_address[REGNO (X)] \ - || num_not_at_initial_offset))) - -/* Given a register X that failed the LRA_REG test, replace X - by its memory equivalent, find the reloads needed for THAT memory - location and substitute that back for the higher-level reload - that we're conducting... */ - -/* WARNING: we reference 'ind_levels' and 'insn' which are local variables - in find_reloads_address (), where the LEGITIMIZE_RELOAD_ADDRESS macro - expands. */ - -#define FRA_REG(X,MODE,OPNUM,TYPE) \ -do { \ - rtx tem = make_memloc ((X), REGNO (X)); \ - \ - if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0))) \ - { \ - /* Note that we're doing address in address - cf. ADDR_TYPE */ \ - find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0), \ - &XEXP (tem, 0), (OPNUM), \ - ADDR_TYPE (TYPE), ind_levels, insn); \ - } \ - (X) = tem; \ -} while (0) - - -/* For the IP2K, we want to be clever about picking IP vs DP for a - base pointer since IP only directly supports a zero displacement. - (Note that we have modified all the HI patterns to correctly handle - IP references by manipulating iph:ipl as we fetch the pieces). */ -#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND,WIN) \ -{ \ - if (GET_CODE (X) == PLUS \ - && REG_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT) \ - { \ - int disp = INTVAL (XEXP (X, 1)); \ - int fit = (disp >= 0 && disp <= (127 - 2 * GET_MODE_SIZE (MODE))); \ - rtx reg = XEXP (X, 0); \ - if (!fit) \ - { \ - push_reload ((X), NULL_RTX, &(X), \ - NULL, MODE_BASE_REG_CLASS (MODE), GET_MODE (X), \ - VOIDmode, 0, 0, OPNUM, TYPE); \ - goto WIN; \ - } \ - if (reg_equiv_memory_loc[REGNO (reg)] \ - && (reg_equiv_address[REGNO (reg)] || num_not_at_initial_offset)) \ - { \ - rtx mem = make_memloc (reg, REGNO (reg)); \ - if (! strict_memory_address_p (GET_MODE (mem), XEXP (mem, 0))) \ - { \ - /* Note that we're doing address in address - cf. ADDR_TYPE */\ - find_reloads_address (GET_MODE (mem), &mem, XEXP (mem, 0), \ - &XEXP (mem, 0), (OPNUM), \ - ADDR_TYPE (TYPE), (IND), insn); \ - } \ - push_reload (mem, NULL, &XEXP (X, 0), NULL, \ - GENERAL_REGS, Pmode, VOIDmode, 0, 0, \ - OPNUM, TYPE); \ - push_reload (X, NULL, &X, NULL, \ - MODE_BASE_REG_CLASS (MODE), GET_MODE (X), VOIDmode, \ - 0, 0, OPNUM, TYPE); \ - goto WIN; \ - } \ - } \ -} -/* A C compound statement that attempts to replace X, which is an - address that needs reloading, with a valid memory address for an - operand of mode MODE. WIN will be a C statement label elsewhere - in the code. It is not necessary to define this macro, but it - might be useful for performance reasons. - - For example, on the i386, it is sometimes possible to use a single - reload register instead of two by reloading a sum of two pseudo - registers into a register. On the other hand, for number of RISC - processors offsets are limited so that often an intermediate - address needs to be generated in order to address a stack slot. - By defining LEGITIMIZE_RELOAD_ADDRESS appropriately, the - intermediate addresses generated for adjacent some stack slots can - be made identical, and thus be shared. - - *Note*: This macro should be used with caution. It is necessary - to know something of how reload works in order to effectively use - this, and it is quite easy to produce macros that build in too - much knowledge of reload internals. - - *Note*: This macro must be able to reload an address created by a - previous invocation of this macro. If it fails to handle such - addresses then the compiler may generate incorrect code or abort. - - The macro definition should use `push_reload' to indicate parts - that need reloading; OPNUM, TYPE and IND_LEVELS are usually - suitable to be passed unaltered to `push_reload'. - - The code generated by this macro must 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. This - also applies to parts that you change indirectly by calling - `push_reload'. - - The macro definition may use `strict_memory_address_p' to test if - the address has become legitimate. - - If you want to change only a part of X, one standard way of doing - this is to use `copy_rtx'. Note, however, that is unshares only a - single level of rtl. Thus, if the part to be changed is not at the - top level, you'll need to replace first the top leve It is not - necessary for this macro to come up with a legitimate address; - but often a machine-dependent strategy can generate better code. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ - do { \ - if (ip2k_mode_dependent_address (ADDR)) goto LABEL; \ - } 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 LEGITIMATE_CONSTANT_P(X) 1 -/* 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 CONST_COSTS(RTX,CODE,OUTER_CODE) \ - case CONST_INT: \ - return 0; \ - case CONST: \ - return 8; \ - case LABEL_REF: \ - return 0; \ - case SYMBOL_REF: \ - return 8; \ - case CONST_DOUBLE: \ - return 0; - -/* 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 DEFAULT_RTX_COSTS(X, CODE, OUTER_CODE) \ - return default_rtx_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 ADDRESS_COST(ADDRESS) ip2k_address_cost (ADDRESS) - -/* 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 REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) 7 -/* 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 MEMORY_MOVE_COST(MODE,CLASS,IN) 6 -/* 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 SLOW_BYTE_ACCESS 0 -/* 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. - - `SLOW_ZERO_EXTEND' - 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'. - - `SLOW_UNALIGNED_ACCESS' - 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. - - `DONT_REDUCE_ADDR' - Define this macro to inhibit strength reduction of memory - addresses. (On some machines, such strength reduction seems to do - harm rather than good.) - - `MOVE_RATIO' - 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 NO_FUNCTION_CSE -/* 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_RECURSIVE_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. - - `ADJUST_COST (INSN, LINK, DEP_INSN, COST)' - 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. - - `ADJUST_PRIORITY (INSN)' - 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 TEXT_SECTION_ASM_OP ".text" -/* 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 DATA_SECTION_ASM_OP ".data" -/* 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 JUMP_TABLES_IN_TEXT_SECTION 1 -/* 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 ASM_COMMENT_START " ; " -/* 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_APP_ON "/* #APP */\n" -/* 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_OFF "/* #NOAPP */\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 OBJC_PROLOGUE {} -/* 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 ASM_OUTPUT_DOUBLE(STREAM, VALUE) \ - fprintf ((STREAM), ".double %.20e\n", (VALUE)) -#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \ - asm_output_float ((STREAM), (VALUE)) - -/* `ASM_OUTPUT_LONG_DOUBLE (STREAM, VALUE)' - `ASM_OUTPUT_THREE_QUARTER_FLOAT (STREAM, VALUE)' - `ASM_OUTPUT_SHORT_FLOAT (STREAM, VALUE)' - `ASM_OUTPUT_BYTE_FLOAT (STREAM, VALUE)' - 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_INT(FILE, VALUE) \ - ( fprintf ((FILE), "\t.long "), \ - output_addr_const ((FILE), (VALUE)), \ - fputs ("\n", (FILE))) - - /* Likewise for `short' and `char' constants. */ - -#define ASM_OUTPUT_SHORT(FILE,VALUE) \ - asm_output_short ((FILE), (VALUE)) -#define ASM_OUTPUT_CHAR(FILE,VALUE) \ - asm_output_char ((FILE), (VALUE)) - -/* `ASM_OUTPUT_QUADRUPLE_INT (STREAM, EXP)' - 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_BYTE(FILE,VALUE) \ - asm_output_byte ((FILE), (VALUE)) -/* A C statement to output to the stdio stream STREAM an assembler - instruction to assemble a single byte containing the number VALUE. */ - -#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) \ - ((C) == '\n' || ((C) == '$')) -/* 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 ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \ -do { \ - fputs ("\t.comm ", (STREAM)); \ - assemble_name ((STREAM), (NAME)); \ - fprintf ((STREAM), ",%d\n", (SIZE)); \ -} while (0) -/* 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_LOCAL(STREAM, NAME, SIZE, ROUNDED) \ -do { \ - fputs ("\t.lcomm ", (STREAM)); \ - assemble_name ((STREAM), (NAME)); \ - fprintf ((STREAM), ",%d\n", (SIZE)); \ -} while (0) -/* 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. */ - -#undef WEAK_ASM_OP -#define WEAK_ASM_OP ".weak" - -#undef ASM_DECLARE_FUNCTION_SIZE -#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ - do { \ - if (!flag_inhibit_size_directive) \ - ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \ - } while (0) -/* 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. */ - -#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" -/* 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. */ - -/* Globalizing directive for a label. */ -#define GLOBAL_ASM_OP ".global\t" - -#undef ASM_FORMAT_PRIVATE_NAME -#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ -( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ - sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) - -/* 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 REGISTER_NAMES { \ - "$00","$01","$02","$03","iph","ipl","sph","spl", \ - "pch","pcl","wreg","status","dph","dpl","$0e","mulh", \ - "$10","$11","$12","$13","$14","$15","$16","$17", \ - "$18","$19","$1a","$1b","$1c","$1d","$1e","$1f", \ - "$20","$21","$22","$23","$24","$25","$26","$27", \ - "$28","$29","$2a","$2b","$2c","$2d","$2e","$2f", \ - "$30","$31","$32","$33","$34","$35","$36","$37", \ - "$38","$39","$3a","$3b","$3c","$3d","$3e","$3f", \ - "$40","$41","$42","$43","$44","$45","$46","$47", \ - "$48","$49","$4a","$4b","$4c","$4d","$4e","$4f", \ - "$50","$51","$52","$53","$54","$55","$56","$57", \ - "$58","$59","$5a","$5b","$5c","$5d","$5e","$5f", \ - "$60","$61","$62","$63","$64","$65","$66","$67", \ - "$68","$69","$6a","$6b","$6c","$6d","$6e","$6f", \ - "$70","$71","$72","$73","$74","$75","$76","$77", \ - "$78","$79","$7a","$7b","$7c","$7d","callh","calll", \ - "$80","$81","$82","$83","$84","$85","$86","$87", \ - "$88","$89","$8a","$8b","$8c","$8d","$8e","$8f", \ - "$90","$91","$92","$93","$94","$95","$96","$97", \ - "$98","$99","$9a","$9b","$9c","$9d","$9e","$9f", \ - "$a0","$a1","$a2","$a3","$a4","$a5","$a6","$a7", \ - "$a8","$a9","$aa","$ab","$ac","$ad","$ae","$af", \ - "$b0","$b1","$b2","$b3","$b4","$b5","$b6","$b7", \ - "$b8","$b9","$ba","$bb","$bc","$bd","$be","$bf", \ - "$c0","$c1","$c2","$c3","$c4","$c5","$c6","$c7", \ - "$c8","$c9","$ca","$cb","$cc","$cd","$ce","$cf", \ - "$d0","$d1","$d2","$d3","$d4","$d5","$d6","$d7", \ - "$d8","$d9","$da","$db","$dc","$dd","$de","$df", \ - "$e0","$e1","$e2","$e3","$e4","$e5","$e6","$e7", \ - "$e8","$e9","$ea","$eb","$ec","$ed","$ee","$ef", \ - "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7", \ - "$f8","$f9","$fa","$fb","$fc","$fd","$fe","$ff", \ - "vfph","vfpl","vaph","vapl"} - -/* 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 PRINT_OPERAND(STREAM, X, CODE) \ - print_operand ((STREAM), (X), (CODE)) -/* 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_PUNCT_VALID_P(CODE) \ - ((CODE) == '<' || (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_ADDRESS(STREAM, X) print_operand_address(STREAM, X) -/* 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::. */ - -/* Since register names don't have a prefix, we must preface all - user identifiers with the '_' to prevent confusion. */ - -#undef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "_" -#define LOCAL_LABEL_PREFIX ".L" -/* `LOCAL_LABEL_PREFIX' - `REGISTER_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. */ - - -#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ - asm_fprintf ((STREAM), "\tpage\t%L%d\n\tjmp\t%L%d\n", (VALUE), (VALUE)) - -/* elfos.h presumes that we will want switch/case dispatch tables aligned. - This is not so for the ip2k. */ -#undef ASM_OUTPUT_CASE_LABEL - -#undef ASM_OUTPUT_ADDR_VEC_ELT -#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ - asm_fprintf ((STREAM), "\tpage\t%L%d\n\tjmp\t%L%d\n", (VALUE), (VALUE)) - -/* 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_ALIGN(STREAM, POWER) \ - fprintf ((STREAM), "\t.align %d\n", (POWER)) -/* 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'. */ - -/* Since instructions are 16 bit word addresses, we should lie and claim that - the dispatch vectors are in QImode. Otherwise the offset into the jump - table will be scaled by the MODE_SIZE. */ - -#define CASE_VECTOR_MODE QImode -/* An alias for a machine mode name. This is the machine mode that - elements of a jump-table should have. */ - - -/* `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. */ - -#undef WORD_REGISTER_OPERATIONS -/* 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 MOVE_MAX 1 -/* The maximum number of bytes that a single instruction can move - quickly between memory and registers or between two memory - locations. */ - -#define MOVE_RATIO 3 -/* MOVE_RATIO is the number of move instructions that is better than a - block move. Make this small on the IP2k, since the code size grows very - large with each move. */ - -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 -/* 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 Pmode HImode -/* 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 FUNCTION_MODE 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 INTEGRATE_THRESHOLD(DECL) \ - (1 + (3 * list_length (DECL_ARGUMENTS (DECL)) / 2)) -/* 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 VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \ - 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. */ - -#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, IDENTIFIER, ARGS) \ - 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. */ - -#define DOLLARS_IN_IDENTIFIERS 0 -/* Define this macro to control use of the character `$' in identifier - names. 0 means `$' is not allowed by default; 1 means it is - allowed. 1 is the default; there is no need to define this macro - in that case. This macro controls the compiler proper; it does - not affect the preprocessor. */ - -#define MACHINE_DEPENDENT_REORG(INSN) 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. */ - -extern int ip2k_reorg_in_progress; -/* Flag if we're in the middle of IP2k-specific reorganization. */ - -extern int ip2k_reorg_completed; -/* Flag if we've completed our IP2k-specific reorganization. If we have - then we allow quite a few more tricks than before. */ - -extern int ip2k_reorg_split_dimode; -extern int ip2k_reorg_split_simode; -extern int ip2k_reorg_split_qimode; -extern int ip2k_reorg_split_himode; -/* Flags for various split operations that we run in sequence. */ - -extern int ip2k_reorg_merge_qimode; -/* Flag to indicate that it's safe to merge QImode operands. */ - -#define GIV_SORT_CRITERION(X, Y) \ - do { \ - if (GET_CODE ((X)->add_val) == CONST_INT \ - && GET_CODE ((Y)->add_val) == CONST_INT) \ - return INTVAL ((X)->add_val) - INTVAL ((Y)->add_val); \ - } while (0) - -/* In some cases, the strength reduction optimization pass can - produce better code if this is defined. This macro controls the - order that induction variables are combined. This macro is - particularly useful if the target has limited addressing modes. - For instance, the SH target has only positive offsets in - addresses. Thus sorting to put the smallest address first allows - the most combinations to be found. */ - -#define TRAMPOLINE_TEMPLATE(FILE) abort () - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 4 - -/* 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 (HImode, plus_constant ((TRAMP), 2)), \ - CXT); \ - emit_move_insn (gen_rtx_MEM (HImode, plus_constant ((TRAMP), 6)), \ - FNADDR); \ -} -/* 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) (void)(0) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - fprintf ((FILE), "/* profiler %d */", (LABELNO)) - -#define TARGET_MEM_FUNCTIONS -/* 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'. */ - - -#undef ENDFILE_SPEC -#undef LINK_SPEC -#undef STARTFILE_SPEC - -/* 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. */ - -#if defined(__STDC__) || defined(ALMOST_STDC) -#define AS2(a,b,c) #a "\t" #b "," #c -#define AS1(a,b) #a "\t" #b -#else -#define AS1(a,b) "a b" -#define AS2(a,b,c) "a b,c" -#endif -#define OUT_AS1(a,b) output_asm_insn (AS1 (a,b), operands) -#define OUT_AS2(a,b,c) output_asm_insn (AS2 (a,b,c), operands) -#define CR_TAB "\n\t" - -/* 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 \ -{ \ - smul_optab->handlers[(int) SImode].libfunc \ - = gen_rtx_SYMBOL_REF (Pmode, "_mulsi3"); \ - \ - smul_optab->handlers[(int) DImode].libfunc \ - = gen_rtx_SYMBOL_REF (Pmode, "_muldi3"); \ - \ - cmp_optab->handlers[(int) HImode].libfunc \ - = gen_rtx_SYMBOL_REF (Pmode, "_cmphi2"); \ - \ - cmp_optab->handlers[(int) SImode].libfunc \ - = gen_rtx_SYMBOL_REF (Pmode, "_cmpsi2"); \ -} - -#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT - -#define PREDICATE_CODES \ - {"ip2k_ip_operand", {MEM}}, \ - {"ip2k_short_operand", {MEM}}, \ - {"ip2k_gen_operand", {MEM, REG, SUBREG}}, \ - {"ip2k_nonptr_operand", {REG, SUBREG}}, \ - {"ip2k_ptr_operand", {REG, SUBREG}}, \ - {"ip2k_split_dest_operand", {REG, SUBREG, MEM}}, \ - {"ip2k_sp_operand", {REG}}, \ - {"ip2k_nonsp_reg_operand", {REG, SUBREG}}, \ - {"ip2k_symbol_ref_operand", {SYMBOL_REF}}, \ - {"ip2k_binary_operator", {PLUS, MINUS, MULT, DIV, \ - UDIV, MOD, UMOD, AND, IOR, \ - XOR, COMPARE, ASHIFT, \ - ASHIFTRT, LSHIFTRT}}, \ - {"ip2k_unary_operator", {NEG, NOT, SIGN_EXTEND, \ - ZERO_EXTEND}}, \ - {"ip2k_unsigned_comparison_operator", {LTU, GTU, NE, \ - EQ, LEU, GEU}},\ - {"ip2k_signed_comparison_operator", {LT, GT, LE, GE}}, - -#define DWARF2_DEBUGGING_INFO 1 - -#define DWARF2_ASM_LINE_DEBUG_INFO 1 - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* Miscellaneous macros to describe machine specifics. */ - -#define STORE_FLAG_VALUE 1 - -#define IS_PSEUDO_P(R) (REGNO (R) >= FIRST_PSEUDO_REGISTER) - -/* Default calculations would cause DWARF address sizes to be 2 bytes, - but the Harvard architecture of the IP2k and the word-addressed 64k - of instruction memory causes us to want a 32-bit "address" field. */ -#undef DWARF2_ADDR_SIZE -#define DWARF2_ADDR_SIZE 4 - diff --git a/gcc/config/ip2k/ip2k.md b/gcc/config/ip2k/ip2k.md deleted file mode 100644 index cc64a43f2b9..00000000000 --- a/gcc/config/ip2k/ip2k.md +++ /dev/null @@ -1,6902 +0,0 @@ -;; -*- Mode: Scheme -*- -;; GCC machine description for Ubicom IP2022 Communications Controller. -;; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. -;; Contributed by Red Hat, Inc and Ubicom, 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. */ - -;; Default all instruction lengths to two bytes (one 16-bit instruction). -;; -(define_attr "length" "" (const_int 2)) - -;; Define if we can "skip" an insn or not -(define_attr "skip" "no,yes" (const_string "no")) - -;; Define an insn clobbers WREG or not -(define_attr "clobberw" "no,yes" (const_string "yes")) - -;; Performance Issues: -;; -;; With the IP2k only having one really useful pointer register we have to -;; make most of our instruction patterns only match one offsettable address -;; before addressing becomes strict whereas afterwards of course we can use -;; any register details that have become fixed. As we've already committed -;; any reloads at this point of course we're a little late so we have to use -;; a number of peephole2 optimizations to remerge viable patterns. We can -;; do a bit more tidying up in the machine-dependent reorg pass to try and -;; make things better still. None of this is ideal, but it's *much* better -;; than nothing. - -;; Constraints: -;; -;; I - -255..-1 - all other literal values have to be loaded -;; J - 0..7 - valid bit number in a register -;; K - 0..127 - valid offset for addressing mode -;; L - 1..127 - positive count suitable for shift. -;; M - -1 as a literal value -;; N - +1 as a literal value -;; O - zero -;; P - 0..255 -;; -;; a - DP or IP registers (general address) -;; f - IP register -;; j - IPL register -;; k - IPH register -;; b - DP register -;; y - DPH register -;; z - DPL register -;; q - SP register -;; c - DP or SP registers (offsettable address) -;; d - non-pointer registers (not SP, DP, IP) -;; u - non-SP registers (everything except SP) -;; -;; R - Indirect thru IP - Avoid this except for QI mode, since we -;; can't access extra bytes. -;; S - Short (stack/dp address). Pointer with 0..127 displacement -;; Note that 0(SP) has undefined contents due to post-decrement push -;; T - data-section immediate value. A CONST_INT or SYMBOL_REF into .data - -;; Special assembly-language format effectors: -;; -;; ABCD - -;; Reference up to 4 big-endian registers - %A0 is Rn+0, while %D0 is Rn+3 -;; STUVWXYZ - -;; Reference up to 8 big-endian registers - %S0 is Rn+0, while %Z0 is Rn+7 -;; -;; H - High part of 16 bit address or literal %hi8data(v) or %hi8insn(v) -;; L - Low part of 16 bit address or literal %lo8data(v) or %lo8insn(v) -;; b - print a literal value with no punctuation (typically bit selector) -;; e - print 1 << v ('exponent') -;; n - print negative number -;; x - print 16 bit hex number -;; < - interior stack push; adjust any stack-relative operands accordingly -;; > - interior stack pop; clear adjustment. - -;; -;; Basic operations to move data in and out of fr's. Also extended to -;; cover the loading of w with immediates -;; - -(define_insn "*movqi_w_gen" - [(set (reg:QI 10) - (match_operand:QI 0 "general_operand" "rSi"))] - "(ip2k_reorg_split_qimode)" - "mov\\tw,%0" - [(set_attr "skip" "yes")]) - -(define_insn "*movqi_fr_w" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rS") - (reg:QI 10))] - "(ip2k_reorg_split_qimode)" - "mov\\t%0,w" - [(set_attr "skip" "yes") - (set_attr "clobberw" "no")]) - - -;; Handle the cases where we get back to back redundant mov patterns issued. -;; This of course sounds somewhat absurd but is actually reasonably common -;; because we aren't able to match certain patterns before registers are -;; chosen. This is particularly true of memory to memory operations where -;; we can't provide patterns that will guarantee to match every time because -;; this would require reloads in the middle of instructions. If we -;; discover a case that doesn't need a reload of course then this combiner -;; operation will tidy up for us. -;; -;; Warning! Whilst it would be nice to match operand 0 as a general operand -;; we mustn't do so because this doesn't work with the REG_DEAD check. -;; -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "ip2k_gen_operand" "")) - (set (match_operand 2 "ip2k_split_dest_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ! (REG_P (operands[2]) && REGNO (operands[2]) == REG_SP) - && (REG_P (operands[2]) - || ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0])))))" - [(set (match_dup 2) - (match_dup 1))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "immediate_operand" "")) - (set (match_operand 2 "ip2k_gen_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ! (REG_P (operands[2]) && REGNO (operands[2]) == REG_SP) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_dup 1))] - "") - -;; -;; Move 8-bit integers. -;; - -(define_expand "movqi" - [(set (match_operand:QI 0 "" "") - (match_operand:QI 1 "" ""))] - "" - "") - -(define_insn "*pushqi" - [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "general_operand" "g"))] - "" - "push\\t%1" - [(set_attr "skip" "yes") - (set_attr "clobberw" "no")]) - -;; IP isn't offsettable but we can fake this behaviour here and win if we would -;; otherwise use DP and require a reload from IP. This instruction is only -;; matched by peephole2 operations. -;; -(define_insn "*movqi_to_ip_plus_offs" - [(set (mem:QI (plus:HI (reg:HI 4) - (match_operand 0 "const_int_operand" "P,P"))) - (match_operand:QI 1 "general_operand" "O,g"))] - "reload_completed && (INTVAL (operands[0]) < 0x100)" - "*{ - if (INTVAL (operands[0]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %0); - OUT_AS2 (add, ipl, w); - } - - switch (which_alternative) - { - case 0: - OUT_AS1 (clr, (IP)); - break; - - case 1: - OUT_AS1 (push, %1%<); - OUT_AS1 (pop, (IP)%>); - break; - } - - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - { - if (INTVAL (operands[0]) == 1) - OUT_AS1 (dec, ipl); - else - OUT_AS2 (sub, ipl, w); - } - return \"\"; - }") - -;; IP isn't offsettable but we can fake this behaviour here and win if we would -;; otherwise use DP and require a reload from IP. This instruction is only -;; matched by peephole2 operations. -;; -(define_insn "*movqi_from_ip_plus_offs" - [(set (match_operand:QI 0 "nonimmediate_operand" "=g") - (mem:QI (plus:HI (reg:HI 4) - (match_operand 1 "const_int_operand" "P"))))] - "reload_completed && (INTVAL (operands[1]) < 0x100)" - "*{ - if (INTVAL (operands[1]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - } - OUT_AS1 (push, (IP)%<); - OUT_AS1 (pop, %0%>); - if (!find_regno_note (insn, REG_DEAD, REG_IP) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_IP, 2)) - { - if (INTVAL (operands[1]) == 1) - OUT_AS1 (dec, ipl); - else - OUT_AS2 (sub, ipl, w); - } - return \"\"; - }") - -(define_insn_and_split "*movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR,roR,r, rS,roR") - (match_operand:QI 1 "general_operand" " O, ri,o,rioR,rSi"))] - "" - "@ - clr\\t%0 - # - # - # - #" - "(ip2k_reorg_split_qimode - && (GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 0))" - [(set (reg:QI 10) (match_dup 1)) - (set (match_dup 0) (reg:QI 10))] - "" - [(set_attr "skip" "yes,no,no,no,no") - (set_attr "clobberw" "no,yes,yes,yes,yes")]) - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (match_operand:QI 0 "nonimmediate_operand" "") - (mem:QI (plus:HI (reg:HI 12) - (match_operand 1 "const_int_operand" ""))))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_regno_dead_p (2, REG_DP) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && (INTVAL (operands[1]) < 0x100))" - [(set (match_dup 0) - (mem:QI (plus:HI (reg:HI 4) - (match_dup 1))))] - "") - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (mem:QI (plus:HI (reg:HI 12) - (match_operand 0 "const_int_operand" ""))) - (match_operand:QI 1 "general_operand" ""))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_regno_dead_p (2, REG_DP) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && (INTVAL (operands[0]) < 0x100))" - [(set (mem:QI (plus:HI (reg:HI 4) - (match_dup 0))) - (match_dup 1))] - "") - -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (mem:QI (plus:HI (reg:HI 4) - (match_operand 1 "const_int_operand" "")))) - (set (match_operand:QI 2 "nonimmediate_operand" "") - (match_dup 0))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_reg_dead_p (2, operands[0]))" - [(set (match_dup 2) - (mem:QI (plus:HI (reg:HI 4) - (match_dup 1))))] - "") - -;; We sometimes want to copy a value twice, usually when we copy a value into -;; both a structure slot and into a temporary register. We can win here -;; because gcc doesn't know about ways of reusing w while we're copying. -;; -(define_insn_and_split "*movqi_twice" - [(set (match_operand:QI 0 "nonimmediate_operand" "=g") - (match_operand:QI 1 "general_operand" "g")) - (set (match_operand:QI 2 "nonimmediate_operand" "=g") - (match_dup 1))] - "ip2k_reorg_merge_qimode" - "mov\\tw,%1\;mov\\t%0,w\;mov\\t%2,w" - "(ip2k_reorg_split_qimode)" - [(set (reg:QI 10) (match_dup 1)) - (set (match_dup 0) (reg:QI 10)) - (set (match_dup 2) (reg:QI 10))] - "") - -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")) - (set (match_operand:QI 2 "nonimmediate_operand" "") - (match_dup 0))] - "(ip2k_reorg_merge_qimode - && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")) - (set (match_operand:QI 2 "nonimmediate_operand" "") - (match_dup 1))] - "(ip2k_reorg_merge_qimode - && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; -;; Move 16-bit integers. -;; - -(define_expand "movhi" - [(set (match_operand:HI 0 "" "") - (match_operand:HI 1 "" ""))] - "" - "") - -(define_insn "*pushhi_ip" - [(set (match_operand:HI 0 "push_operand" "=<") - (mem:HI (reg:HI 4)))] - "reload_completed" - "inc\\tipl\;push\\t(IP)\;dec\\tipl\;push\\t(IP)" - [(set_attr "clobberw" "no")]) - -(define_insn "*movhi_to_ip" - [(set (mem:HI (reg:HI 4)) - (match_operand:HI 0 "general_operand" "O,roi"))] - "reload_completed" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (clr, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS1 (clr, (IP)); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - return \"\"; - - case 1: - OUT_AS2 (mov, w, %H0); - OUT_AS2 (mov, (IP), w); - OUT_AS2 (mov, w, %L0); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, (IP), w); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - return \"\"; - default: - abort (); - } - }") - -(define_insn "*movhi_from_ip" - [(set (match_operand:HI 0 "nonimmediate_operand" "=f,bqdo") - (mem:HI (reg:HI 4)))] - "reload_completed" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (push, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, ipl, w); - OUT_AS1 (pop, iph); - return \"\"; - - case 1: - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %H0, w); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %L0, w); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - return \"\"; - default: - abort (); - } - }") - -(define_insn "*movhi_from_ip_plus_offs" - [(set (match_operand:HI 0 "nonimmediate_operand" "=f,bqdo") - (mem:HI (plus:HI (reg:HI 4) - (match_operand 1 "const_int_operand" "P, P"))))] - "reload_completed && (INTVAL (operands[1]) < 0x100)" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - OUT_AS1 (push, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, ipl, w); - OUT_AS1 (pop, iph); - return \"\"; - - case 1: - if (INTVAL (operands[1]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - } - OUT_AS1 (push, (IP)%<); - OUT_AS1 (pop, %H0%>); - OUT_AS1 (inc, ipl); - OUT_AS1 (push, (IP)%<); - OUT_AS1 (pop, %L0%>); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - { - OUT_AS1 (dec, ipl); - if (INTVAL (operands[1]) == 1) - OUT_AS1 (dec, ipl); - else - OUT_AS2 (sub, ipl, w); - } - return \"\"; - default: - abort (); - } - }") - -(define_insn_and_split "*movhi" - [(set - (match_operand:HI 0 "ip2k_split_dest_operand" "=<,<,uo,b, uS,uo,uo, q,u") - (match_operand:HI 1 "general_operand" "ron,i, n,T,uoi,uS,ui,ui,q"))] - "" - "@ - push\\t%L1%<\;push\\t%H1%> - push\\t%L1%<\;push\\t%H1%> - mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%L1\;mov\\t%L0,w - loadl\\t%x1\;loadh\\t%x1 - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w - mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%L1\;mov\\t%L0,w - mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%L1\;mov\\t%L0,w" - "(ip2k_reorg_split_himode - && (GET_CODE (operands[1]) == CONST_INT - || (push_operand (operands[0], HImode) - && GET_CODE (operands[1]) == REG) - || (register_operand (operands[0], HImode) - && REGNO (operands[0]) >= 0x80 - && ip2k_gen_operand (operands[1], HImode))))" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - "{ - ip2k_split_words (QImode, HImode, operands); /* Split into 2=3,4=5 */ - }" - [(set_attr "clobberw" "no,no,yes,no,yes,yes,yes,yes,yes")]) - -;; We don't generally use IP for HImode indirections because it's not -;; offsettable, however if we're accessing something that's already pointed -;; to by IP and would otherwise require a reload of DP then we can win by -;; simulating HImode accesses via IP instead. - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (mem:HI (reg:HI 12)) - (match_operand:HI 0 "general_operand" ""))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && peep2_regno_dead_p (2, REG_DP))" - [(set (mem:HI (reg:HI 4)) - (match_dup 0))] - "") - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (match_operand:HI 0 "nonimmediate_operand" "") - (mem:HI (reg:HI 12)))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && peep2_regno_dead_p (2, REG_DP))" - [(set (match_dup 0) - (mem:HI (reg:HI 4)))] - "") - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (match_operand:HI 0 "nonimmediate_operand" "") - (mem:HI (plus:HI (reg:HI 12) - (match_operand 1 "const_int_operand" ""))))] - ; - ; We only match here if IP and DP both go dead because emulating - ; offsets in conjunction with IP doesn't win unless IP goes - ; dead too. - ; - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_regno_dead_p (2, REG_DP) - && peep2_regno_dead_p (2, REG_IP) - && (INTVAL (operands[1]) < 0x100))" - [(set (match_dup 0) - (mem:HI (plus:HI (reg:HI 4) - (match_dup 1))))] - "") - -(define_peephole2 - [(set (reg:HI 12) - (reg:HI 4)) - (set (reg:HI 4) - (mem:HI (plus:HI (reg:HI 12) - (match_operand 0 "const_int_operand" ""))))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_regno_dead_p (2, REG_DP) - && (INTVAL (operands[0]) < 0x100))" - [(set (reg:HI 4) - (mem:HI (plus:HI (reg:HI 4) - (match_dup 0))))] - "") - -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (mem:HI (reg:HI 4))) - (set (match_operand:HI 2 "nonimmediate_operand" "") - (match_dup 0))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_reg_dead_p (2, operands[0]))" - [(set (match_dup 2) - (mem:HI (reg:HI 4)))] - "") - -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (mem:HI (plus:HI (reg:HI 4) - (match_operand 1 "const_int_operand" "")))) - (set (match_operand:HI 2 "nonimmediate_operand" "") - (match_dup 0))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_reg_dead_p (2, operands[0]) - && (INTVAL (operands[1]) < 0x100))" - [(set (match_dup 2) - (mem:HI (plus:HI (reg:HI 4) - (match_dup 1))))] - "") - -(define_peephole2 - [(set (match_operand:HI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:HI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (reg:HI 4)) - (set (mem:HI (reg:HI 12)) - (match_dup 0))] - "(peep2_reg_dead_p (3, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) - && peep2_regno_dead_p (3, REG_DP))" - [(set (mem:HI (reg:HI 4)) - (match_dup 1))] - "") - -;; We sometimes want to copy a value twice, usually when we copy a value into -;; both a structure slot and into a temporary register. We can win here -;; because gcc doesn't know about ways of reusing w while we're copying. -;; -(define_insn "*movhi_twice" - [(set (match_operand:HI 0 "ip2k_gen_operand" "=&uS,uS") - (match_operand:HI 1 "ip2k_gen_operand" "uS,uS")) - (set (match_operand:HI 2 "ip2k_gen_operand" "=&uS,uS") - (match_dup 1))] - "ip2k_reorg_split_simode" - "*{ - switch (which_alternative) - { - case 0: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, %L2, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (mov, %H2, w); - - case 1: - return AS2 (mov, w, %L1) CR_TAB - AS1 (push, %H1%<) CR_TAB - AS1 (push, %H1%<) CR_TAB - AS1 (pop, %H0%>) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (pop, %H2%>) CR_TAB - AS2 (mov, %L2, w); - default: - abort (); - } - }") - -;; We have to be *very* careful with this one to use predicates that do not -;; allow this to match if there are any register dependencies between the -;; operands. -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:HI 0 "ip2k_gen_operand" "") - (match_operand:HI 1 "ip2k_gen_operand" "")) - (set (match_operand:HI 2 "ip2k_gen_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_simode)" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; We have to be *very* careful with this one to use predicates that do not -;; allow this to match if there are any register dependencies between the -;; operands. -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:HI 0 "ip2k_gen_operand" "") - (match_operand:HI 1 "ip2k_gen_operand" "")) - (set (match_operand:HI 2 "ip2k_gen_operand" "") - (match_dup 1))] - "(ip2k_reorg_split_simode - && (!REG_P (operands[0]) - || ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 2)))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; -;; Move 32-bit integers. -;; - -(define_expand "movsi" - [(set (match_operand:SI 0 "" "") - (match_operand:SI 1 "" ""))] - "" - "") - -(define_insn_and_split "*movsi" - [(set (match_operand:SI 0 "ip2k_split_dest_operand" "=<, ro, S") - (match_operand:SI 1 "general_operand" "roSi,rSi,roi"))] - "" - "#" - "ip2k_reorg_split_simode" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - "{ - ip2k_split_words (HImode, SImode, operands); /* Split into 2=3,4=5 */ - }") - -;; We sometimes want to copy a value twice, usually when we copy a value into -;; both a structure slot and into a temporary register. We can win here -;; because gcc doesn't know about ways of reusing w while we're copying. -;; -(define_insn "*movsi_twice" - [(set (match_operand:SI 0 "ip2k_gen_operand" "=&uS,uS") - (match_operand:SI 1 "ip2k_gen_operand" "uS,uS")) - (set (match_operand:SI 2 "ip2k_gen_operand" "=&uS,uS") - (match_dup 1))] - "ip2k_reorg_split_dimode" - "*{ - switch (which_alternative) - { - case 0: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, %A2, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %B2, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %C2, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, %D2, w); - - case 1: - return AS2 (mov, w, %D1) CR_TAB - AS1 (push, %C1%<) CR_TAB - AS1 (push, %B1%<) CR_TAB - AS1 (push, %A1%<) CR_TAB - AS1 (push, %C1%<) CR_TAB - AS1 (push, %B1%<) CR_TAB - AS1 (push, %A1%<) CR_TAB - AS1 (pop, %A0%>) CR_TAB - AS1 (pop, %B0%>) CR_TAB - AS1 (pop, %C0%>) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (pop, %A2%>) CR_TAB - AS1 (pop, %B2%>) CR_TAB - AS1 (pop, %C2%>) CR_TAB - AS2 (mov, %D2, w); - default: - abort (); - } - }") - -;; We have to be *very* careful with this one to use predicates that do not -;; allow this to match if there are any register dependencies between the -;; operands. -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:SI 0 "ip2k_gen_operand" "") - (match_operand:SI 1 "ip2k_gen_operand" "")) - (set (match_operand:SI 2 "ip2k_gen_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_dimode - && (!REG_P (operands[0]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 4) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), 4))) - && (!REG_P (operands[1]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[1]), 4) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[1]), 4))) - && (!REG_P (operands[2]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 4) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 4))))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; We have to be *very* careful with this one to use predicates that do not -;; allow this to match if there are any register dependencies between the -;; operands. -;; Don't try to match until we've removed redundant reloads. Often this -;; simplification will remove the need to do two moves! -;; -(define_peephole2 - [(set (match_operand:SI 0 "ip2k_gen_operand" "") - (match_operand:SI 1 "ip2k_gen_operand" "")) - (set (match_operand:SI 2 "ip2k_gen_operand" "") - (match_dup 1))] - "(ip2k_reorg_split_dimode - && (!REG_P (operands[0]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 4) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), 4))) - && (!REG_P (operands[1]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[1]), 4) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[1]), 4))) - && (!REG_P (operands[2]) - || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 4) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 4))))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (match_dup 2) - (match_dup 1))])] - "") - -;; -;; Move 64-bit integers. -;; - -(define_expand "movdi" - [(set (match_operand:DI 0 "" "") - (match_operand:DI 1 "" ""))] - "" - "") - -(define_insn_and_split "*movdi" - [(set (match_operand:DI 0 "ip2k_split_dest_operand" "=<, ro, S") - (match_operand:DI 1 "general_operand" "roSi,rSi,roi"))] - "" - "#" - "ip2k_reorg_split_dimode" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - "{ - ip2k_split_words (SImode, DImode, operands); /* Split into 2=3,4=5 */ - }") - -;; -;; Move 32-bit floating point values. -;; - -(define_expand "movsf" - [(set (match_operand:SF 0 "" "") - (match_operand:SF 1 "" ""))] - "" - "if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[1] = copy_to_mode_reg (SFmode, operands[1]); - ") - -(define_insn_and_split "*movsf" - [(set (match_operand:SF 0 "ip2k_split_dest_operand" "=r<, o") - (match_operand:SF 1 "general_operand" "roi,ri"))] - "(ip2k_short_operand (operands[0], SFmode) - && ip2k_short_operand (operands[1], SFmode)) - || ! (memory_operand (operands[0], SFmode) - && memory_operand (operands[1], SFmode))" - "#" - "(reload_completed || reload_in_progress)" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5)) - (set (match_dup 6) (match_dup 7)) - (set (match_dup 8) (match_dup 9))] - "{ - /* Split into 2=3,4=5 */ - ip2k_split_words (HImode, SImode, operands); - /* Split 4=5 into 6=7,8=9 */ - ip2k_split_words (QImode, HImode, &operands[4]); - operands[0] = operands[2]; - operands[1] = operands[3]; - ip2k_split_words (QImode, HImode, operands); - }") - -;; -;; Move 64-bit floating point values. -;; - -;; -;; Block move operations. -;; - -;; Copy a block of bytes (memcpy()). We expand the definition to convert -;; our memory operand into a register pointer operand instead. -;; -(define_expand "movstrhi" - [(use (match_operand:BLK 0 "memory_operand" "")) - (use (match_operand:BLK 1 "memory_operand" "")) - (use (match_operand:HI 2 "general_operand" "")) - (use (match_operand 3 "const_int_operand" ""))] - "" - "{ - rtx addr0, addr1, count; - - addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - - if (GET_CODE (operands[2]) == CONST_INT) - count = gen_int_mode (INTVAL (operands[2]) & 0xffff, HImode); - else - count = operands[2]; - - emit_insn (gen_movstrhi_expanded (addr0, count, addr1)); - DONE; - }") - -;; Block copy instruction. We handle this by calling one of two functions in -;; libgcc. The first of these is a special case (faster) routine that handles -;; constant block sizes under 256 bytes. This one is particularly common -;; because we use it when copying data structures. The second routine handles -;; the general case where we have either a variable block size or one that is -;; greater than 255 bytes. -;; -(define_insn "movstrhi_expanded" - [(set - (mem:BLK - (match_operand:HI 0 "nonimmediate_operand" "rS,ro,rS, rS, ro, rS")) - (mem:BLK - (match_operand:HI 2 "nonimmediate_operand" "ro,rS,rS, ro, rS, rS"))) - (use - (match_operand:HI 1 "general_operand" "P, P, P,rSi,rSi,roi"))] - "" - "@ - push\\t%L1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>\;page\\t__movstrhi_countqi\;call\\t__movstrhi_countqi - push\\t%L1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>\;page\\t__movstrhi_countqi\;call\\t__movstrhi_countqi - push\\t%L1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>\;page\\t__movstrhi_countqi\;call\\t__movstrhi_countqi - push\\t%L1%<\;push\\t%H1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>%>\;page\\t__movstrhi_counthi\;call\\t__movstrhi_counthi - push\\t%L1%<\;push\\t%H1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>%>\;page\\t__movstrhi_counthi\;call\\t__movstrhi_counthi - push\\t%L1%<\;push\\t%H1%<\;push\\t%L2%<\;push\\t%H2%<\;push\\t%L0%<\;push\\t%H0%>%>%>%>%>\;page\\t__movstrhi_counthi\;call\\t__movstrhi_counthi") - - -;; Bit insert -;; -(define_expand "insv" - [(set (zero_extract:QI (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand 1 "immediate_operand" "") ;size - (match_operand 2 "immediate_operand" "")) ;pos - (match_operand:QI 3 "general_operand" ""))] - "" - "{ - if (! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J') - || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) - FAIL; - }") - -(define_insn "*insv" - [(set (zero_extract:QI - (match_operand:QI - 0 "nonimmediate_operand" "+roR,roR,roR,roR,&roR,&roR,&r") - (match_operand - 1 "immediate_operand" "N, N, J, J, N, J, J") ;sz - (match_operand - 2 "immediate_operand" "J, J, J, J, J, J, J"));pos - (match_operand:QI - 3 "general_operand" "MN, O, M, O, roR, rn,oR"))] - "" - "*{ - unsigned int pos = INTVAL (operands[2]), - siz = INTVAL (operands[1]), - mask = (1 << (pos + siz)) - (1 << pos); - - switch (which_alternative) - { - case 0: - return \"setb\\t%0,%b1\"; - - case 1: - return \"clrb\\t%0,%b1\"; - - case 2: - operands[3] = gen_int_mode (mask & 0xff, QImode); - return AS2 (mov, w, %3) CR_TAB - AS2 (or, %0, w); - - case 3: - operands[3] = gen_int_mode (0xff & ~mask, QImode); - return AS2 (mov, w, %3) CR_TAB - AS2 (and, %0, w); - - case 4: - return AS2 (clrb, %0,%b2) CR_TAB - AS2 (snb, %3, 0) CR_TAB - AS2 (setb, %0, %b2); - - case 5: - case 6: - { - static char buff[256]; - char *p = buff; - - /* Clear the destination field */ - - p += sprintf (buff, \"mov\\tw,#$%2.2x\;and\\t%%0,w\;\", - 0xff & ~mask); - - if (CONSTANT_P (operands[3])) - /* Constant can just be or-ed in. */ - { - p += sprintf (p, \"mov\\tw,#$%2.2x\;or\\t%%0,w\", - (INTVAL (operands[3]) << pos) & mask & 0xff); - return buff; - } - - p += sprintf (p, \"mov\\tw,%%3\;\"); /* Value to deposit */ - - /* Shift and mask the value before OR-ing into the destination. */ - - if (pos != 0) - p += sprintf (p, \"mulu\\tw,#%d\;\", 1<) CR_TAB - AS1 (incsnz, 2(SP)) CR_TAB - AS1 (inc, 1(SP)); - - case 1: - return AS2 (mov, w, %H1) CR_TAB - AS1 (push, %L1) CR_TAB - AS1 (push, wreg) CR_TAB - AS1 (incsnz, 2(SP)) CR_TAB - AS1 (inc, 1(SP)); - - case 2: - return AS1 (push, %L1%<) CR_TAB - AS1 (push, %H1%>) CR_TAB - AS2 (mov, w, #-1) CR_TAB - AS2 (add, 2(SP), w) CR_TAB - AS2 (addc, 1(SP), w); - - case 3: - OUT_AS2 (mov, w, %L2); - OUT_AS2 (add, %L1, w); - OUT_AS1 (push, %L1); - OUT_AS1 (push, %H1); - if (!find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - OUT_AS2 (sub, %L1, w); - return \"\"; - - case 4: - case 5: - return AS2 (mov, w, %L2) CR_TAB - AS2 (add, w, %L1) CR_TAB - AS1 (push, wreg%<) CR_TAB - AS2 (mov, w, %H2) CR_TAB - AS2 (addc, w, %H1) CR_TAB - AS1 (push, wreg%>); - - case 6: - return AS2 (mov, w, %H1) CR_TAB - AS1 (push, %L1) CR_TAB - AS1 (push, wreg) CR_TAB - AS2 (mov, w, %L2) CR_TAB - AS2 (add, 2(SP), w) CR_TAB - AS2 (mov, w, %H2) CR_TAB - AS2 (addc, 1(SP), w); - - case 7: - { - operands[3] = GEN_INT (INTVAL (operands[2]) + 2); - return AS1 (push, %L3) CR_TAB - AS1 (push, %H3) CR_TAB - AS2 (mov, w, %L1) CR_TAB - AS2 (add, 2(SP), w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (addc, 1(SP), w); - } - default: - abort (); - } - }" - [(set_attr "clobberw" "no,yes,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*push_addhi3_zero_ext" ; 0 1 2 3 - [(set (match_operand:HI 0 "push_operand" "=<, <, <, <") - (plus:HI - (zero_extend:HI - (match_operand:QI 1 "general_operand" "%roRi,roRi,roRi,rSi")) - (match_operand:HI 2 "general_operand" "N, P, rSi,roi")))] - "" - "@ - inc\\tw,%L2\;push\\twreg\;push\\t#0\;rl\\t1(SP) - mov\\tw,%L2\;add\\tw,%1\;push\\twreg\;push\\t#0\;rl\\t1(SP) - mov\\tw,%L2\;add\\tw,%1\;push\\twreg%<\;mov\\tw,%H2\;addc\\tw,$ff\;push\\twreg%> - mov\\tw,%L2\;add\\tw,%1\;push\\twreg%<\;mov\\tw,%H2\;addc\\tw,$ff\;push\\twreg%>") - -(define_insn "*addhi3_imm_zero_ext_w" - [(set - (match_operand:HI 0 "nonimmediate_operand" "=rS,o,a,b,a,a,rS,o,rS,o") - (plus:HI (zero_extend:HI (reg:QI 10)) - (match_operand 1 "immediate_operand" "O,O,M,i,P,I, P,P, i,i")))] - "" - "@ - mov\\t%L0,w\;clr\\t%H0 - mov\\t%L0,w\;clr\\t%H0 - mov\\t%L0,w\;clr\\t%H0\;dec\\t%L0 - loadh\\t%x1\;loadl\\t%x1\;add\\t%L0,w - mov\\t%L0,w\;clr\\t%H0\;mov\\tw,%1\;add\\t%L0,w - mov\\t%L0,w\;clr\\t%H0\;mov\\tw,#%n1\;sub\\t%L0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\t%H0\;rl\\t%H0 - add\\tw,%L1\;mov\\t%L0,w\;clr\\t%H0\;rl\\t%H0 - add\\tw,%L1\;mov\\t%L0,w\;clr\\t%H0\;mov\\tw,%H1\;addc\\t%H0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\t%H0\;mov\\tw,%H1\;addc\\t%H0,w") - -(define_insn_and_split "*addhi3_imm_zero_ext" - [(set - (match_operand:HI - 0 "nonimmediate_operand" "=rS, o, rS, o, a, b, a, a, rS, o, rS, o") - (plus:HI - (zero_extend:HI - (match_operand:QI - 1 "general_operand" "%roR,rS,roR,rS,roR,roR,roR,roR,roR,rS,roR,rS")) - (match_operand - 2 "immediate_operand" " O, O, N, N, M, i, P, I, P, P, i, i")))] - "" - "@ - # - # - clr\\t%H0\;incsnz\\tw,%1\;inc\\t%H0\;mov\\t%L0,w - clr\\t%H0\;incsnz\\tw,%1\;inc\\t%H0\;mov\\t%L0,w - # - # - # - # - # - # - # - #" - "(ip2k_reorg_split_qimode - && (GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 1))" - [(set (reg:QI 10) - (match_dup 1)) - (set (match_dup 0) - (plus:HI (zero_extend:HI (reg:QI 10)) - (match_dup 2)))]) - -(define_insn "*addhi3_immediate" ; 0 1 2 3 4 5 6 7 8 9 a b c d e f - [(set (match_operand:HI 0 "nonimmediate_operand" "=a,do,a,do,a,a,a,do,&uo,&uS,bf,bf,bf,&uS,&uo, u") - (plus:HI (match_operand:HI 1 "general_operand" "%0, 0,0, 0,0,0,0, 0, rS, ro,uo,uo,uo, ro, rS,uo") - (match_operand 2 "immediate_operand" "N, N,M, M,P,I,i, i, N, N, M, P, I, i, i, i")))] - "" - "@ - inc\\t%L0 - incsnz\\t%L0\;inc\\t%H0 - dec\\t%L0 - mov\\tw,#-1\;add\\t%L0,w\;addc\\t%H0,w - mov\\tw,%2\;add\\t%L0,w - mov\\tw,#%n2\;sub\\t%L0,w - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;add\\t%H0,w - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;addc\\t%H0,w - mov\\tw,%H1\;mov\\t%H0,w\;incsnz\\tw,%L1\;inc\\t%H0\;mov\\t%L0,w - mov\\tw,%H1\;mov\\t%H0,w\;incsnz\\tw,%L1\;inc\\t%H0\;mov\\t%L0,w - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w\;dec\\t%L0 - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w\;mov\\tw,%2\;add\\t%L0,w - mov\\tw,%H1\;push\\t%L1%<\;pop\\t%L0%>\;mov\\t%H0,w\;mov\\tw,#%n2\;sub\\t%L0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;push\\twreg%<\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w\;pop\\t%L0%>" - [(set_attr "skip" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no,no,no") - (set_attr "clobberw" "no,no,no,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*addhi3_nonimmediate" ; 0 1 2 3 4 5 6 7 - [(set (match_operand:HI 0 "nonimmediate_operand" "=&bf,bf,&dS,&do,d,&rS,&rS, o") - (plus:HI (match_operand:HI 1 "general_operand" "%0, 0, 0, 0,0, ro, rS,rS") - (match_operand:HI 2 "nonimmediate_operand" "ro,uo, ro, rS,r, rS, ro,rS")))] - "" - "@ - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;add\\t%H0,w - mov\\tw,%L2\;push\\t%H2%<\;add\\t%L0,w\;pop\\twreg%>\;add\\t%H0,w - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;addc\\t%H0,w - mov\\tw,%L2\;add\\t%L0,w\;mov\\tw,%H2\;addc\\t%H0,w - mov\\tw,%L2\;push\\t%H2%<\;add\\t%L0,w\;pop\\twreg%>\;addc\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w") - -(define_insn "*addhi3_nonimm_zero_extend_w" - [(set (match_operand:HI 0 "nonimmediate_operand" "=a,ro,&ro,&rS,&rS, u") - (plus:HI - (zero_extend:HI (reg:QI 10)) - (match_operand:HI 1 "nonimmediate_operand" "0, 0, rS, rS, ro,uo")))] - "" - "@ - add\\t%L0,w - add\\t%L0,w\;clr\\twreg\;addc\\t%H0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;addc\\tw,%H1\;mov\\t%H0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;addc\\tw,%H1\;mov\\t%H0,w - add\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;addc\\tw,%H1\;mov\\t%H0,w - add\\tw,%L1\;push\\twreg%<\;clr\\twreg\;addc\\tw,%H1\;mov\\t%H0,w\;pop\\t%L0%>" - [(set_attr "skip" "yes,no,no,no,no,no") - (set_attr "clobberw" "no,yes,yes,yes,yes,yes")]) - -(define_insn_and_split "*addhi3_nonimm_zero_extend" - [(set (match_operand:HI 0 "nonimmediate_operand" "=a, ro,&ro,&rS,&rS, u") - (plus:HI - (zero_extend:HI - (match_operand:QI 1 "general_operand" "roR,roR, rS,roR, rS,rS")) - (match_operand:HI 2 "nonimmediate_operand" "0, 0, rS, rS, ro,uo")))] - "" - "#" - "(ip2k_reorg_split_qimode)" - [(set (reg:QI 10) - (match_dup 1)) - (set (match_dup 0) - (plus:HI (zero_extend:HI (reg:QI 10)) - (match_dup 2)))]) - - -;; -;; Add 32-bit integers. -;; - -(define_expand "addsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (plus:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "") - -(define_insn "*push_addsi3" - [(set (match_operand:SI 0 "push_operand" "=<,<, <") - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%g,g, g") - (match_operand:SI 2 "general_operand" "N,M,rSi")))] - "" - "*{ - switch (which_alternative) { - case 0: - OUT_AS1 (push, %D1%<); - OUT_AS1 (push, %C1%<); - OUT_AS1 (push, %B1%<); - OUT_AS1 (push, %A1%>%>%>); - OUT_AS1 (incsnz, 4(SP)); - OUT_AS1 (incsz, 3(SP)); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, 2(SP)); - OUT_AS1 (inc, 1(SP)); - OUT_AS1 (1:,); - return \"\"; - - case 1: - OUT_AS1 (push, %D1%<); - OUT_AS1 (push, %C1%<); - OUT_AS1 (push, %B1%<); - OUT_AS1 (push, %A1%>%>%>); - OUT_AS2 (mov, w, #-1); - OUT_AS2 (add, 4(SP), w); - OUT_AS2 (addc, 3(SP), w); - OUT_AS2 (addc, 2(SP), w); - OUT_AS2 (addc, 1(SP), w); - return \"\"; - - case 2: - OUT_AS2 (mov, w, %D2); - OUT_AS2 (add, w, %D1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %C2); - OUT_AS2 (addc, w, %C1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %B2); - OUT_AS2 (addc, w, %B1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %A2); - OUT_AS2 (addc, w, %A1); - OUT_AS1 (push, wreg%>%>%>); - return \"\"; - - default: - abort(); - } - }" - [(set_attr "clobberw" "no,yes,yes")]) - -(define_insn "*addsi3" ; 0 1 2 3 4 5 6 - [(set - (match_operand:SI 0 "nonimmediate_operand" "=ro,ro, ro, rS,&ro,&rS,&rS") - (plus:SI - (match_operand:SI 1 "nonimmediate_operand" "%0, 0, 0, 0, rS, ro, rS") - (match_operand:SI 2 "general_operand" "N, M,rSi,roi,rSi,rSi,roi")))] - "" - "@ - incsnz\\t%D0\;incsz\\t%C0\;page\\t1f\;jmp\\t1f\;incsnz\\t%B0\;inc\\t%A0\;1: - mov\\tw,#-1\;add\\t%D0,w\;addc\\t%C0,w\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%D2\;add\\t%D0,w\;mov\\tw,%C2\;addc\\t%C0,w\;mov\\tw,%B2\;addc\\t%B0,w\;mov\\tw,%A2\;addc\\t%A0,w - mov\\tw,%D2\;add\\t%D0,w\;mov\\tw,%C2\;addc\\t%C0,w\;mov\\tw,%B2\;addc\\t%B0,w\;mov\\tw,%A2\;addc\\t%A0,w - mov\\tw,%D2\;add\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,%A1\;mov\\t%A0,w - mov\\tw,%D2\;add\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,%A1\;mov\\t%A0,w - mov\\tw,%D2\;add\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,%A1\;mov\\t%A0,w" - [(set_attr "clobberw" "no,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*push_addsi3_zero_extendqi" ; 0 1 - [(set (match_operand:SI 0 "push_operand" "=<, <") - (plus:SI (zero_extend:SI - (match_operand:QI 1 "general_operand" "%roRi,rSi")) - (match_operand:SI 2 "general_operand" "rSi,roi")))] - "" - "@ - mov\\tw,%D2\;add\\tw,%1\;push\\twreg%<\;mov\\tw,%C2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%B2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%A2\;addc\\tw,$ff\;push\\twreg%>%>%> - mov\\tw,%D2\;add\\tw,%1\;push\\twreg%<\;mov\\tw,%C2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%B2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%A2\;addc\\tw,$ff\;push\\twreg%>%>%>") - -(define_insn "*addsi3_zero_extendqi" ; - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,&ro,&rS,&rS") - (plus:SI - (zero_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR, rS,roR, rS")) - (match_operand:SI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "@ - mov\\tw,%1\;add\\t%D0,w\;clr\\twreg\;addc\\t%C0,w\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%1\;add\\t%D0,w\;clr\\twreg\;addc\\t%C0,w\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,$ff\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w - mov\\tw,%1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,$ff\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w - mov\\tw,%1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,$ff\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w") - -(define_insn "*push_addsi3_zero_extendhi" ; 0 1 - [(set (match_operand:SI 0 "push_operand" "=<, <") - (plus:SI (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "%roR,rSR")) - (match_operand:SI 2 "general_operand" "rSi,roi")))] - "" - "@ - mov\\tw,%D2\;add\\tw,%L1\;push\\twreg%<\;mov\\tw,%C2\;addc\\tw,%H1\;push\\twreg%<\;mov\\tw,%B2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%A2\;addc\\tw,$ff\;push\\twreg%>%>%> - mov\\tw,%D2\;add\\tw,%L1\;push\\twreg%<\;mov\\tw,%C2\;addc\\tw,%H1\;push\\twreg%<\;mov\\tw,%B2\;addc\\tw,$ff\;push\\twreg%<\;mov\\tw,%A2\;addc\\tw,$ff\;push\\twreg%>%>%>") - -(define_insn "*addsi3_zero_extendhi" ; - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,rS,&ro,&rS,&rS") - (plus:SI - (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "rS,ro, rS, ro, rS")) - (match_operand:SI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "@ - mov\\tw,%L1\;add\\t%D0,w\;mov\\tw,%H1\;addc\\t%C0,w\;clr\\twreg\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%L1\;add\\t%D0,w\;mov\\tw,%H1\;addc\\t%C0,w\;clr\\twreg\;addc\\t%B0,w\;addc\\t%A0,w - mov\\tw,%L1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%H1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w - mov\\tw,%L1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%H1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w - mov\\tw,%L1\;add\\tw,%D2\;mov\\t%D0,w\;mov\\tw,%C2\;addc\\tw,%H1\;mov\\t%C0,w\;mov\\tw,%B2\;addc\\tw,$ff\;mov\\t%B0,w\;mov\\tw,%A2\;addc\\tw,$ff\;mov\\t%A0,w") - -;; -;; Add 64-bit integers. -;; - -(define_expand "adddi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (plus:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" "")))] - "" - "") - -(define_insn "*push_adddi3" - [(set (match_operand:DI 0 "push_operand" "=<,<, <") - (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%g,g, g") - (match_operand:DI 2 "general_operand" "N,M,rSi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS1 (incsnz, 8(SP)); - OUT_AS1 (incsz, 7(SP)); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, 6(SP)); - OUT_AS1 (incsz, 5(SP)); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, 4(SP)); - OUT_AS1 (incsz, 3(SP)); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, 2(SP)); - OUT_AS1 (inc, 1(SP)); - OUT_AS1 (1:,); - return \"\"; - - case 1: - OUT_AS1 (push, %Z1%<); - OUT_AS1 (push, %Y1%<); - OUT_AS1 (push, %X1%<); - OUT_AS1 (push, %W1%<); - OUT_AS1 (push, %V1%<); - OUT_AS1 (push, %U1%<); - OUT_AS1 (push, %T1%<); - OUT_AS1 (push, %S1%>%>%>%>%>%>%>); - OUT_AS2 (mov, w, #-1); - OUT_AS2 (add, 8(SP), w); - OUT_AS2 (addc, 7(SP), w); - OUT_AS2 (addc, 6(SP), w); - OUT_AS2 (addc, 5(SP), w); - OUT_AS2 (addc, 4(SP), w); - OUT_AS2 (addc, 3(SP), w); - OUT_AS2 (addc, 2(SP), w); - OUT_AS2 (addc, 1(SP), w); - return \"\"; - - case 2: - OUT_AS2 (mov, w, %Z2); - OUT_AS2 (add, w, %Z1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, %Y1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, %X1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, %W1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, %V1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, %U1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, %T1); - OUT_AS1 (push, wreg%<); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, %S1); - OUT_AS1 (push, wreg%>%>%>%>%>%>%>); - return \"\"; - - default: - abort(); - } - }" - [(set_attr "clobberw" "no,yes,yes")]) - -(define_insn "*adddi3" ; 0 1 2 3 4 5 6 - [(set - (match_operand:DI 0 "nonimmediate_operand" "=ro,ro, ro, rS,&ro,&rS,&rS") - (plus:DI - (match_operand:DI 1 "nonimmediate_operand" "%0, 0, 0, 0, rS, ro, rS") - (match_operand:DI 2 "general_operand" "N, M,rSi,roi,rSi,rSi,roi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (incsnz, %Z0); - OUT_AS1 (incsz, %Y0); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, %X0); - OUT_AS1 (incsz, %W0); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, %V0); - OUT_AS1 (incsz, %U0); - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - OUT_AS1 (incsnz, %T0); - OUT_AS1 (inc, %S0); - OUT_AS1 (1:, ); - return \"\"; - - case 1: - OUT_AS2 (mov, w, #-1); - OUT_AS2 (add, %Z0, w); - OUT_AS2 (addc, %Y0, w); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (addc, %W0, w); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 2: - case 3: - OUT_AS2 (mov, w, %Z2); - OUT_AS2 (add, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 4: - case 5: - case 6: - OUT_AS2 (mov, w, %Z2); - OUT_AS2 (add, w, %Z1); - OUT_AS2 (mov, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, %Y1); - OUT_AS2 (mov, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, %X1); - OUT_AS2 (mov, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, %W1); - OUT_AS2 (mov, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, %V1); - OUT_AS2 (mov, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, %U1); - OUT_AS2 (mov, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, %T1); - OUT_AS2 (mov, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, %S1); - OUT_AS2 (mov, %S0, w); - return \"\"; - - default: - abort(); - } - }" - [(set_attr "clobberw" "no,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*adddi3_zero_extendqi" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro, rS,&ro,&rS,&rS") - (plus:DI - (zero_extend:DI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR, rS,roR, rS")) - (match_operand:DI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - case 1: - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, %Z0, w); - OUT_AS1 (clr, wreg); - OUT_AS2 (addc, %Y0, w); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (addc, %W0, w); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 2: - case 3: - case 4: - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, w, %Z2); - OUT_AS2 (mov, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %S0, w); - return \"\"; - - default: - abort(); - } - }") - -(define_insn "*adddi3_zero_extendhi" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,rS,&ro,&rS,&rS") - (plus:DI - (zero_extend:DI - (match_operand:HI 1 "nonimmediate_operand" "rS,ro, rS, ro, rS")) - (match_operand:DI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - case 1: - OUT_AS2 (mov, w, %L1); - OUT_AS2 (add, %Z0, w); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (addc, %Y0, w); - OUT_AS1 (clr, wreg); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (addc, %W0, w); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 2: - case 3: - case 4: - OUT_AS2 (mov, w, %L1); - OUT_AS2 (add, w, %Z2); - OUT_AS2 (mov, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, %H1); - OUT_AS2 (mov, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %S0, w); - return \"\"; - - default: - abort(); - } - }") - -(define_insn "*adddi3_zero_extendsi" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,rS,&ro,&rS,&rS") - (plus:DI - (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "rS,ro, rS, ro, rS")) - (match_operand:DI 2 "general_operand" "0, 0,rSi,rSi,roi")))] - "" - "*{ - switch (which_alternative) - { - case 0: - case 1: - OUT_AS2 (mov, w, %D1); - OUT_AS2 (add, %Z0, w); - OUT_AS2 (mov, w, %C1); - OUT_AS2 (addc, %Y0, w); - OUT_AS2 (mov, w, %B1); - OUT_AS2 (addc, %X0, w); - OUT_AS2 (mov, w, %A1); - OUT_AS2 (addc, %W0, w); - OUT_AS1 (clr, wreg); - OUT_AS2 (addc, %V0, w); - OUT_AS2 (addc, %U0, w); - OUT_AS2 (addc, %T0, w); - OUT_AS2 (addc, %S0, w); - return \"\"; - - case 2: - case 3: - case 4: - OUT_AS2 (mov, w, %D1); - OUT_AS2 (add, w, %Z2); - OUT_AS2 (mov, %Z0, w); - OUT_AS2 (mov, w, %Y2); - OUT_AS2 (addc, w, %C1); - OUT_AS2 (mov, %Y0, w); - OUT_AS2 (mov, w, %X2); - OUT_AS2 (addc, w, %B1); - OUT_AS2 (mov, %X0, w); - OUT_AS2 (mov, w, %W2); - OUT_AS2 (addc, w, %A1); - OUT_AS2 (mov, %W0, w); - OUT_AS2 (mov, w, %V2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %V0, w); - OUT_AS2 (mov, w, %U2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %U0, w); - OUT_AS2 (mov, w, %T2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %T0, w); - OUT_AS2 (mov, w, %S2); - OUT_AS2 (addc, w, $ff); - OUT_AS2 (mov, %S0, w); - return \"\"; - - default: - abort(); - } - }") - -;; -;; Subtract bytes. -;; - -(define_expand "subqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (minus:QI (match_operand:QI 1 "general_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "if (GET_CODE (operands[2]) == CONST_INT) - { - emit_insn (gen_addqi3 (operands[0], operands[1], - gen_int_mode (-INTVAL (operands[2]), QImode))); - DONE; - } - ") - -(define_insn "*push_subqi3" - [(set (match_operand:QI 0 "push_operand" "=<, <") - (minus:QI (match_operand:QI 1 "general_operand" "g,rSn") - (match_operand:QI 2 "general_operand" "rSn, g")))] - "" - "@ - push\\t%1%<\;mov\\tw,%2\;sub\\t1(SP),w%> - push\\t%1%<\;mov\\tw,%2\;sub\\t1(SP),w%>") - -(define_insn "*subqi3_w" - [(set (reg:QI 10) - (minus:QI (match_operand:QI 0 "general_operand" "rS,rSi, g,rSi") - (match_operand:QI 1 "general_operand" "rSi, rS,rSi, g")))] - "(ip2k_reorg_split_qimode)" - "@ - mov\\tw,%1\;sub\\tw,%0 - mov\\tw,%1\;sub\\tw,%0 - mov\\tw,%1\;sub\\tw,%0 - mov\\tw,%1\;sub\\tw,%0") - -(define_insn_and_split "*subqi3" - [(set - (match_operand:QI - 0 "nonimmediate_operand" "=k,k,z,z,djyoR,djyoR,djyS,djyoR, g, g, rS, rS") - (minus:QI - (match_operand:QI - 1 "general_operand" "0,0,0,0, 0, 0, 0, 0, rS,rSi, g,rSi") - (match_operand:QI - 2 "general_operand" "M,g,M,g, M, N, g, rSi,rSi, rS,rSi, g")))] - "" - "@ - incsnz\\t%0\;dec\\tiph - mov\\tw,%2\;sub\\t%0,w - incsnz\\t%0\;dec\\tdph - mov\\tw,%2\;sub\\t%0,w - inc\\t%0 - dec\\t%0 - mov\\tw,%2\;sub\\t%0,w - mov\\tw,%2\;sub\\t%0,w - # - # - # - #" - "(ip2k_reorg_split_qimode - && ! rtx_equal_p (operands[0], operands[1]))" - [(set (reg:QI 10) - (minus:QI (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (reg:QI 10))] - "" - [(set_attr "skip" "no,no,no,no,yes,yes,no,no,no,no,no,no") - (set_attr "clobberw" "no,yes,no,yes,no,no,yes,yes,yes,yes,yes,yes")]) - -;; -;; Subtract 16-bit integers. -;; - -(define_expand "subhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (minus:HI (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "" - "if (GET_CODE (operands[2]) == CONST_INT) - { - emit_insn (gen_addhi3 (operands[0], operands[1], - gen_int_mode (-INTVAL (operands[2]), HImode))); - DONE; - } - ") - -(define_insn "*push_subhi3" - [(set (match_operand:HI 0 "push_operand" "=<, <") - (minus:HI (match_operand:HI 1 "general_operand" "ron,rSn") - (match_operand:HI 2 "general_operand" "rSn,ron")))] - "" - "@ - push\\t%L1%<\;mov\\tw,%L2\;sub\\t1(SP),w\;push\\t%H1%<\;mov\\tw,%H2\;subc\\t1(SP),w%>%> - push\\t%L1%<\;mov\\tw,%L2\;sub\\t1(SP),w\;push\\t%H1%<\;mov\\tw,%H2\;subc\\t1(SP),w%>%>") - -(define_insn "*subhi3_imm" - [(set - (match_operand:HI 0 "nonimmediate_operand" "=a,a,a,a,do,&r,&ro,&rS") - (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0, 0,ro, rS, ro") - (match_operand 2 "immediate_operand" "N,M,P,i, i, O, i, i")))] - "" - "@ - dec\\t%L0 - inc\\t%L0 - mov\\tw,%2\;sub\\t%L0,w - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;sub\\t%H0,w - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;subc\\t%H0,w - mov\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w" - [(set_attr "skip" "yes,yes,no,no,no,no,no,no") - (set_attr "clobberw" "no,no,yes,yes,yes,yes,yes,yes")]) - -(define_insn "*subhi3_ximm_zero_extend" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (minus:HI (match_operand:HI 1 "immediate_operand" "i, i") - (zero_extend:HI - (match_operand:QI 2 "nonimmediate_operand" "rS,roR"))))] - "" - "@ - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w\;clr\\twreg\;subc\\t%H0,w - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w\;clr\\twreg\;subc\\t%H0,w") - -(define_insn "*subhi3_ximm" - [(set (match_operand:HI 0 "nonimmediate_operand" "=&uo,&ro,&rS") - (minus:HI (match_operand:HI 1 "immediate_operand" "i, i, i") - (match_operand:HI 2 "nonimmediate_operand" "0, rS, ro")))] - "" - "@ - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;push\\t%H2%<\;mov\\tw,%H1\;mov\\t%H0,w\;pop\\twreg%>\;subc\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%H2\;subc\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H1\;mov\\t%H0,w\;mov\\tw,%H2\;subc\\t%H0,w") - -(define_insn "*subhi3_nonimm_zero_extend" - [(set - (match_operand:HI 0 "nonimmediate_operand" "=a,ro, rS,&ro,&rS,&rS") - (minus:HI - (match_operand:HI 1 "nonimmediate_operand" "0, 0, 0, rS, ro, rS") - (zero_extend:HI - (match_operand:QI 2 "general_operand" "roR,rS,roR, rS, rS,roR"))))] - "" - "@ - mov\\tw,%2\;sub\\t%L0,w - mov\\tw,%2\;sub\\t%L0,w\;clr\\twreg\;subc\\t%H0,w - mov\\tw,%2\;sub\\t%L0,w\;clr\\twreg\;subc\\t%H0,w - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%2\;sub\\tw,%L1\;mov\\t%L0,w\;clr\\twreg\;subc\\tw,%H1\;mov\\t%H0,w") - -(define_insn "*subhi3_nonimm" ; 0 1 2 3 4 5 6 - [(set - (match_operand:HI 0 "nonimmediate_operand" "=a,dS, o,&rS,&rS,&rS, o") - (minus:HI - (match_operand:HI 1 "nonimmediate_operand" "0, 0, 0, ro, ro, rS,rS") - (match_operand:HI 2 "nonimmediate_operand" "ro,ro,rS, 0, rS, ro,rS")))] - "" - "@ - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;sub\\t%H0,w - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;subc\\t%H0,w - mov\\tw,%L2\;sub\\t%L0,w\;mov\\tw,%H2\;subc\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w - mov\\tw,%L2\;sub\\tw,%L1\;mov\\t%L0,w\;mov\\tw,%H2\;subc\\tw,%H1\;mov\\t%H0,w") - -;; -;; Subtract 32-bit integers. -;; - -(define_insn "subsi3" ; 0 1 2 3 4 5 6 7 8 9 a b - [(set - (match_operand:SI - 0 "nonimmediate_operand" "=ro,ro, ro, rS,&ro,&rS,&ro,&rS,&rS,&ro,&ro,&rS") - (minus:SI - (match_operand:SI - 1 "general_operand" "0, 0, 0, 0, i, ro, rS, rS, ro, rS, i, i") - (match_operand:SI - 2 "general_operand" "M, N,rSi,roi, 0, 0, 0,roi,rSi,rSi, rS, ro")))] - "" - "*{ - switch (which_alternative) { - case 0: - return AS2 (mov, w, #1) CR_TAB - AS2 (add, %D0, w) CR_TAB - AS1 (clr, wreg) CR_TAB - AS2 (addc, %C0, w) CR_TAB - AS2 (addc, %B0, w) CR_TAB - AS2 (addc, %A0, w); - - case 1: - return AS2 (mov, w, #-1) CR_TAB - AS2 (sub, %D0, w) CR_TAB - AS2 (subc, %C0, w) CR_TAB - AS2 (subc, %B0, w) CR_TAB - AS2 (subc, %A0, w); - - case 2: - case 3: - return AS2 (mov, w, %D2) CR_TAB - AS2 (sub, %D0, w) CR_TAB - AS2 (mov, w, %C2) CR_TAB - AS2 (subc, %C0, w) CR_TAB - AS2 (mov, w, %B2) CR_TAB - AS2 (subc, %B0, w) CR_TAB - AS2 (mov, w, %A2) CR_TAB - AS2 (subc, %A0, w); - - case 4: - return AS2 (mov, w, %D2) CR_TAB - AS2 (sub, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (push, %C2%<) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %C0, w) CR_TAB - AS1 (push, %B2%<) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %B0, w) CR_TAB - AS1 (push, %A2%<) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %A0, w); - - case 5: - case 6: - case 7: - case 8: - case 9: - return AS2 (mov, w, %D2) CR_TAB - AS2 (sub, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %C2) CR_TAB - AS2 (subc, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %B2) CR_TAB - AS2 (subc, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %A2) CR_TAB - AS2 (subc, w, %A1) CR_TAB - AS2 (mov, %A0, w); - - case 10: - case 11: - return AS2 (mov, w, %D2) CR_TAB - AS2 (sub, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %C2) CR_TAB - AS2 (subc, %C0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %B2) CR_TAB - AS2 (subc, %B0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %A2) CR_TAB - AS2 (subc, %A0, w); - default: - abort (); - } - }") - -;; -;; Subtract 64-bit integers. -;; - -(define_insn "subdi3" ; 0 1 2 3 4 5 6 7 8 9 a b - [(set - (match_operand:DI - 0 "nonimmediate_operand" "=ro,ro, ro, rS,ro,&rS,&ro,&rS,&rS,&ro,&ro,&rS") - (minus:DI - (match_operand:DI - 1 "general_operand" "0, 0, 0, 0, i, ro, rS, rS, ro, rS, i, i") - (match_operand:DI - 2 "general_operand" "M, N,rSi,roi, 0, 0, 0,roi,rSi,rSi, rS, ro")))] - "" - "*{ - switch (which_alternative) { - case 0: - return AS2 (mov, w, #1) CR_TAB - AS2 (add, %Z0, w) CR_TAB - AS1 (clr, wreg) CR_TAB - AS2 (addc, %Y0, w) CR_TAB - AS2 (addc, %X0, w) CR_TAB - AS2 (addc, %W0, w) CR_TAB - AS2 (addc, %V0, w) CR_TAB - AS2 (addc, %U0, w) CR_TAB - AS2 (addc, %T0, w) CR_TAB - AS2 (addc, %S0, w); - - case 1: - return AS2 (mov, w, #-1) CR_TAB - AS2 (sub, %Z0, w) CR_TAB - AS2 (subc, %Y0, w) CR_TAB - AS2 (subc, %X0, w) CR_TAB - AS2 (subc, %W0, w) CR_TAB - AS2 (subc, %V0, w) CR_TAB - AS2 (subc, %U0, w) CR_TAB - AS2 (subc, %T0, w) CR_TAB - AS2 (subc, %S0, w); - - case 2: - case 3: - return AS2 (mov, w, %Z2) CR_TAB - AS2 (sub, %Z0, w) CR_TAB - AS2 (mov, w, %Y2) CR_TAB - AS2 (subc, %Y0, w) CR_TAB - AS2 (mov, w, %X2) CR_TAB - AS2 (subc, %X0, w) CR_TAB - AS2 (mov, w, %W2) CR_TAB - AS2 (subc, %W0, w) CR_TAB - AS2 (mov, w, %V2) CR_TAB - AS2 (subc, %V0, w) CR_TAB - AS2 (mov, w, %U2) CR_TAB - AS2 (subc, %U0, w) CR_TAB - AS2 (mov, w, %T2) CR_TAB - AS2 (subc, %T0, w) CR_TAB - AS2 (mov, w, %S2) CR_TAB - AS2 (subc, %S0, w); - - case 4: - return AS2 (mov, w, %Z2) CR_TAB - AS2 (sub, w, %Z1) CR_TAB - AS2 (mov, %Z0, w) CR_TAB - AS1 (push, %Y2%<) CR_TAB - AS2 (mov, w, %Y1) CR_TAB - AS2 (mov, %Y0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %Y0, w) CR_TAB - AS1 (push, %X2%<) CR_TAB - AS2 (mov, w, %X1) CR_TAB - AS2 (mov, %X0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %X0, w) CR_TAB - AS1 (push, %W2%<) CR_TAB - AS2 (mov, w, %W1) CR_TAB - AS2 (mov, %W0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %W0, w) CR_TAB - AS1 (push, %V2%<) CR_TAB - AS2 (mov, w, %V1) CR_TAB - AS2 (mov, %V0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %V0, w) CR_TAB - AS1 (push, %U2%<) CR_TAB - AS2 (mov, w, %U1) CR_TAB - AS2 (mov, %U0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %U0, w) CR_TAB - AS1 (push, %T2%<) CR_TAB - AS2 (mov, w, %T1) CR_TAB - AS2 (mov, %T0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %T0, w) CR_TAB - AS1 (push, %S2%<) CR_TAB - AS2 (mov, w, %S1) CR_TAB - AS2 (mov, %S0, w) CR_TAB - AS1 (pop, wreg%>) CR_TAB - AS2 (subc, %S0, w); - - case 5: - case 6: - case 7: - case 8: - case 9: - return AS2 (mov, w, %Z2) CR_TAB - AS2 (sub, w, %Z1) CR_TAB - AS2 (mov, %Z0, w) CR_TAB - AS2 (mov, w, %Y2) CR_TAB - AS2 (subc, w, %Y1) CR_TAB - AS2 (mov, %Y0, w) CR_TAB - AS2 (mov, w, %X2) CR_TAB - AS2 (subc, w, %X1) CR_TAB - AS2 (mov, %X0, w) CR_TAB - AS2 (mov, w, %W2) CR_TAB - AS2 (subc, w, %W1) CR_TAB - AS2 (mov, %W0, w) CR_TAB - AS2 (mov, w, %V2) CR_TAB - AS2 (subc, w, %V1) CR_TAB - AS2 (mov, %V0, w) CR_TAB - AS2 (mov, w, %U2) CR_TAB - AS2 (subc, w, %U1) CR_TAB - AS2 (mov, %U0, w) CR_TAB - AS2 (mov, w, %T2) CR_TAB - AS2 (subc, w, %T1) CR_TAB - AS2 (mov, %T0, w) CR_TAB - AS2 (mov, w, %S2) CR_TAB - AS2 (subc, w, %S1) CR_TAB - AS2 (mov, %S0, w); - - case 10: - case 11: - return AS2 (mov, w, %Z2) CR_TAB - AS2 (sub, w, %Z1) CR_TAB - AS2 (mov, %Z0, w) CR_TAB - AS2 (mov, w, %Y1) CR_TAB - AS2 (mov, %Y0, w) CR_TAB - AS2 (mov, w, %Y2) CR_TAB - AS2 (subc, %Y0, w) CR_TAB - AS2 (mov, w, %X1) CR_TAB - AS2 (mov, %X0, w) CR_TAB - AS2 (mov, w, %X2) CR_TAB - AS2 (subc, %X0, w) CR_TAB - AS2 (mov, w, %W1) CR_TAB - AS2 (mov, %W0, w) CR_TAB - AS2 (mov, w, %W2) CR_TAB - AS2 (subc, %W0, w) CR_TAB - AS2 (mov, w, %V1) CR_TAB - AS2 (mov, %V0, w) CR_TAB - AS2 (mov, w, %V2) CR_TAB - AS2 (subc, %V0, w) CR_TAB - AS2 (mov, w, %U1) CR_TAB - AS2 (mov, %U0, w) CR_TAB - AS2 (mov, w, %U2) CR_TAB - AS2 (subc, %U0, w) CR_TAB - AS2 (mov, w, %T1) CR_TAB - AS2 (mov, %T0, w) CR_TAB - AS2 (mov, w, %T2) CR_TAB - AS2 (subc, %T0, w) CR_TAB - AS2 (mov, w, %S1) CR_TAB - AS2 (mov, %S0, w) CR_TAB - AS2 (mov, w, %S2) CR_TAB - AS2 (subc, %S0, w); - default: - abort (); - } - }") - -;; -;; Bitwise and instructions. -;; - -(define_expand "andqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (and:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "") - -(define_insn "*andqi3_bit" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR") - (and:QI (match_dup 0) - (match_operand:QI 1 "const_int_operand" "n")))] - "(find_one_clear_bit_p (INTVAL (operands[1]) | 0xffffff00UL) != -1)" - "*{ - operands[2] = GEN_INT (find_one_clear_bit_p (INTVAL (operands[1]) - | 0xffffff00UL)); - return AS2 (clrb, %0, %b2); - }" - [(set_attr "skip" "yes") - (set_attr "clobberw" "no")]) - -(define_insn "*andqi3_w_fr" - [(set (reg:QI 10) - (and:QI (match_operand:QI 0 "general_operand" "roRn") - (reg:QI 10)))] - "(ip2k_reorg_split_qimode)" - "and\\tw,%0" - [(set_attr "skip" "yes")]) - -(define_insn_and_split "*andqi3_fr_w" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR,rS,roR, rS,rS") - (and:QI - (match_operand:QI 1 "nonimmediate_operand" "%0, 0, rS,roR,rS") - (reg:QI 10)))] - "(ip2k_reorg_split_qimode)" - "@ - and\\t%0,w - and\\t%0,w - # - # - #" - "(ip2k_reorg_split_qimode - && ! rtx_equal_p (operands[0], operands[1]))" - [(set (reg:QI 10) - (and:QI (match_dup 1) - (reg:QI 10))) - (set (match_dup 0) - (reg:QI 10))] - "" - [(set_attr "skip" "yes,yes,no,no,no") - (set_attr "clobberw" "no,no,yes,yes,yes")]) - -(define_insn_and_split "*andqi3" ; 0 1 2 3 4 - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR, rS,roR, rS, rS") - (and:QI - (match_operand:QI 1 "nonimmediate_operand" "%0, 0, rS,roR, rS") - (match_operand:QI 2 "general_operand" "rSn,roRn,rSn,rSn,roRn")))] - "" - "@ - mov\\tw,%2\;and\\t%0,w - # - # - # - #" - "(ip2k_reorg_split_qimode - && (! rtx_equal_p (operands[0], operands[1]) - || GET_CODE (operands[2]) != CONST_INT - || find_one_clear_bit_p (INTVAL (operands[2]) | 0xffffff00UL) == -1))" - [(set (reg:QI 10) - (match_dup 2)) - (set (match_dup 0) - (and:QI (match_dup 1) - (reg:QI 10)))]) - -(define_insn_and_split "andhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (and:HI - (match_operand:HI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:HI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_himode)" - [(set (match_dup 3) - (and:QI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (and:QI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[1], QImode); - operands[5] = ip2k_get_high_half (operands[2], QImode); - operands[6] = ip2k_get_low_half (operands[0], QImode); - operands[7] = ip2k_get_low_half (operands[1], QImode); - operands[8] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_insn_and_split "andsi3" ; 0 1 2 3 4 - [(set (match_operand:SI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (and:SI - (match_operand:SI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:SI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_simode)" - [(set (match_dup 3) - (and:HI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (and:HI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_high_half (operands[1], HImode); - operands[5] = ip2k_get_high_half (operands[2], HImode); - operands[6] = ip2k_get_low_half (operands[0], HImode); - operands[7] = ip2k_get_low_half (operands[1], HImode); - operands[8] = ip2k_get_low_half (operands[2], HImode); - }") - -(define_insn_and_split "anddi3" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (and:DI - (match_operand:DI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:DI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_dimode)" - [(set (match_dup 3) - (and:SI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (and:SI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_high_half (operands[1], SImode); - operands[5] = ip2k_get_high_half (operands[2], SImode); - operands[6] = ip2k_get_low_half (operands[0], SImode); - operands[7] = ip2k_get_low_half (operands[1], SImode); - operands[8] = ip2k_get_low_half (operands[2], SImode); - }") - -;; -;; Bitwise or instructions. -;; - -(define_expand "iorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (ior:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "") - -(define_insn "*iorqi3_bit" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR") - (ior:QI (match_dup 0) - (match_operand:QI 1 "const_int_operand" "n")))] - "(find_one_set_bit_p (INTVAL (operands[1]) & 0xff) != -1)" - "*{ - operands[2] = GEN_INT (find_one_set_bit_p (INTVAL (operands[1]) & 0xff)); - return AS2 (setb, %0, %b2); - }" - [(set_attr "skip" "yes") - (set_attr "clobberw" "no")]) - -(define_insn "*iorqi3" ; 0 1 2 3 4 - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR, rS,roR, rS, rS") - (ior:QI - (match_operand:QI 1 "nonimmediate_operand" "%0, 0, rS,roR, rS") - (match_operand:QI 2 "general_operand" "rSi,roRi,rSi,rSi,roRi")))] - "" - "@ - mov\\tw,%2\;or\\t%0,w - mov\\tw,%2\;or\\t%0,w - mov\\tw,%2\;or\\tw,%1\;mov\\t%0,w - mov\\tw,%2\;or\\tw,%1\;mov\\t%0,w - mov\\tw,%2\;or\\tw,%1\;mov\\t%0,w") - -(define_insn_and_split "iorhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (ior:HI - (match_operand:HI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:HI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_himode)" - [(set (match_dup 3) - (ior:QI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (ior:QI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[1], QImode); - operands[5] = ip2k_get_high_half (operands[2], QImode); - operands[6] = ip2k_get_low_half (operands[0], QImode); - operands[7] = ip2k_get_low_half (operands[1], QImode); - operands[8] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_insn_and_split "iorsi3" ; 0 1 2 3 4 - [(set (match_operand:SI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (ior:SI - (match_operand:SI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:SI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_simode)" - [(set (match_dup 3) - (ior:HI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (ior:HI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_high_half (operands[1], HImode); - operands[5] = ip2k_get_high_half (operands[2], HImode); - operands[6] = ip2k_get_low_half (operands[0], HImode); - operands[7] = ip2k_get_low_half (operands[1], HImode); - operands[8] = ip2k_get_low_half (operands[2], HImode); - }") - -(define_insn_and_split "iordi3" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (ior:DI - (match_operand:DI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:DI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_dimode)" - [(set (match_dup 3) - (ior:SI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (ior:SI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_high_half (operands[1], SImode); - operands[5] = ip2k_get_high_half (operands[2], SImode); - operands[6] = ip2k_get_low_half (operands[0], SImode); - operands[7] = ip2k_get_low_half (operands[1], SImode); - operands[8] = ip2k_get_low_half (operands[2], SImode); - }") - -;; -;; Bitwise xor instructions -;; -;; TODO: xor ops can also use "not w, fr"! -;; - -(define_insn "xorqi3" - [(set - (match_operand:QI 0 "nonimmediate_operand" "=roR,roR, rS,roR, rS, rS") - (xor:QI (match_operand:QI 1 "general_operand" "%0, 0, 0, rS,roR, rS") - (match_operand:QI 2 "general_operand" "M,rSi,roRi,rSi,rSi,roRi")))] - "" - "@ - not\\t%0 - mov\\tw,%2\;xor\\t%0,w - mov\\tw,%2\;xor\\t%0,w - mov\\tw,%1\;xor\\tw,%2\;mov\\t%0,w - mov\\tw,%1\;xor\\tw,%2\;mov\\t%0,w - mov\\tw,%1\;xor\\tw,%2\;mov\\t%0,w" - [(set_attr "clobberw" "no,yes,yes,yes,yes,yes")]) - -(define_insn_and_split "xorhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (xor:HI - (match_operand:HI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:HI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_himode)" - [(set (match_dup 3) - (xor:QI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (xor:QI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[1], QImode); - operands[5] = ip2k_get_high_half (operands[2], QImode); - operands[6] = ip2k_get_low_half (operands[0], QImode); - operands[7] = ip2k_get_low_half (operands[1], QImode); - operands[8] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_insn_and_split "xorsi3" ; 0 1 2 3 4 - [(set (match_operand:SI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (xor:SI - (match_operand:SI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:SI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_simode)" - [(set (match_dup 3) - (xor:HI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (xor:HI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_high_half (operands[1], HImode); - operands[5] = ip2k_get_high_half (operands[2], HImode); - operands[6] = ip2k_get_low_half (operands[0], HImode); - operands[7] = ip2k_get_low_half (operands[1], HImode); - operands[8] = ip2k_get_low_half (operands[2], HImode); - }") - -(define_insn_and_split "xordi3" ; 0 1 2 3 4 - [(set (match_operand:DI 0 "nonimmediate_operand" "=uo, uS,&dS,&do,&dS") - (xor:DI - (match_operand:DI 1 "nonimmediate_operand" "%0, 0, ro, rS, rS") - (match_operand:DI 2 "general_operand" "rSn,ron,rSn,rSn,ron")))] - "" - "#" - "(ip2k_reorg_split_dimode)" - [(set (match_dup 3) - (xor:SI (match_dup 4) - (match_dup 5))) - (set (match_dup 6) - (xor:SI (match_dup 7) - (match_dup 8)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_high_half (operands[1], SImode); - operands[5] = ip2k_get_high_half (operands[2], SImode); - operands[6] = ip2k_get_low_half (operands[0], SImode); - operands[7] = ip2k_get_low_half (operands[1], SImode); - operands[8] = ip2k_get_low_half (operands[2], SImode); - }") - -;; -;; Multiply instructions. -;; - -(define_insn "umulqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=ro, rS, rS") - (mult:QI (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS") - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi")))] - "" - "mov\\tw,%1\;mulu\\tw,%2\;mov\\t%0,w") - -(define_insn "mulqihi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS, rS") - (mult:HI - (sign_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS")) - (sign_extend:HI - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi"))))] - "" - "@ - mov\\tw,%1\;muls\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w - mov\\tw,%1\;muls\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w - mov\\tw,%1\;muls\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w") - -(define_insn_and_split "umulqihi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS, rS") - (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS")) - (zero_extend:HI - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi"))))] - "" - "#" - "ip2k_reorg_split_qimode" - [(set (match_dup 3) - (mult:QI (match_dup 1) - (match_dup 2))) - (set (reg:QI 10) - (reg:QI 15)) - (set (match_dup 4) - (reg:QI 10))] - "{ - operands[3] = ip2k_get_low_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[0], QImode); - }") - -(define_insn "*mulhi3_by2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "0, rS, ro") - (zero_extend:HI (const_int 2))))] - "" - "@ - clrb\\tSTATUS,0\;rl\\t%L0\;rl\\t%H0 - clrb\\tSTATUS,0\;rl\\tw,%L1\;mov\\t%L0,w\;rl\\tw,%H1\;mov\\t%H0,w - clrb\\tSTATUS,0\;rl\\tw,%L1\;mov\\t%L0,w\;rl\\tw,%H1\;mov\\t%H0,w" - [(set_attr "clobberw" "no,yes,yes")]) - -(define_insn "*mulhi3_byqi" - [(set (match_operand:HI - 0 "nonimmediate_operand" "=ro,&ro,&rS, &rS") - (mult:HI (match_operand:HI - 1 "nonimmediate_operand" "0, rS, ro, rS") - (zero_extend:HI (match_operand:QI - 2 "general_operand" "rSi,rSi,rSi,roRi"))))] - "" - "@ - mov\\tw,%L1\;mulu\\tw,%2\;mov\\t%L0,w\;push\\tmulh%<\;mov\\tw,%H1\;mulu\\tw,%2\;pop\\t%H0%>\;add\\t%H0,w - mov\\tw,%L1\;mulu\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w\;mov\\tw,%H1\;mulu\\tw,%2\;add\\t%H0,w - mov\\tw,%L1\;mulu\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w\;mov\\tw,%H1\;mulu\\tw,%2\;add\\t%H0,w - mov\\tw,%L1\;mulu\\tw,%2\;mov\\t%L0,w\;mov\\tw,mulh\;mov\\t%H0,w\;mov\\tw,%H1\;mulu\\tw,%2\;add\\t%H0,w") - -(define_insn "smulqi_highpart" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR, rS, rS") - (truncate:QI - (lshiftrt:HI - (mult:HI - (sign_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS")) - (sign_extend:HI - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi"))) - (const_int 8))))] - "" - "@ - mov\\tw,%1\;muls\\tw,%2\;mov\\tw,mulh\;mov %0,w - mov\\tw,%1\;muls\\tw,%2\;mov\\tw,mulh\;mov %0,w - mov\\tw,%1\;muls\\tw,%2\;mov\\tw,mulh\;mov %0,w") - -(define_insn "umulqi_highpart" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR, rS, rS") - (truncate:QI - (lshiftrt:HI - (mult:HI - (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "%rS,roR, rS")) - (zero_extend:HI - (match_operand:QI 2 "general_operand" "rSi,rSi,roRi"))) - (const_int 8))))] - "" - "@ - mov\\tw,%1\;mulu\\tw,%2\;mov\\tw,mulh\;mov %0,w - mov\\tw,%1\;mulu\\tw,%2\;mov\\tw,mulh\;mov %0,w - mov\\tw,%1\;mulu\\tw,%2\;mov\\tw,mulh\;mov %0,w") - -(define_insn "mulhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=uo, uS, uS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rS, ro, rS") - (match_operand:HI 2 "general_operand" "rSi,rSi,roi")))] - "" - "push\\t%L2%<\;push\\t%H2%<\;push\\t%L1%<\;push\\t%H1%>\;page\\t__mulhi3\;call\\t__mulhi3\;pop\\t%H0%>\;pop\\t%L0%>") - -;; If we find that we're multiplying by a constant that's less than 256 we -;; can replace a full "mulhi3" with one of the lighter weight variants -;; that multiplies an HImode value by a QImode one. -;; -(define_split - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,rS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "rS,ro") - (match_operand:HI 2 "const_int_operand" "P, P")))] - "(INTVAL (operands[2]) < 0x100)" - [(set (match_dup 0) - (mult:HI (match_dup 1) - (zero_extend:HI (match_dup 3))))] - "operands[3] = gen_int_mode (INTVAL (operands[2]), QImode);") - -;; -;; Divide/Modulus functions. -;; - -(define_expand "udivmodhi4" - [(parallel [(set (reg:HI 128) - (udiv:HI (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (set (reg:HI 130) - (umod:HI (match_dup 1) (match_dup 2))) - (clobber (reg:QI 132)) - (clobber (reg:QI 133))]) - (set (match_operand:HI 0 "general_operand" "") (reg:HI 128)) - (set (match_operand:HI 3 "general_operand" "") (reg:HI 130))] - "" - "") - -(define_insn "*udivmodhi4_call" - [(set (reg:HI 128) - (udiv:HI (match_operand:HI 0 "general_operand" "uSi,uoi") - (match_operand:HI 1 "general_operand" "uoi,uSi"))) - (set (reg:HI 130) - (umod:HI (match_dup 0) (match_dup 1))) - (clobber (reg:QI 132)) - (clobber (reg:QI 133))] - "" - "push\\t%L1%<\;push\\t%H1%<\;push\\t%L0%<\;push\\t%H0%>%>%>\;page\\t__udivmodhi4\;call\\t__udivmodhi4") - -(define_expand "divmodhi4" - [(parallel [(set (reg:HI 128) - (div:HI (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (set (reg:HI 130) - (mod:HI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 132)) - (clobber (reg:QI 133)) - (clobber (reg:QI 134)) - (clobber (reg:QI 135))]) - (set (match_operand:HI 0 "general_operand" "") (reg:HI 128)) - (set (match_operand:HI 3 "general_operand" "") (reg:HI 130))] - "" - "") - -(define_insn "*divmodhi4_call" - [(set (reg:HI 128) - (div:HI (match_operand:HI 0 "general_operand" "uSi,uoi") - (match_operand:HI 1 "general_operand" "uoi,uSi"))) - (set (reg:HI 130) - (mod:HI (match_dup 0) (match_dup 1))) - (clobber (reg:QI 132)) - (clobber (reg:QI 133)) - (clobber (reg:QI 134)) - (clobber (reg:QI 135))] - "" - "push\\t%L1%<\;push\\t%H1%<\;push\\t%L0%<\;push\\t%H0%>%>%>\;page\\t__divmodhi4\;call\\t__divmodhi4") - -(define_expand "udivmodsi4" - [(parallel [(set (reg:SI 128) - (udiv:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" ""))) - (set (reg:SI 132) - (umod:SI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 136)) - (clobber (reg:QI 137)) - (clobber (reg:QI 138)) - (clobber (reg:QI 139))]) - (set (match_operand:SI 0 "general_operand" "") (reg:SI 128)) - (set (match_operand:SI 3 "general_operand" "") (reg:SI 132))] - "" - "") - -(define_insn "*udivmodsi4_call" - [(set (reg:SI 128) - (udiv:SI (match_operand:SI 0 "general_operand" "rSi,roi") - (match_operand:SI 1 "general_operand" "roi,rSi"))) - (set (reg:SI 132) - (umod:SI (match_dup 0) - (match_dup 1))) - (clobber (reg:QI 136)) - (clobber (reg:QI 137)) - (clobber (reg:QI 138)) - (clobber (reg:QI 139))] - "" - "push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%<\;push\\t%D0%<\;push\\t%C0%<\;push\\t%B0%<\;push\\t%A0%>%>%>%>%>%>%>\;page\\t__udivmodsi4\;call\\t__udivmodsi4") - -(define_expand "divmodsi4" - [(parallel [(set (reg:SI 128) - (div:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" ""))) - (set (reg:SI 132) - (mod:SI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 136)) - (clobber (reg:QI 137)) - (clobber (reg:QI 138)) - (clobber (reg:QI 139)) - (clobber (reg:QI 140)) - (clobber (reg:QI 141))]) - (set (match_operand:SI 0 "general_operand" "") (reg:SI 128)) - (set (match_operand:SI 3 "general_operand" "") (reg:SI 132))] - "" - "") - -(define_insn "*divmodsi4_call" - [(set (reg:SI 128) - (div:SI (match_operand:SI 0 "general_operand" "rSn,ron") - (match_operand:SI 1 "general_operand" "ron,rSn"))) - (set (reg:SI 132) - (mod:SI (match_dup 0) - (match_dup 1))) - (clobber (reg:QI 136)) - (clobber (reg:QI 137)) - (clobber (reg:QI 138)) - (clobber (reg:QI 139)) - (clobber (reg:QI 140)) - (clobber (reg:QI 141))] - "" - "push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%<\;push\\t%D0%<\;push\\t%C0%<\;push\\t%B0%<\;push\\t%A0%>%>%>%>%>%>%>\;page\\t__divmodsi4\;call\\t__divmodsi4") - -(define_expand "udivmoddi4" - [(parallel [(set (reg:DI 128) - (udiv:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" ""))) - (set (reg:DI 136) - (umod:DI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 144)) - (clobber (reg:QI 145)) - (clobber (reg:QI 146)) - (clobber (reg:QI 147)) - (clobber (reg:QI 148)) - (clobber (reg:QI 149)) - (clobber (reg:QI 150)) - (clobber (reg:QI 151))]) - (set (match_operand:DI 0 "general_operand" "") (reg:DI 128)) - (set (match_operand:DI 3 "general_operand" "") (reg:DI 136))] - "" - "") - -(define_insn "*udivmoddi4_call" - [(set (reg:DI 128) - (udiv:DI (match_operand:DI 0 "general_operand" "rSi,roi") - (match_operand:DI 1 "general_operand" "roi,rSi"))) - (set (reg:DI 136) - (umod:DI (match_dup 0) - (match_dup 1))) - (clobber (reg:QI 144)) - (clobber (reg:QI 145)) - (clobber (reg:QI 146)) - (clobber (reg:QI 147)) - (clobber (reg:QI 148)) - (clobber (reg:QI 149)) - (clobber (reg:QI 150)) - (clobber (reg:QI 151))] - "" - "push\\t%Z1%<\;push\\t%Y1%<\;push\\t%X1%<\;push\\t%W1%<\;push\\t%V1%<\;push\\t%U1%<\;push\\t%T1%<\;push\\t%S1%<\;push\\t%Z0%<\;push\\t%Y0%<\;push\\t%X0%<\;push\\t%W0%<\;push\\t%V0%<\;push\\t%U0%<\;push\\t%T0%<\;push\\t%S00%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>\;page\\t__udivmoddi4\;call\\t__udivmoddi4") - -(define_expand "divmoddi4" - [(parallel [(set (reg:DI 128) - (div:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" ""))) - (set (reg:DI 136) - (mod:DI (match_dup 1) - (match_dup 2))) - (clobber (reg:QI 144)) - (clobber (reg:QI 145)) - (clobber (reg:QI 146)) - (clobber (reg:QI 147)) - (clobber (reg:QI 148)) - (clobber (reg:QI 149)) - (clobber (reg:QI 150)) - (clobber (reg:QI 151))]) - (set (match_operand:DI 0 "general_operand" "") (reg:DI 128)) - (set (match_operand:DI 3 "general_operand" "") (reg:DI 136))] - "" - "") - -(define_insn "*divmoddi4_call" - [(set (reg:DI 128) - (div:DI (match_operand:DI 0 "general_operand" "rSn,ron") - (match_operand:DI 1 "general_operand" "ron,rSn"))) - (set (reg:DI 136) - (mod:DI (match_dup 0) - (match_dup 1))) - (clobber (reg:QI 144)) - (clobber (reg:QI 145)) - (clobber (reg:QI 146)) - (clobber (reg:QI 147)) - (clobber (reg:QI 148)) - (clobber (reg:QI 149)) - (clobber (reg:QI 150)) - (clobber (reg:QI 151))] - "" - "push\\t%Z1%<\;push\\t%Y1%<\;push\\t%X1%<\;push\\t%W1%<\;push\\t%V1%<\;push\\t%U1%<\;push\\t%T1%<\;push\\t%S1%<\;push\\t%Z0%<\;push\\t%Y0%<\;push\\t%X0%<\;push\\t%W0%<\;push\\t%V0%<\;push\\t%U0%<\;push\\t%T0%<\;push\\t%S00%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>\;page\\t__divmoddi4\;call\\t__divmoddi4") - -;; -;; Arithmetic shift left instructions. -;; - -(define_insn "ashlqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=roR,roR, rS,roR, rS") - (ashift:QI - (match_operand:QI 1 "nonimmediate_operand" "0, rS,roR, 0, 0") - (match_operand:QI 2 "general_operand" "N, L, L, rS,roR")))] - "" - "@ - clrb status,0\;rl\\t%0 - mov\\tw,%e2\;mulu\\tw,%1\;mov\\t%0,w - mov\\tw,%e2\;mulu\\tw,%1\;mov\\t%0,w - mov\\tw,%2\;snz\;page\\t1f\;jmp\\t1f\;2:clrb\\tstatus,0\;rl\\t%0\;decsz\\twreg\;page\\t2b\;jmp\\t2b\;1: - mov\\tw,%2\;snz\;page\\t1f\;jmp\\t1f\;2:clrb\\tstatus,0\;rl\\t%0\;decsz\\twreg\;page\\t2b\;jmp\\t2b\;1:" - [(set_attr "clobberw" "no,yes,yes,yes,yes")]) - -;; Convert simple fixed-size shift of a zero-extended QImode value into a -;; multiply as our multiplier is much faster. We also do this so that the -;; multiply can possibly be merged into a much faster multiply-and-accumulate -;; operation. -;; -(define_split - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (ashift:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR")) - (match_operand:QI 2 "const_int_operand" "J, J")))] - "(INTVAL (operands[2]) < 8)" - [(set (match_dup 0) - (mult:HI (zero_extend:HI (match_dup 1)) - (zero_extend:HI (match_dup 3))))] - "operands[3] = gen_int_mode (1 << INTVAL (operands[2]), QImode);") - -(define_insn_and_split "*ashlhi3_by8_zero_extend" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (ashift:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR")) - (const_int 8)))] - "" - "#" - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], QImode); - operands[3] = ip2k_get_low_half (operands[0], QImode); - }") - -(define_insn "*ashlhi3_zero_extend" ; 0 1 - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (ashift:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS,roR")) - (match_operand:QI 2 "const_int_operand" "n, n")))] - "" - "*{ - if (INTVAL (operands[2]) < 8) - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w); - else - { - operands[3] = GEN_INT (INTVAL (operands[2]) - 8); - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %e3) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS1 (clr, %L0); - } - }") - -;; Convert simple fixed-size shift of a HImode value into a multiply as -;; our multiplier is much faster. We also do this so that the multiply can -;; possibly be merged into a much faster multiply-and-accumulate operation. -;; -(define_split - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,rS") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "rS,ro") - (match_operand:QI 2 "const_int_operand" "J, J")))] - "(INTVAL (operands[2]) < 8)" - [(set (match_dup 0) - (mult:HI (match_dup 1) - (zero_extend:HI (match_dup 3))))] - "operands[3] = gen_int_mode (1 << INTVAL (operands[2]), QImode);") - -(define_insn_and_split "ashlhi3_split" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,rS") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "rS,ro") - (match_operand:QI 2 "const_int_operand" "n, n")))] - "(INTVAL (operands[2]) >= 8)" - "#" - "&& ip2k_reorg_split_himode" - [(set (match_dup 4) (const_int 0))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_low_half (operands[0], QImode); - operands[5] = ip2k_get_low_half (operands[1], QImode); - - if (INTVAL (operands[2]) == 8) - emit_insn (gen_movqi (operands[3], operands[5])); - else - { - operands[6] = gen_int_mode (INTVAL (operands[2]) - 8, QImode); - emit_insn (gen_ashlqi3 (operands[3], operands[5], operands[6])); - } - }") - -(define_insn "ashlhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&rS,&ro,ro, rS") - (ashift:HI - (match_operand:HI 1 "nonimmediate_operand" "0, ro, rS, 0, 0") - (match_operand:QI 2 "general_operand" "L, L, L,rS,roR")))] - "" - "*{ - switch (which_alternative) - { - case 0: - switch (INTVAL (operands[2])) - { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0); - - case 3: - case 4: - case 5: - case 6: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (push, MULH%<) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (or, 1(SP), w) CR_TAB - AS1 (pop, %H0%>); - - case 7: - return AS1 (rr, %H0) CR_TAB - AS2 (mov, w, %L0) CR_TAB - AS1 (clr, %L0) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - default: - /* Should be caught by a different insn pattern */ - abort (); - } - - case 1: - case 2: - switch (INTVAL (operands[2])) - { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rl, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (rl, w, %H1) CR_TAB - AS2 (mov, %H0, w); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rl, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (rl, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0); - - case 3: - case 4: - case 5: - case 6: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (push, MULH%<) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (or, 1(SP), w) CR_TAB - AS1 (pop, %H0%>); - - case 7: - return AS2 (rr, w, %H1) CR_TAB - AS2 (mov, w, %L1) CR_TAB - AS1 (clr, %L0) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - default: - /* Should be caught by a different insn pattern */ - abort (); - } - - case 3: - case 4: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %L0) CR_TAB - AS1 (rl, %H0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - default: - abort(); - } - }") - -(define_insn_and_split "*ashlsi3_by16_zero_extend" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,rS") - (ashift:SI (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "rS,ro")) - (const_int 16)))] - "" - "#" - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], HImode); - operands[3] = ip2k_get_low_half (operands[0], HImode); - }") - -(define_insn_and_split "ashlsi3_split" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0, rS, ro") - (match_operand:QI 2 "const_int_operand" "n, n, n")))] - "(INTVAL (operands[2]) >= 16)" - "#" - "&& ip2k_reorg_split_simode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_low_half (operands[0], HImode); - operands[5] = ip2k_get_low_half (operands[1], HImode); - - if (INTVAL (operands[2]) == 16) - { - emit_insn (gen_movhi (operands[3], operands[5])); - emit_insn (gen_movhi (operands[4], GEN_INT (0))); - } - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 16); - emit_insn (gen_ashlhi3 (operands[3], operands[5], operands[6])); - emit_insn (gen_movhi (operands[4], GEN_INT (0))); - } - }") - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,ro,&ro,&rS") - (ashift:SI - (match_operand:SI 1 "nonimmediate_operand" "0, 0, 0, rS, ro") - (match_operand:QI 2 "general_operand" "L,roR,rS, L, L")))] - "" - "*{ - switch (which_alternative) { - case 0: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0); - - case 8: - return AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %C0) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %D0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, %D0); - - case 16: - return AS2 (mov, w, %C0) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %D0) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0); - - case 23: - return AS2 (rr, w, %C0) CR_TAB - AS2 (mov, w, %D0) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0); - - case 24: - return AS2 (mov, w, %D0) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0); - - case 31: - return AS2 (rr, w, %D0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (rr, %A0); - - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 1: - case 2: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 3: - case 4: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rl, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (rl, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rl, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rl, w, %A1) CR_TAB - AS2 (mov, %A0, w); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rl, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (rl, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rl, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rl, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0); - - case 8: - return AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, %D0); - - case 16: - return AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0); - - case 23: - return AS2 (rr, w, %C1) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0); - - case 24: - return AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0); - - case 31: - return AS2 (rr, w, %D1) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (rr, %A0); - - default: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0) CR_TAB - AS1 (rl, %B0) CR_TAB - AS1 (rl, %A0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - default: - abort (); - } - }") - -(define_insn_and_split "ashldi3_split" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0, rS, ro") - (match_operand:QI 2 "const_int_operand" "n, n, n")))] - "((INTVAL (operands[2]) >= 32) || (INTVAL (operands[2]) == 16))" - "#" - "&& ip2k_reorg_split_dimode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_low_half (operands[0], SImode); - operands[5] = ip2k_get_low_half (operands[1], SImode); - - if (INTVAL (operands[2]) == 16) - { - operands[6] = ip2k_get_high_half (operands[1], SImode); - operands[7] = ip2k_get_high_half (operands[3], HImode); - operands[8] = ip2k_get_low_half (operands[3], HImode); - operands[9] = ip2k_get_high_half (operands[4], HImode); - operands[10] = ip2k_get_low_half (operands[4], HImode); - operands[11] = ip2k_get_low_half (operands[6], HImode); - operands[12] = ip2k_get_high_half (operands[5], HImode); - operands[13] = ip2k_get_low_half (operands[5], HImode); - emit_insn (gen_movhi (operands[7], operands[11])); - emit_insn (gen_movhi (operands[8], operands[12])); - emit_insn (gen_movhi (operands[9], operands[13])); - emit_insn (gen_movhi (operands[10], GEN_INT (0))); - } - else if (INTVAL (operands[2]) == 32) - { - emit_insn (gen_movsi (operands[3], operands[5])); - emit_insn (gen_movsi (operands[4], GEN_INT (0))); - } - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 32); - emit_insn (gen_ashlsi3 (operands[3], operands[5], operands[6])); - emit_insn (gen_movsi (operands[4], GEN_INT (0))); - } - }") - -;; -;; Arithmetic shift right instructions. -;; - -(define_expand "ashrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "if (operands[2] == const0_rtx) - { - emit_move_insn (operands[0], operands[1]); - DONE; - } - ") - -(define_insn "*ashrqi3" - [(set - (match_operand:QI 0 "nonimmediate_operand" "=roR,roR, rS,roR, rS,roR, rS") - (ashiftrt:QI - (match_operand:QI 1 "nonimmediate_operand" "0, 0, 0, rS,roR, rS,roR") - (match_operand:QI 2 "general_operand" "N, rS,roR, N, N, L, L")))] - "" - "*{ - switch (which_alternative) - { - case 0: - return AS2 (rl, w, %0) CR_TAB - AS1 (rr, %0); - - case 3: - case 4: - return AS2 (rl, w, %1) CR_TAB /* dup the sign bit */ - AS2 (rr, w, %1) CR_TAB - AS2 (mov, %0, w); - - case 5: - case 6: - /* Do >> by left-shifting partially into MULH. */ - operands[2] = GEN_INT (8 - INTVAL (operands[2])); - return AS2 (mov, w, %1) CR_TAB - AS2 (muls, w, %e2) CR_TAB - AS2 (mov, w, mulh) CR_TAB - AS2 (mov, %0, w); - - case 1: - case 2: - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - } - }") - -(define_insn "ashrhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&rS,&ro,ro, rS") - (ashiftrt:HI - (match_operand:HI 1 "nonimmediate_operand" "0, ro, rS, 0, 0") - (match_operand:QI 2 "general_operand" "L, L, L,rS,roR")))] - "" - "*{ - switch (which_alternative) { - case 0: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (rl, w, %H0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 2: - return AS2 (rl, w, %H0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS2 (rl, w, %H0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 8: - return AS2 (mov, w, %H0) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (clr, %H0) CR_TAB - AS2 (snb, %L0, 7) CR_TAB - AS1 (not, %H0); - - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %H0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 1: - case 2: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (rl, w, %H1) CR_TAB - AS2 (rr, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (rr, w, %L1) CR_TAB - AS2 (mov, %L0, w); - - case 2: - return AS2 (rl, w, %H1) CR_TAB - AS2 (rr, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (rr, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (rl, w, %H0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 8: - return AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (clr, %H0) CR_TAB - AS2 (snb, %L0, 7) CR_TAB - AS1 (not, %H0); - - default: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %H0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 3: - case 4: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %H0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - default: - abort(); - } - }") - -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,ro,&ro,&rS") - (ashiftrt:SI - (match_operand:SI 1 "nonimmediate_operand" "0, 0, 0, rS, ro") - (match_operand:QI 2 "general_operand" "L,roR,rS, L, L")))] - "" - "*{ - switch (which_alternative) { - case 0: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (rl, w, %A0) CR_TAB /* dup the sign bit */ - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 2: - return AS2 (rl, w, %A0) CR_TAB /* dup the sign bit */ - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS2 (rl, w, %A0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 8: - return AS2 (mov, w, %C0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %A0) CR_TAB - AS2 (snb, %B0, 7) CR_TAB - AS1 (not, %A0); - - case 16: - return AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %C0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w); - - case 23: - return AS2 (rl, w, %B0) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %D0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0); - - case 24: - return AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %D0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w); - - case 31: - return AS2 (rl, w, %A0) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %A0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (rl, %D0); - - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %A0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, WREG) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 1: - case 2: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %A0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, WREG) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 3: - case 4: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (rl, w, %A1) CR_TAB /* dup the sign bit */ - AS2 (rr, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (rr, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rr, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rr, w, %D1) CR_TAB - AS2 (mov, %D0, w); - - case 2: - return AS2 (rl, w, %A1) CR_TAB /* dup the sign bit */ - AS2 (rr, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (rr, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rr, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rr, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (rl, w, %A0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 8: - return AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %A0) CR_TAB - AS2 (snb, %B0, 7) CR_TAB - AS1 (not, %A0); - - case 16: - return AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %C0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w); - - case 23: - return AS2 (rl, w, %B1) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %D0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0); - - case 24: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %D0, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w); - - case 31: - return AS2 (rl, w, %A1) CR_TAB - AS1 (clr, WREG) CR_TAB - AS2 (snb, %A1, 7) CR_TAB - AS1 (not, WREG) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS1 (rl, %D0); - - default: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (setb, status, 0) CR_TAB - AS2 (sb, %A0, 7) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - default: - abort (); - } - }") - -;; -;; Logical shift right instructions. -;; - -(define_insn "lshrqi3" - [(set (match_operand:QI - 0 "nonimmediate_operand" "=roR, rS,roR,roR, rS,&roR,roR, rS") - (lshiftrt:QI - (match_operand:QI - 1 "nonimmediate_operand" "0, 0, 0, rS,roR, rS, rS,roR") - (match_operand:QI - 2 "general_operand" "N,roR, rS, N, N, rS, L, L")))] - "" - "*{ - switch (which_alternative) - { - case 0: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %0); - - case 1: - case 2: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 3: - case 4: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %1) CR_TAB - AS2 (mov, %0, w); - - case 5: - return AS2 (mov, w, %1) CR_TAB - AS2 (mov, %0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 6: - case 7: - /* Do >> by left-shifting partially into MULH. */ - operands[2] = GEN_INT (8 - INTVAL (operands[2])); - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, w, mulh) CR_TAB - AS2 (mov, %0, w); - default: - abort (); - } - }") - -(define_insn_and_split "lshrhi3_split" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,rS") - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "rS,ro") - (match_operand:QI 2 "const_int_operand" "n, n")))] - "(INTVAL (operands[2]) >= 8)" - "#" - "&& ip2k_reorg_split_himode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_low_half (operands[0], QImode); - operands[5] = ip2k_get_high_half (operands[1], QImode); - - if (INTVAL (operands[2]) == 8) - emit_insn (gen_movqi (operands[4], operands[5])); - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 8); - emit_insn (gen_lshrqi3 (operands[4], operands[5], operands[6])); - } - emit_insn (gen_movqi (operands[3], GEN_INT (0))); - }") - -(define_insn "lshrhi3" ; 0 1 2 3 4 - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&rS,&ro,ro, rS") - (lshiftrt:HI - (match_operand:HI 1 "nonimmediate_operand" " 0, ro, rS, 0, 0") - (match_operand:QI 2 "general_operand" "L, L, L,rS,roR")))] - "" - "*{ - switch (which_alternative) - { - case 0: - switch (INTVAL (operands[2])) - { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 3: - case 4: - case 5: - case 6: - case 7: - operands[2] = GEN_INT (8 - INTVAL (operands[2])); - return AS2 (mov, w, %L0) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H0) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (or, %L0, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w); - - default: - /* Should be caught by a different insn pattern */ - abort (); - } - - case 1: - case 2: - switch (INTVAL (operands[2])) - { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (rr, w, %L1) CR_TAB - AS2 (mov, %L0, w); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (rr, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0); - - case 3: - case 4: - case 5: - case 6: - case 7: - operands[2] = GEN_INT (8 - INTVAL (operands[2])); - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %e2) CR_TAB - AS2 (or, %L0, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w); - - default: - /* Should be caught by a different insn pattern */ - abort (); - } - - case 3: - case 4: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %H0) CR_TAB - AS1 (rr, %L0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - default: - abort(); - } - }") - -(define_insn_and_split "lshrsi3_split" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0, rS, ro") - (match_operand:QI 2 "const_int_operand" "n, n, n")))] - "(INTVAL (operands[2]) >= 16)" - "#" - "&& ip2k_reorg_split_simode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_low_half (operands[0], HImode); - operands[5] = ip2k_get_high_half (operands[1], HImode); - - if (INTVAL (operands[2]) == 16) - emit_insn (gen_movhi (operands[4], operands[5])); - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 16); - emit_insn (gen_lshrhi3 (operands[4], operands[5], operands[6])); - } - emit_insn (gen_movhi (operands[3], GEN_INT (0))); - }") - -;; This occurs frequently in supporting FP among other things, -;; and out-of-line is almost as big as inline, so.... -;; -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,ro,&ro,&rS") - (lshiftrt:SI - (match_operand:SI 1 "nonimmediate_operand" "0, 0, 0, rS, ro") - (match_operand:QI 2 "general_operand" "L,roR,rS, L, L")))] - - "" - "*{ - switch (which_alternative) { - case 0: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 8: - return AS2 (mov, w, %C0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %A0); - - case 16: - return AS2 (mov, w, %B0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0); - - case 23: - return AS2 (rl, w, %B0) CR_TAB - AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0); - - case 24: - return AS2 (mov, w, %A0) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0); - - case 31: - return AS2 (rl, w, %A0) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (rl, %D0); - - default: - return AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - - case 1: - case 2: - return AS2 (mov, w, %2) CR_TAB - AS1 (snz,) CR_TAB - AS1 (page, 2f) CR_TAB - AS1 (jmp, 2f) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b) CR_TAB - AS1 (2:,); - - case 3: - case 4: - switch (INTVAL (operands[2])) { - case 1: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (rr, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rr, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rr, w, %D1) CR_TAB - AS2 (mov, %D0, w); - - case 2: - return AS2 (clrb, status, 0) CR_TAB - AS2 (rr, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (rr, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (rr, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (rr, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0); - - case 8: - return AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS1 (clr, %A0); - - case 16: - return AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0); - - case 23: - return AS2 (rl, w, %B1) CR_TAB - AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (rl, %D0) CR_TAB - AS1 (rl, %C0); - - case 24: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0); - - case 31: - return AS2 (rl, w, %A1) CR_TAB - AS1 (clr, %D0) CR_TAB - AS1 (clr, %C0) CR_TAB - AS1 (clr, %B0) CR_TAB - AS1 (clr, %A0) CR_TAB - AS1 (rl, %D0); - - default: - return AS2 (mov, w, %A1) CR_TAB - AS2 (mov, %A0, w) CR_TAB - AS2 (mov, w, %B1) CR_TAB - AS2 (mov, %B0, w) CR_TAB - AS2 (mov, w, %C1) CR_TAB - AS2 (mov, %C0, w) CR_TAB - AS2 (mov, w, %D1) CR_TAB - AS2 (mov, %D0, w) CR_TAB - AS2 (mov, w, %2) CR_TAB - AS1 (1:,) CR_TAB - AS2 (clrb, status, 0) CR_TAB - AS1 (rr, %A0) CR_TAB - AS1 (rr, %B0) CR_TAB - AS1 (rr, %C0) CR_TAB - AS1 (rr, %D0) CR_TAB - AS1 (decsz, wreg) CR_TAB - AS1 (page, 1b) CR_TAB - AS1 (jmp, 1b); - } - default: - abort (); - } - }") - -(define_insn_and_split "lshrdi3_split" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0, rS, ro") - (match_operand:QI 2 "const_int_operand" "n, n, n")))] - "((INTVAL (operands[2]) >= 32) || (INTVAL (operands[2]) == 16))" - "#" - "&& ip2k_reorg_split_dimode" - [(const_int 0)] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_low_half (operands[0], SImode); - operands[5] = ip2k_get_high_half (operands[1], SImode); - - if (INTVAL (operands[2]) == 16) - { - operands[6] = ip2k_get_low_half (operands[1], SImode); - operands[7] = ip2k_get_high_half (operands[3], HImode); - operands[8] = ip2k_get_low_half (operands[3], HImode); - operands[9] = ip2k_get_high_half (operands[4], HImode); - operands[10] = ip2k_get_low_half (operands[4], HImode); - operands[11] = ip2k_get_high_half (operands[6], HImode); - operands[12] = ip2k_get_low_half (operands[5], HImode); - operands[13] = ip2k_get_high_half (operands[5], HImode); - emit_insn (gen_movhi (operands[10], operands[11])); - emit_insn (gen_movhi (operands[9], operands[12])); - emit_insn (gen_movhi (operands[8], operands[13])); - emit_insn (gen_movhi (operands[7], GEN_INT(0))); - } - else if (INTVAL (operands[2]) == 32) - { - emit_insn (gen_movsi (operands[4], operands[5])); - emit_insn (gen_movsi (operands[3], GEN_INT (0))); - } - else - { - operands[6] = GEN_INT (INTVAL (operands[2]) - 32); - emit_insn (gen_lshrsi3 (operands[4], operands[5], operands[6])); - emit_insn (gen_movsi (operands[3], GEN_INT (0))); - } - }") - -;; -;; Absolute value conversion instructions. -;; - -(define_insn "absqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=g") - (abs:QI (match_operand:QI 1 "nonimmediate_operand" "g")))] - "" - "mov\\tw,%1\;snb\\twreg,7\;sub\\tw,#0\;mov\\t%0,w") - -(define_insn "abssf2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=ro") - (abs:SF (match_operand:SF 1 "nonimmediate_operand" "0")))] - "" - "clrb %A0,7" - [(set_attr "clobberw" "no")]) - -;; -;; Negate (X = 0 - Y) instructions. -;; - -(define_insn_and_split "negqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0, rS, ro")))] - "" - "#" - "" - [(set (match_dup 0) - (not:QI (match_dup 1))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int 1)))] - "") - -(define_insn_and_split "neghi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0, rS, ro")))] - "" - "#" - "" - [(set (match_dup 0) - (not:HI (match_dup 1))) - (set (match_dup 0) - (plus:HI (match_dup 0) - (const_int 1)))] - "") - -(define_insn_and_split "negsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0, rS, ro")))] - "" - "#" - "" - [(set (match_dup 0) - (not:SI (match_dup 1))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int 1)))] - "") - -(define_insn_and_split "negdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0, rS, ro")))] - "" - "#" - "" - [(set (match_dup 0) - (not:DI (match_dup 1))) - (set (match_dup 0) - (plus:DI (match_dup 0) - (const_int 1)))] - "") - -;; -;; Bitwise not (one's complement) instructions. -;; - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=g,roR, rS") - (not:QI (match_operand:QI 1 "general_operand" "0, rS,roR")))] - "" - "@ - not\\t%0 - not\\tw,%1\;mov\\t%0,w - not\\tw,%1\;mov\\t%0,w" - [(set_attr "skip" "yes,no,no") - (set_attr "clobberw" "no,yes,yes")]) - -(define_insn_and_split "one_cmplhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (not:HI (match_operand:HI 1 "general_operand" "0, rS, ro")))] - "" - "#" - "(ip2k_reorg_split_himode)" - [(set (match_dup 3) - (not:QI (match_dup 4))) - (set (match_dup 5) - (not:QI (match_dup 6)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], QImode); - operands[4] = ip2k_get_high_half (operands[1], QImode); - operands[5] = ip2k_get_low_half (operands[0], QImode); - operands[6] = ip2k_get_low_half (operands[1], QImode); - }") - -(define_insn_and_split "one_cmplsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (not:SI (match_operand:SI 1 "general_operand" "0, rS, ro")))] - "" - "#" - "(ip2k_reorg_split_simode)" - [(set (match_dup 3) - (not:HI (match_dup 4))) - (set (match_dup 5) - (not:HI (match_dup 6)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], HImode); - operands[4] = ip2k_get_high_half (operands[1], HImode); - operands[5] = ip2k_get_low_half (operands[0], HImode); - operands[6] = ip2k_get_low_half (operands[1], HImode); - }") - -(define_insn_and_split "one_cmpldi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,&ro,&rS") - (not:DI (match_operand:DI 1 "general_operand" "0, rS, ro")))] - "" - "#" - "(ip2k_reorg_split_dimode)" - [(set (match_dup 3) - (not:SI (match_dup 4))) - (set (match_dup 5) - (not:SI (match_dup 6)))] - "{ - operands[3] = ip2k_get_high_half (operands[0], SImode); - operands[4] = ip2k_get_high_half (operands[1], SImode); - operands[5] = ip2k_get_low_half (operands[0], SImode); - operands[6] = ip2k_get_low_half (operands[1], SImode); - }") - -;; -;; Sign extension instructions. -;; - -(define_insn "*push_extendqihi2" - [(set (match_operand:HI 0 "push_operand" "=<,<") - (sign_extend:HI (match_operand:QI 1 "general_operand" "roR,n")))] - "" - "@ - push\\t%1%<\;push\\t#0%<\;snb\\t%1,7\;not\\t1(SP)%>%> - push\\t%L1\;push\\t%H1" - [(set_attr "clobberw" "no,no")]) - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS,ro,ro") - (sign_extend:HI (match_operand:QI 1 "general_operand" "roR,rS, n")))] - "" - "*{ - switch (which_alternative) - { - case 0: - case 1: - if (register_operand (operands[0], HImode) - && register_operand (operands[1], QImode) - && REGNO (operands[0]) == (REGNO (operands[1]) - 1)) - return AS1 (clr, %H0) CR_TAB - AS2 (snb, %1, 7) CR_TAB - AS1 (not, %H0); - else - return AS2 (mov, w, %1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (clr, %H0) CR_TAB - AS2 (snb, wreg, 7) CR_TAB - AS1 (not, %H0); - - case 2: - return AS2 (mov, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %H0, w); - default: - abort (); - } - }") - -(define_insn "*push_extendhisi2" - [(set (match_operand:SI 0 "push_operand" "=<,<,<") - (sign_extend:SI (match_operand:HI 1 "general_operand" "roS,n,s")))] - "" - "@ - push\\t%L1%<\;push\\t%H1%<\;clr\\twreg\;snb\\t%H1,7\;not\\twreg\;push\\twreg\;push\\twreg%>%> - push\\t%D1\;push\\t%C1\;push\\t%B1\;push\\t%A1 - push\\t%L1\;push\\t%H1\;push\\t#0\;push\\t#0" - [(set_attr "clobberw" "yes,no,no")]) - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro,rS,ro,ro") - (sign_extend:SI (match_operand:HI 1 "general_operand" "rS,ro, n, s")))] - "" - "@ - mov\\tw,%L1\;push\\t%H1%<\;pop\\t%C0%>\;mov\\t%D0,w\;clr\\twreg\;snb\\t%C0,7\;not\\twreg\;mov\\t%B0,w\;mov\\t%A0,w - mov\\tw,%L1\;push\\t%H1%<\;pop\\t%C0%>\;mov\\t%D0,w\;clr\\twreg\;snb\\t%C0,7\;not\\twreg\;mov\\t%B0,w\;mov\\t%A0,w - mov\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A1\;mov\\t%A0,w - mov\\tw,%L1\;push\\t%H1%<\;pop\\t%C0%>\;mov\\t%D0,w\;clr\\t%B0\;clr\\t%A0") - -(define_insn "*push_extendqisi2" - [(set (match_operand:SI 0 "push_operand" "=<,<") - (sign_extend:SI (match_operand:QI 1 "general_operand" "roR,n")))] - "" - "@ - push\\t%1%<\;clr\\twreg\;snb\\t%1,7\;not\\twreg\;push\\twreg\;push\\twreg\;push\\twreg%> - push\\t%D1\;push\\t%C1\;push\\t%B1\;push\\t%A1" - [(set_attr "clobberw" "yes,no")]) - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS,ro") - (sign_extend:SI (match_operand:QI 1 "general_operand" "rS,roR, n")))] - "" - "@ - mov\\tw,%1\;mov\\t%D0,w\;clr\\twreg\;snb\\t%1,7\;not\\twreg\;mov\\t%C0,w\;mov\\t%B0,w\;mov\\t%A0,w - mov\\tw,%1\;mov\\t%D0,w\;clr\\twreg\;snb\\t%1,7\;not\\twreg\;mov\\t%C0,w\;mov\\t%B0,w\;mov\\t%A0,w - mov\\tw,%D1\;mov\\t%D0,w\;mov\\tw,%C1\;mov\\t%C0,w\;mov\\tw,%B1\;mov\\t%B0,w\;mov\\tw,%A1\;mov\\t%A0,w") - -;; -;; Zero extension instructions. -;; - -(define_insn "*push_zero_extendqihi2" - [(set (match_operand:HI 0 "push_operand" "=<") - (zero_extend:HI (match_operand:QI 1 "general_operand" "roRi")))] - "" - "push\\t%1\;push\\t#0" - [(set_attr "clobberw" "no")]) - -(define_insn_and_split "zero_extendqihi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:HI (match_operand:QI 1 "general_operand" "rSi,roRi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], QImode); - operands[3] = ip2k_get_low_half (operands[0], QImode); - }") - -(define_insn "*push_zero_extendhisi2" - [(set (match_operand:SI 0 "push_operand" "=<") - (zero_extend:SI (match_operand:HI 1 "general_operand" "roSi")))] - "" - "push\\t%L1%<\;push\\t%H1%>\;push\\t#0\;push\\t#0") - -(define_insn_and_split "zero_extendhisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:SI (match_operand:HI 1 "general_operand" "rSi,roi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], HImode); - operands[3] = ip2k_get_low_half (operands[0], HImode); - }") - -(define_insn "*push_zero_extendqisi2" - [(set (match_operand:SI 0 "push_operand" "=<") - (zero_extend:SI (match_operand:QI 1 "general_operand" "roRi")))] - "" - "push\\t%1\;push\\t#0\;push\\t#0\;push\\t#0" - [(set_attr "clobberw" "no")]) - -(define_insn_and_split "zero_extendqisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:SI (match_operand:QI 1 "general_operand" "rSi,roRi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (zero_extend:HI (match_dup 1))) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], HImode); - operands[3] = ip2k_get_low_half (operands[0], HImode); - }") - -(define_insn "*push_zero_extendsidi2" - [(set (match_operand:DI 0 "push_operand" "=<") - (zero_extend:DI (match_operand:SI 1 "general_operand" "roSi")))] - "" - "push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%>%>%>\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0") - -(define_insn_and_split "zero_extendsidi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:DI (match_operand:SI 1 "general_operand" "rSi,roi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], SImode); - operands[3] = ip2k_get_low_half (operands[0], SImode); - }") - -(define_insn "*push_zero_extendhidi2" - [(set (match_operand:DI 0 "push_operand" "=<") - (zero_extend:DI (match_operand:HI 1 "general_operand" "roSi")))] - "" - "push\\t%L1%<\;push\\t%H1%>\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0" - [(set_attr "clobberw" "no")]) - -(define_insn_and_split "zero_extendhidi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:DI (match_operand:HI 1 "general_operand" "rSi,roi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (zero_extend:SI (match_dup 1))) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], SImode); - operands[3] = ip2k_get_low_half (operands[0], SImode); - }") - -(define_insn "*push_zero_extendqidi2" - [(set (match_operand:DI 0 "push_operand" "=<") - (zero_extend:DI (match_operand:QI 1 "general_operand" "roRi")))] - "" - "push\\t%1\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0\;push\\t#0" - [(set_attr "clobberw" "no")]) - -(define_insn_and_split "zero_extendqidi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=ro, rS") - (zero_extend:DI (match_operand:QI 1 "general_operand" "rSi,roRi")))] - "" - "#" - "ip2k_reorg_completed" - [(set (match_dup 3) (zero_extend:SI (match_dup 1))) - (set (match_dup 2) (const_int 0))] - "{ - operands[2] = ip2k_get_high_half (operands[0], SImode); - operands[3] = ip2k_get_low_half (operands[0], SImode); - }") - -;; -;; Truncation instructions. -;; - -(define_insn "truncsihi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS, ro") - (truncate:HI (match_operand:SI 1 "general_operand" "roi,rSi")))] - "" - "@ - mov\\tw,%D1\;push\\t%C1%<\;pop\\t%H0%>\;mov\\t%L0,w - mov\\tw,%D1\;push\\t%C1%<\;pop\\t%H0%>\;mov\\t%L0,w") - -(define_insn "truncsiqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rS, ro") - (truncate:QI (match_operand:SI 1 "general_operand" "roi,rSi")))] - "" - "@ - mov\\tw,%D1\;mov\\t%0,w - mov\\tw,%D1\;mov\\t%0,w") - -(define_insn "trunchiqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rS, ro") - (truncate:QI (match_operand:HI 1 "general_operand" "roi,rSi")))] - "" - "@ - mov\\tw,%L1\;mov\\t%0,w - mov\\tw,%L1\;mov\\t%0,w") - -;; -;; Compare with zero (test) instructions. -;; -;; As we don't have a particularly good set of condition codes we simply -;; tagging our comparison operands for use later within our "compare -;; and branch" instructions. -;; - -(define_insn "tstqi" - [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" "roR"))] - "" - "* return ip2k_set_compare (operands[0], const0_rtx);") - -(define_insn "tsthi" - [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" "roS"))] - "" - "* return ip2k_set_compare (operands[0], const0_rtx);") - -(define_insn "tstsi" - [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "roS"))] - "" - "* return ip2k_set_compare (operands[0], const0_rtx);") - -(define_insn "tstdi" - [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "roS"))] - "" - "* return ip2k_set_compare (operands[0], const0_rtx);") - -;; -;; General value comparison instructions. -;; -;; As we don't have a particularly good set of condition codes we simply -;; tagging our comparison operands for use later within our "compare -;; and branch" instructions. -;; - -(define_insn "cmpqi" - [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_operand" "roR, rS") - (match_operand:QI 1 "general_operand" "rSn,roRn")))] - "" - "* return ip2k_set_compare (operands[0], operands[1]);") - -(define_insn "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "nonimmediate_operand" "ro, rS") - (match_operand:HI 1 "general_operand" "rSn,ron")))] - "" - "* return ip2k_set_compare (operands[0], operands[1]);") - -(define_insn "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "nonimmediate_operand" "ro, rS") - (match_operand:SI 1 "general_operand" "rSn,ron")))] - "" - "* return ip2k_set_compare (operands[0], operands[1]);") - -(define_insn "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "nonimmediate_operand" "ro, rS") - (match_operand:DI 1 "general_operand" "rSn,ron")))] - "" - "* return ip2k_set_compare (operands[0], operands[1]);") - -;; -;; Conditional jump instructions. -;; - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - - -(define_expand "ble" - [(set (pc) - (if_then_else (le (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "") - - -;; Implementation of conditional jumps. -;; -;; The assumption is that a previous test or compare instruction will have -;; provided the arguments to be compared to form cc0 and then we perform -;; a compare and branch operation here. -;; -(define_insn "*unsigned_cmp_branch" - [(set (pc) - (if_then_else (match_operator 1 "ip2k_unsigned_comparison_operator" - [(cc0) - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return ip2k_gen_unsigned_comp_branch (insn, GET_CODE (operands[1]), - operands[0]);") - -;; Signed branches use Z, N or synthesized V. -;; result is generated as 0 (LT), 1 (EQ), 2 (GT) -;; -(define_insn "*signed_cmp_branch" - [(set (pc) - (if_then_else (match_operator 1 "ip2k_signed_comparison_operator" - [(cc0) - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* return ip2k_gen_signed_comp_branch (insn, GET_CODE (operands[1]), - operands[0]);") - -;; Reverse branch - reverse our comparison condition so that we can -;; branch in the opposite sense. -;; -(define_insn_and_split "*rvbranch" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" [(cc0) - (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "#" - "reload_completed" - [(set (pc) - (if_then_else (match_dup 2) - (label_ref (match_operand 0 "" "")) - (pc)))] - "{ - operands[2] = gen_rtx (reverse_condition (GET_CODE (operands[1])), - GET_MODE (operands[1]), - cc0_rtx, const0_rtx); - }") - -;; This is a bit test and jump sequence. -;; -(define_insn "*bit_cmpqi_branch" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(zero_extract - (match_operand:QI 1 "nonimmediate_operand" "roR") - (const_int 1) - (match_operand 2 "immediate_operand" "i")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "(GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)" - "*{ - if (GET_CODE (operands[0]) == EQ) - OUT_AS2 (sb, %1, %b2); - else - OUT_AS2 (snb, %1, %b2); - return AS1 (page, %3) CR_TAB - AS1 (jmp, %3); - }" - [(set_attr "clobberw" "no")]) - -;; This is a bit test and jump sequence but for 16-bit operands. It's pretty -;; certain that there must be a way to do this using a zero_extract operation, -;; but this didn't seem to want to work so we use a bitwise and instead. This -;; is exactly as efficient but the combiner handles this OK - the implementation -;; here isn't quite as nice though. -;; -(define_insn "*bit_cmphi_branch" - [(set - (pc) - (if_then_else - (match_operator 0 "comparison_operator" - [(and:HI (match_operand:HI 1 "nonimmediate_operand" "roS") - (match_operand 2 "const_int_operand" "n")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "((GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE) - && find_one_set_bit_p (INTVAL (operands[2])) != -1)" - "*{ - int bp = find_one_set_bit_p (INTVAL (operands[2])); - if (INTVAL (operands[2]) >= 8) - operands[4] = GEN_INT (bp - 8); - else - operands[4] = GEN_INT (bp); - - if (GET_CODE (operands[0]) == EQ) - { - if (INTVAL (operands[2]) >= 8) - OUT_AS2 (sb, %H1, %b4); - else - OUT_AS2 (sb, %L1, %b4); - } - else - { - if (INTVAL (operands[2]) >= 8) - OUT_AS2 (snb, %H1, %b4); - else - OUT_AS2 (snb, %L1, %b4); - } - return AS1 (page, %3) CR_TAB - AS1 (jmp, %3); - }" - [(set_attr "clobberw" "no")]) - -;; Add two operands, compare with a third and branch if equal or not-equal. -;; -(define_insn "*add_and_comp_branch" - [(set - (pc) - (if_then_else - (match_operator 0 "comparison_operator" - [(plus:HI - (match_operand:HI 1 "nonimmediate_operand" "ro, rS, rS") - (match_operand:HI 2 "general_operand" "rSn,ron,rSn")) - (match_operand:HI 3 "general_operand" "rSn,rSn,ron")]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE)" - "*{ - OUT_AS2 (mov, w, %L2); - OUT_AS2 (add, w, %L1); - OUT_AS2 (cse, w, %L3); - if (GET_CODE (operands[0]) == EQ) - { - OUT_AS1 (page, 1f); - OUT_AS1 (jmp, 1f); - } - else - { - OUT_AS1 (page, %4); - OUT_AS1 (jmp, %4); - } - OUT_AS2 (mov, w, %H2); - OUT_AS2 (addc, w, %H1); - if (GET_CODE (operands[0]) == EQ) - OUT_AS2 (csne, w, %H3); - else - OUT_AS2 (cse, w, %H3); - OUT_AS1 (page, %4); - OUT_AS1 (jmp, %4); - return AS1 (1:, ); - }") - -;; Unconditional jump -;; -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "page\\t%0\;jmp\\t%0" - [(set_attr "clobberw" "no")]) - -;; Indirect jump -;; -(define_insn "indirect_jump" - [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "ro"))] - "" - "page\\t1f\;call\\t1f\;1:mov\\tw,%H0\;mov\\tcallh,w\;mov\\tw,%L0\;mov\\tcalll,w\;ret") - -;; -;; Function call instructions. -;; - -(define_expand "call" - [(call (match_operand 0 "" "") - (match_operand:HI 1 "" ""))] - "" - "") - -(define_insn "*call" - [(call (mem:HI (match_operand:HI 0 "general_operand" "i,roS")) - (match_operand:HI 1 "" ""))] - "" - "@ - page\\t%b0\;call\\t%b0 - push\\t%L0%<\;push\\t%H0%>\;page\\t__indcall\;call\\t__indcall") - -(define_expand "call_pop" - [(parallel [(call (match_operand 0 "" "") - (match_operand:HI 1 "" "")) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 3 "immediate_operand" "")))])] - "" - "") - -(define_insn "*call_pop" - [(call (mem:HI (match_operand:HI 0 "general_operand" "i,roS")) - (match_operand:HI 1 "" "")) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 2 "immediate_operand" "")))] - "" - "@ - page\\t%b0\;call\\t%b0 - push\\t%L0%<\;push\\t%H0%>\;page\\t__indcall\;call\\t__indcall") - -;; Undo any splitting of operands that lead to redundant movhi3 instructions. -;; -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (parallel [(call (mem:HI (match_dup 0)) - (match_operand:HI 2 "" "")) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 3 "immediate_operand" "")))])] - "" - [(parallel [(call (mem:HI (match_dup 1)) - (match_dup 2)) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_dup 3)))])] - "") - -(define_expand "call_value" - [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand:HI 2 "" "")))] - "" - "") - -(define_insn "*call_value" - [(set (match_operand 0 "" "") - (call (mem:HI (match_operand:HI 1 "general_operand" "i,roS")) - (match_operand:HI 2 "" "")))] - "" - "@ - page\\t%b1\;call\\t%b1 - push\\t%L1%<\;push\\t%H1%>\;page\\t__indcall\;call\\t__indcall") - -(define_expand "call_value_pop" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand:HI 2 "" ""))) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 4 "immediate_operand" "")))])] - "" - "") - -(define_insn "*call_value_pop" - [(set (match_operand 0 "" "") - (call (mem:HI (match_operand:HI 1 "general_operand" "i,roS")) - (match_operand:HI 2 "" ""))) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 3 "immediate_operand" "")))] - "" - "@ - page\\t%b1\;call\\t%b1 - push\\t%L1%<\;push\\t%H1%>\;page\\t__indcall\;call\\t__indcall") - -;; Undo any splitting of operands that lead to redundant movhi3 instructions. -;; -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (parallel [(set (match_operand 2 "" "") - (call (mem:HI (match_dup 0)) - (match_operand:HI 3 "" ""))) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_operand:HI 4 "immediate_operand" "")))])] - "" - [(parallel [(set (match_dup 2) - (call (mem:HI (match_dup 1)) - (match_dup 3))) - (set (reg:HI 6) - (plus:HI (reg:HI 6) - (match_dup 4)))])] - "") - -;; Nop instruction. -;; -;; We don't really want nops to appear in our code so just insert an comment. -;; -(define_insn "nop" - [(const_int 0)] - "" - "; nop") - - -;; SEQ instruction -;; -(define_insn "seq" - [(set (match_operand:QI 0 "register_operand" "=r") - (eq:QI (cc0) (const_int 0)))] - "" - "* return ip2k_gen_sCOND (insn, EQ, operands[0]);") - -;; Tweak SEQ if we can adjust the output operand. Note that we have to do -;; this via a peephole because we need to ensure that any reloads have taken -;; place before we try to do this. If there's a reload in order to get our -;; actual result operand then this peephole won't match. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "") - (eq:QI (cc0) (const_int 0))) - (set (reg:QI 10) - (match_dup 0)) - (set (match_operand:QI 1 "nonimmediate_operand" "") - (reg:QI 10))] - "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))" - "* return ip2k_gen_sCOND (insn, EQ, operands[1]);") - -;; Another peephole match handles the same merge as above but for cases where -;; we're emulating memory accesses via IP and an offset. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "") - (eq:QI (cc0) (const_int 0))) - (set (reg:QI 10) - (match_dup 0)) - (set (mem:QI (plus:HI (reg:HI 4) - (match_operand:QI 1 "const_int_operand" ""))) - (reg:QI 10))] - "(find_regno_note (insn, REG_DEAD, REGNO (operands[0])) - && (INTVAL (operands[1]) < 0x100))" - "*{ - if (INTVAL (operands[1]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - } - ip2k_gen_sCOND (insn, EQ, - gen_rtx_MEM (QImode, gen_rtx_REG (HImode, REG_IP))); - if (find_regno_note (insn, REG_DEAD, REG_IP)) - { - if (INTVAL (operands[1]) == 1) - OUT_AS1 (dec, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (sub, ipl, w); - } - } - return \"\"; - }") - -;; SNE instruction -;; -(define_insn "sne" - [(set (match_operand:QI 0 "register_operand" "=r") - (ne:QI (cc0) (const_int 0)))] - "" - "* return ip2k_gen_sCOND (insn, NE, operands[0]);") - -;; Tweak SNE if we can adjust the output operand. Note that we have to do -;; this via a peephole because we need to ensure that any reloads have taken -;; place before we try to do this. If there's a reload in order to get our -;; actual result operand then this peephole won't match. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "") - (ne:QI (cc0) (const_int 0))) - (set (reg:QI 10) - (match_dup 0)) - (set (match_operand:QI 1 "nonimmediate_operand" "") - (reg:QI 10))] - "find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0]))" - "* return ip2k_gen_sCOND (insn, NE, operands[1]);") - -;; Another peephole match handles the same merge as above but for cases where -;; we're emulating memory accesses via IP and an offset. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "") - (ne:QI (cc0) (const_int 0))) - (set (reg:QI 10) - (match_dup 0)) - (set (mem:QI (plus:HI (reg:HI 4) - (match_operand:QI 1 "const_int_operand" ""))) - (reg:QI 10))] - "(find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0])) - && (INTVAL (operands[1]) < 0x100))" - "*{ - if (INTVAL (operands[1]) == 1) - OUT_AS1 (inc, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, ipl, w); - } - ip2k_gen_sCOND (insn, NE, - gen_rtx_MEM (QImode, gen_rtx_REG (HImode, REG_IP))); - if (find_regno_note (insn, REG_DEAD, REG_IP)) - { - if (INTVAL (operands[1]) == 1) - OUT_AS1 (dec, ipl); - else - { - OUT_AS2 (mov, w, %1); - OUT_AS2 (sub, ipl, w); - } - } - return \"\"; - }") - - - -;; Case Dispatch Table Support. -;; -;; Called with 5 arguments: -;; -;; 0. case index -;; 1. lower bound (const_int) -;; 2. range (const_int) -;; 3. label before dispatch table -;; 4. out-of-bounds label -;; -;; With the IP2k we actually really want to do a caseqi but that -;; doesn't exist so we cheat and make it look (to the core of gcc) -;; like we're going to do the SImode stuff but then truncate it -;; away when it's no longer looking :-) -;; -(define_expand "casesi" - [(set (match_dup 5) - (truncate:QI (match_operand:SI 0 "general_operand" "g"))) - (set (match_dup 5) - (minus:QI (match_dup 5) - (match_operand 1 "const_int_operand" "n"))) - (set (cc0) - (compare (match_dup 5) - (match_operand 2 "const_int_operand" "n"))) - (set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (parallel [(set (pc) - (plus:HI (pc) - (zero_extend:HI (match_dup 5)))) - (use (label_ref (match_operand 3 "" ""))) - (use (match_dup 2))])] - "" - "{ - operands[5] = gen_reg_rtx (QImode); - }") - -;; There are TWO instructions per dispatch entry (page & jump), so we -;; multiply by two even though our RTL only indicates a simple addition. -;; Subsequent linker relaxation may well restore this back to what the -;; RTL says though! -;; -;; Note that we handle tables with 128 or more entries differently! -;; -(define_insn "*casedispatch" - [(set (pc) - (plus:HI (pc) (zero_extend:HI - (match_operand:QI 2 "nonimmediate_operand" "roR,roR")))) - (use (label_ref (match_operand 0 "" ""))) - (use (match_operand 1 "const_int_operand" "K, n"))] - "" - "@ - mov\\tw,%2\;add\\tw,wreg\;add\\tpcl,w - mov\\tw,%2\;push\\t%0%<\;push\\t#0%<\;add\\tw,wreg\;snc\;inc\\t1(SP)\;add\\t2(SP),w\;snc\;inc\\t1(SP)\;page\\t__indcall\;jmp\\t__indcall%>%>") - -;; Handle cleaning up the switch statement stuff. We can eliminate some -;; register moves in some cases. Note that our pattern is slightly different -;; to the casesi pattern because our minus has become a plus! -;; -;; Note that as of 07-FEB-2002 we must have this pattern as it is because -;; linker relaxation will not work any other way. -;; -(define_peephole - [(set (reg:QI 10) - (plus:QI (match_operand 5 "nonimmediate_operand" "rS,rS,rS,rS") - (match_operand 1 "const_int_operand" "M, n, M, n"))) - (set (match_operand:QI 0 "register_operand" "+r, r, r, r") - (reg:QI 10)) - (set (cc0) - (compare (match_dup 0) - (match_operand 2 "const_int_operand" "K, K, n, n"))) - (set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (parallel [(set (pc) - (plus:HI (pc) - (zero_extend:HI (match_dup 0)))) - (use (label_ref (match_operand 3 "" ""))) - (use (match_dup 2))])] - "(INTVAL (operands[1]) != 0 - && find_regno_note (insn, REG_DEAD, REGNO (operands[0])))" - "*{ - switch (which_alternative) - { - case 0: - case 2: - OUT_AS2 (dec, w, %5); - break; - - case 1: - case 3: - OUT_AS2 (mov, w, %1); - OUT_AS2 (add, w, %5); - break; - default: - abort (); - } - - OUT_AS2 (cmp, w, %2); - OUT_AS1 (sc, ); - OUT_AS1 (page, %4); - OUT_AS1 (jmp, %4); - - switch (which_alternative) - { - case 0: - case 1: - OUT_AS2 (add, w, WREG); - OUT_AS2 (add, pcl, w); - return \"\"; - - case 2: - case 3: - OUT_AS1 (push, %0%<); - OUT_AS1 (push, #0%<); - OUT_AS2 (add, w, WREG); - OUT_AS1 (snc, ); - OUT_AS1 (inc, 1(SP)); - OUT_AS2 (add, 2(SP), w); - OUT_AS1 (snc, ); - OUT_AS1 (inc, 1(SP)); - OUT_AS1 (page, __indcall); - OUT_AS1 (jmp, __indcall%>%>); - return \"\"; - default: - abort (); - } - }") - -(define_peephole - [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_operand" "rS,rS") - (match_operand 1 "const_int_operand" "K, n"))) - (set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc))) - (parallel [(set (pc) - (plus:HI (pc) - (zero_extend:HI (match_dup 0)))) - (use (label_ref (match_operand 3 "" ""))) - (use (match_dup 1))])] - "" - "@ - mov\\tw,%0\;cmp\\tw,%1\;sc\;page\\t%2\;jmp\\t%2\;add\\tw,wreg\;add\\tpcl,w - mov\\tw,%0\;cmp\\tw,%1\;sc\;page\\t%2\;jmp\\t%2\;push\\t%0%<\;push\\t#0%<\;add\\tw,wreg\;snc\;inc\\t1(SP)\;add\\t2(SP),w\;snc\;inc\\t1(SP)\;page\\t__indcall\;jmp\\t__indcall%>%>") - -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+roR") - (plus:HI (match_dup 0) - (const_int -1))) - (set (cc0) - (compare (match_dup 0) - (match_operand 3 "const_int_operand" "n"))) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "((GET_CODE (operands[2]) == EQ || GET_CODE (operands[2]) == NE) - && ((INTVAL (operands[3]) == -1) || (INTVAL (operands[3]) == 65535)))" - "*{ - OUT_AS2 (mov, w, #255); - OUT_AS2 (add, %L0, w); - if ((GET_CODE (operands[0]) == REG) - && ((REGNO (operands[0]) == REG_DP) - || (REGNO (operands[0]) == REG_IP) - || (REGNO (operands[0]) == REG_SP))) - { - OUT_AS2 (add, %H0, w); - } - else - { - OUT_AS2 (addc, %H0, w); - } - if (GET_CODE (operands[2]) == EQ) - OUT_AS1 (sc, ); - else - OUT_AS1 (snc, ); - return AS1 (page, %1) CR_TAB - AS1 (jmp, %1); - }") - -(define_peephole - [(set (match_operand:QI 0 "nonimmediate_operand" "+rS") - (plus:QI (match_dup 0) - (const_int -1))) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "(GET_CODE (operands[2]) == EQ || GET_CODE (operands[2]) == NE)" - "*{ - if (GET_CODE (operands[2]) == EQ) - OUT_AS1 (decsnz, %0); - else - OUT_AS1 (decsz, %0); - return AS1 (page, %1) CR_TAB - AS1 (jmp, %1); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 1 "nonimmediate_operand" "rS")) - (set (match_operand:QI 0 "nonimmediate_operand" "=rS") - (reg:QI 10)) - (set (cc0) - (match_operand:QI 2 "nonimmediate_operand" "rS")) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "((GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE) - && (rtx_equal_p (operands[0], operands[2]) - || rtx_equal_p (operands[1], operands[2])))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (mov, %0, w); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 1 "nonimmediate_operand" "uS")) - (set (match_operand:QI 0 "nonimmediate_operand" "+uS") - (reg:QI 10)) - (set (cc0) - (match_operand:SI 2 "nonimmediate_operand" "uS")) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "((GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE) - && (rtx_equal_p (operands[0], - ip2k_get_high_half (ip2k_get_high_half (operands[2], - HImode), QImode)) - || rtx_equal_p (operands[1], - ip2k_get_high_half (ip2k_get_high_half (operands[2], - HImode), - QImode))))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (mov, %0, w); - OUT_AS2 (or, w, %B2); - OUT_AS2 (or, w, %C2); - OUT_AS2 (or, w, %D2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 1 "nonimmediate_operand" "uS")) - (set (match_operand:QI 0 "nonimmediate_operand" "+uS") - (reg:QI 10)) - (set (cc0) - (match_operand:HI 2 "nonimmediate_operand" "uS")) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "((GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE) - && (rtx_equal_p (operands[0], ip2k_get_high_half (operands[2], QImode)) - || rtx_equal_p (operands[1], ip2k_get_high_half (operands[2], QImode)) - || rtx_equal_p (operands[0], ip2k_get_low_half (operands[2], QImode)) - || rtx_equal_p (operands[1], ip2k_get_low_half (operands[2],QImode))))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (mov, %0, w); - if (rtx_equal_p (operands[0], ip2k_get_high_half (operands[2], QImode)) - || rtx_equal_p (operands[1], ip2k_get_high_half (operands[2], QImode))) - OUT_AS2 (or, w, %L2); - else - OUT_AS2 (or, w, %H2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+uo") - (match_operand:HI 1 "nonimmediate_operand" "uo")) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "(GET_CODE (operands[2]) == EQ || GET_CODE (operands[2]) == NE)" - "*{ - OUT_AS2 (mov, w, %H1); - OUT_AS1 (push, %L1%<); - OUT_AS1 (pop, %L0%>); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (or, w, %L0); - if (GET_CODE (operands[2]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %3) CR_TAB - AS1 (jmp, %3); - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+uo") - (match_operand:HI 1 "nonimmediate_operand" "uo")) - (set (cc0) - (match_dup 1)) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "(GET_CODE (operands[2]) == EQ || GET_CODE (operands[2]) == NE)" - "*{ - OUT_AS2 (mov, w, %H1); - OUT_AS1 (push, %L1%<); - OUT_AS1 (pop, %L0%>); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (or, w, %L0); - if (GET_CODE (operands[2]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %3) CR_TAB - AS1 (jmp, %3); - }") - -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+f,bqdo") - (mem:HI (reg:HI 4))) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "(GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (push, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, ipl, w); - OUT_AS1 (pop, iph); - OUT_AS2 (or, w, iph); - if (GET_CODE (operands[1]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %2) CR_TAB - AS1 (jmp, %2); - - case 1: - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %H0, w); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %L0, w); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - OUT_AS2 (or, w, %H0); - if (GET_CODE (operands[1]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %2) CR_TAB - AS1 (jmp, %2); - default: - abort (); - } - }") - -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+f,bqdo") - (mem:HI (reg:HI 4))) - (set (cc0) - (mem:HI (reg:HI 4))) - (set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "(GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)" - "*{ - switch (which_alternative) - { - case 0: - OUT_AS1 (push, (IP)); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, ipl, w); - OUT_AS1 (pop, iph); - OUT_AS2 (or, w, iph); - if (GET_CODE (operands[1]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %2) CR_TAB - AS1 (jmp, %2); - - case 1: - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %H0, w); - OUT_AS1 (inc, ipl); - OUT_AS2 (mov, w, (IP)); - OUT_AS2 (mov, %L0, w); - if (!find_regno_note (insn, REG_DEAD, REG_IP)) - OUT_AS1 (dec, ipl); - OUT_AS2 (or, w, %H0); - if (GET_CODE (operands[1]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %2) CR_TAB - AS1 (jmp, %2); - default: - abort (); - } - }") - -;; Handle move-twice and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(parallel [(set (match_operand:HI 0 "ip2k_gen_operand" "=uS") - (match_operand:HI 1 "ip2k_gen_operand" "uS")) - (set (match_operand:HI 2 "ip2k_gen_operand" "=uS") - (match_dup 1))]) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE)" - "*{ - if ((REG_P (operands[0]) - && !(ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 2) - && ip2k_xexp_not_uses_reg_p (operands[2], - REGNO (operands[0]), 2))) - || (REG_P (operands[2]) - && !(ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 2) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 2)))) - { - OUT_AS2 (mov, w, %L1); - OUT_AS1 (push, %H1%<); - OUT_AS1 (push, %H1%<); - OUT_AS1 (pop, %H0%>); - OUT_AS2 (mov, %L0, w); - OUT_AS1 (pop, %H2%>); - OUT_AS2 (mov, %L2, w); - OUT_AS2 (or, w, %H2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - } - else - { - OUT_AS2 (mov, w, %L1); - OUT_AS2 (mov, %L0, w); - OUT_AS2 (mov, %L2, w); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (mov, %H2, w); - OUT_AS2 (or, w, %L2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - } - }") - -(define_peephole - [(parallel [(set (match_operand:HI 0 "ip2k_gen_operand" "=uS") - (match_operand:HI 1 "ip2k_gen_operand" "uS")) - (set (match_operand:HI 2 "ip2k_gen_operand" "=uS") - (match_dup 1))]) - (set (cc0) - (match_dup 2)) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE)" - "*{ - if ((REG_P (operands[0]) - && !(ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 2) - && ip2k_xexp_not_uses_reg_p (operands[2], - REGNO (operands[0]), 2))) - || (REG_P (operands[2]) - && !(ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 2) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 2)))) - { - OUT_AS2 (mov, w, %L1); - OUT_AS1 (push, %H1%<); - OUT_AS1 (push, %H1%<); - OUT_AS1 (pop, %H0%>); - OUT_AS2 (mov, %L0, w); - OUT_AS1 (pop, %H2%>); - OUT_AS2 (mov, %L2, w); - OUT_AS2 (or, w, %H2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - } - else - { - OUT_AS2 (mov, w, %L1); - OUT_AS2 (mov, %L0, w); - OUT_AS2 (mov, %L2, w); - OUT_AS2 (mov, w, %H1); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (mov, %H2, w); - OUT_AS2 (or, w, %L2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - } - }") - -;; Handle move and compare-with-zero operations - we can reuse w across -;; the two operations. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+uo") - (match_operand:HI 1 "nonimmediate_operand" "uo")) - (set (cc0) - (match_operand:SI 2 "nonimmediate_operand" "uo")) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "((GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE) - && (rtx_equal_p (operands[0], ip2k_get_high_half (operands[2], HImode)) - || rtx_equal_p (operands[1], - ip2k_get_high_half (operands[2], HImode))))" - "*{ - OUT_AS2 (mov, w, %H1); - OUT_AS1 (push, %L1%<); - OUT_AS1 (pop, %L0%>); - OUT_AS2 (mov, %H0, w); - OUT_AS2 (or, w, %B0); - OUT_AS2 (or, w, %C0); - OUT_AS2 (or, w, %D0); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle bitwise-and and compare-with-zero operations on bytes. -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 2 "general_operand" " g")) - (set (reg:QI 10) - (and:QI (match_operand:QI 1 "general_operand" "g") - (reg:QI 10))) - (set (match_operand:QI 0 "register_operand" "+r") - (reg:QI 10)) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0])) - && (GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (and, w, %2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Handle bitwise-xor and compare-with-zero operations on bytes. -;; -(define_peephole - [(set (match_operand:QI 0 "register_operand" "+r") - (xor:QI (match_operand:QI 1 "general_operand" "g") - (match_operand:QI 2 "general_operand" "g"))) - (set (cc0) - (match_dup 0)) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0])) - && (GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE))" - "*{ - OUT_AS2 (mov, w, %1); - OUT_AS2 (xor, w, %2); - if (GET_CODE (operands[3]) == EQ) - OUT_AS1 (snz, ); - else - OUT_AS1 (sz, ); - return AS1 (page, %4) CR_TAB - AS1 (jmp, %4); - }") - -;; Cope with reload's vagaries. -;; - -(define_insn "*pushqi_reload_popqi" - [(set (match_operand:QI 0 "ip2k_nonsp_reg_operand" "=u, u") - (match_operand:QI 1 "ip2k_short_operand" "S, S")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "i,ro")) - (set (match_operand:QI 3 "ip2k_short_operand" "=S, S") - (match_dup 0))] - "" - "@ - push\\t%1%<\;loadh\\t%x2\;loadl\\t%x2\;pop\\t%3%> - push\\t%1%<\;mov\\tw,%L2\;push\\t%H2\;pop\\tdph\;mov\\tdpl,w\;pop\\t%3%>" -) - -(define_peephole2 - [(set (match_operand:QI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:QI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "")) - (set (match_operand:QI 3 "ip2k_short_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_himode - && peep2_reg_dead_p (3, operands[0]) - && ip2k_address_uses_reg_p (operands[1], REG_DP) - && ip2k_address_uses_reg_p (operands[3], REG_DP) - && !(ip2k_address_uses_reg_p (operands[2], REG_SP) - && (GET_CODE (XEXP (operands[2], 0)) == PLUS) - && (INTVAL (XEXP (XEXP (operands[2], 0), 1)) >= 126)) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (reg:HI 12) - (match_dup 2)) - (set (match_dup 3) - (match_dup 0))])] - "") - -(define_insn "*pushhi_reload_pophi" - [(set (match_operand:HI 0 "ip2k_nonsp_reg_operand" "=u, u") - (match_operand:HI 1 "ip2k_short_operand" "S, S")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "i,ro")) - (set (match_operand:HI 3 "ip2k_short_operand" "=S, S") - (match_dup 0))] - "" - "@ - push\\t%L1%<\;push\\t%H1%<\;loadh\\t%x2\;loadl\\t%x2\;pop\\t%H3%>\;pop\\t%L3%> - push\\t%L1%<\;push\\t%H1%<\;mov\\tw,%L2\;push\\t%H2\;pop\\tdph\;mov\\tdpl,w\;pop\\t%H3%>\;pop\\t%L3%>" -) - -(define_peephole2 - [(set (match_operand:HI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:HI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "")) - (set (match_operand:HI 3 "ip2k_short_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_simode - && peep2_reg_dead_p (3, operands[0]) - && ip2k_address_uses_reg_p (operands[1], REG_DP) - && ip2k_address_uses_reg_p (operands[3], REG_DP) - && !(ip2k_address_uses_reg_p (operands[2], REG_SP) - && (GET_CODE (XEXP (operands[2], 0)) == PLUS) - && (INTVAL (XEXP (XEXP (operands[2], 0), 1)) >= 125)) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (reg:HI 12) - (match_dup 2)) - (set (match_dup 3) - (match_dup 0))])] - "") - -(define_insn "*pushsi_reload_popsi" - [(set (match_operand:SI 0 "ip2k_nonsp_reg_operand" "=u, u") - (match_operand:SI 1 "ip2k_short_operand" "S, S")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "i,ro")) - (set (match_operand:SI 3 "ip2k_short_operand" "=S, S") - (match_dup 0))] - "" - "@ - push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%<\;loadh\\t%x2\;loadl\\t%x2\;pop\\t%A3%>\;pop\\t%B3%>\;pop\\t%C3%>\;pop\\t%D3%> - push\\t%D1%<\;push\\t%C1%<\;push\\t%B1%<\;push\\t%A1%<\;mov\\tw,%L2\;push\\t%H2\;pop\\tdph\;mov\\tdpl,w\;pop\\t%A3%>\;pop\\t%B3%>\;pop\\t%C3%>\;pop\\t%D3%>" -) - -(define_peephole2 - [(set (match_operand:SI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:SI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "")) - (set (match_operand:SI 3 "ip2k_short_operand" "") - (match_dup 0))] - "(ip2k_reorg_split_dimode - && peep2_reg_dead_p (3, operands[0]) - && ip2k_address_uses_reg_p (operands[1], REG_DP) - && ip2k_address_uses_reg_p (operands[3], REG_DP) - && ! (ip2k_address_uses_reg_p (operands[2], REG_SP) - && (GET_CODE (XEXP (operands[2], 0)) == PLUS) - && (INTVAL (XEXP (XEXP (operands[2], 0), 1)) >= 123)))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (reg:HI 12) - (match_dup 2)) - (set (match_dup 3) - (match_dup 0))])] - "") - -(define_insn "*pushdi_reload_popdi" - [(set (match_operand:DI 0 "ip2k_nonsp_reg_operand" "=u, u") - (match_operand:DI 1 "ip2k_short_operand" "S, S")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "i,ro")) - (set (match_operand:DI 3 "ip2k_short_operand" "=S, S") - (match_dup 0))] - "" - "@ - push\\t%S1%<\;push\\t%T1%<\;push\\t%U1%<\;push\\t%V1%<\;push\\t%W1%<\;push\\t%X1%<\;push\\t%Y1%<\;push\\t%Z1%<\;loadh\\t%x2\;loadl\\t%x2\;pop\\t%Z3%>\;pop\\t%Y3%>\;pop\\t%X3%>\;pop\\t%W3%>\;pop\\t%V3%>\;pop\\t%U3%>\;pop\\t%T3%>\;pop\\t%S3%> - push\\t%S1%<\;push\\t%T1%<\;push\\t%U1%<\;push\\t%V1%<\;push\\t%W1%<\;push\\t%X1%<\;push\\t%Y1%<\;push\\t%Z1%<\;mov\\tw,%L2\;push\\t%H2\;pop\\tdph\;mov\\tdpl,w\;pop\\t%Z3%>\;pop\\t%Y3%>\;pop\\t%X3%>\;pop\\t%W3%>\;pop\\t%V3%>\;pop\\t%U3%>\;pop\\t%T3%>\;pop\\t%S3%>" -) - -(define_peephole2 - [(set (match_operand:DI 0 "ip2k_nonsp_reg_operand" "") - (match_operand:DI 1 "ip2k_short_operand" "")) - (set (reg:HI 12) - (match_operand:HI 2 "general_operand" "")) - (set (match_operand:DI 3 "ip2k_short_operand" "") - (match_dup 0))] - "((ip2k_reorg_in_progress || ip2k_reorg_completed) - && peep2_reg_dead_p (3, operands[0]) - && ip2k_address_uses_reg_p (operands[1], REG_DP) - && ip2k_address_uses_reg_p (operands[3], REG_DP) - && ! (ip2k_address_uses_reg_p (operands[2], REG_SP) - && (GET_CODE (XEXP (operands[2], 0)) == PLUS) - && (INTVAL (XEXP (XEXP (operands[2], 0), 1)) >= 119)))" - [(parallel [(set (match_dup 0) - (match_dup 1)) - (set (reg:HI 12) - (match_dup 2)) - (set (match_dup 3) - (match_dup 0))])] - "") - -;; FIXME: Disabled because in lshiftrt:SI op1 must match op0 -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_operand 1 "general_operand" "") - (match_operand 2 "general_operand" "")])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "0 && (peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(match_dup 1) - (match_dup 2)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(zero_extend:HI - (match_operand 1 "general_operand" "")) - (match_operand 2 "general_operand" "")])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(zero_extend:HI (match_dup 1)) - (match_dup 2)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_operand 1 "general_operand" "") - (zero_extend:HI - (match_operand 2 "general_operand" ""))])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(match_dup 1) - (zero_extend:HI (match_dup 2))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(zero_extend:SI - (match_operand 1 "general_operand" "")) - (match_operand 2 "general_operand" "")])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(zero_extend:SI (match_dup 1)) - (match_dup 2)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_operand 1 "general_operand" "") - (zero_extend:SI - (match_operand 2 "general_operand" ""))])) - (set (match_operand 4 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 4) - (match_op_dup 3 [(match_dup 1) - (zero_extend:SI (match_dup 2))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_operand 4 "general_operand" "") - (match_dup 0)]))] - "0 && ((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 4) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(zero_extend:HI - (match_operand 4 "general_operand" "")) - (match_dup 0)]))] - "((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(zero_extend:HI (match_dup 4)) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(zero_extend:SI - (match_operand 4 "general_operand" "")) - (match_dup 0)]))] - "((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(zero_extend:SI (match_dup 4)) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_dup 0) - (match_operand 4 "general_operand" "")]))] - "0 && ((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1) - (match_dup 4)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_dup 0) - (zero_extend:HI - (match_operand 4 "general_operand" ""))]))] - "((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1) - (zero_extend:HI (match_dup 4))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_binary_operator" - [(match_dup 0) - (zero_extend:SI - (match_operand 4 "general_operand" ""))]))] - "((peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[0], operands[2])) - && ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1) - (zero_extend:SI (match_dup 4))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(match_operand 3 "general_operand" "") - (match_dup 0)]))] - "0 && (peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(match_dup 3) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(zero_extend:HI - (match_operand 3 "general_operand" "")) - (match_dup 0)]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(zero_extend:HI (match_dup 3)) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(zero_extend:SI - (match_operand 3 "general_operand" "")) - (match_dup 0)]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(zero_extend:SI (match_dup 3)) - (match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(match_dup 0) - (match_operand 3 "general_operand" "")]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(match_dup 1) - (match_dup 3)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(match_dup 0) - (zero_extend:HI - (match_operand 3 "general_operand" ""))]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(match_dup 1) - (zero_extend:HI (match_dup 3))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_operator 2 "ip2k_binary_operator" - [(match_dup 0) - (zero_extend:SI - (match_operand 3 "general_operand" ""))]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (cc0) - (match_op_dup 2 [(match_dup 1) - (zero_extend:SI (match_dup 3))]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operator 3 "ip2k_unary_operator" - [(match_operand 1 "general_operand" "")])) - (set (match_operand 2 "nonimmediate_operand" "") - (match_dup 0))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (match_operand 2 "nonimmediate_operand" "") - (match_operator 3 "ip2k_unary_operator" [(match_dup 0)]))] - "(peep2_reg_dead_p (2, operands[0]) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))))" - [(set (match_dup 2) - (match_op_dup 3 [(match_dup 1)]))] - "") - -(define_peephole2 - [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") - (match_operand 1 "nonimmediate_operand" "")) - (set (cc0) - (match_dup 0))] - "peep2_reg_dead_p (2, operands[0])" - [(set (cc0) - (match_dup 1))] - "") - -;; Look for places where we can shorten a compare operation. -;; -(define_peephole2 - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (const_int 0)) - (set (cc0) - (match_operand:HI 1 "nonimmediate_operand" "")) - (set (pc) - (if_then_else (match_operator 2 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "(rtx_equal_p (ip2k_get_high_half (operands[1], QImode), operands[0]))" - [(set (match_dup 0) - (const_int 0)) - (set (cc0) - (match_dup 4)) - (set (pc) - (if_then_else (match_op_dup 2 - [(cc0) (const_int 0)]) - (label_ref (match_dup 3)) - (pc)))] - "{ - operands[4] = ip2k_get_low_half (operands[1], QImode); - }") - -;; Look for places where we can shorten a compare operation. -;; -(define_peephole2 - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (const_int 0)) - (set (cc0) - (compare (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand 2 "const_int_operand" ""))) - (set (pc) - (if_then_else (match_operator 3 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "(rtx_equal_p (ip2k_get_high_half (operands[1], QImode), operands[0]) - && (abs (INTVAL (operands[2]) <= 127)))" - [(set (match_dup 0) - (const_int 0)) - (set (cc0) - (compare (match_dup 5) - (match_dup 6))) - (set (pc) - (if_then_else (match_op_dup 3 - [(cc0) (const_int 0)]) - (label_ref (match_dup 4)) - (pc)))] - "{ - operands[5] = ip2k_get_low_half (operands[1], QImode); - operands[6] = gen_int_mode (INTVAL (operands[2]) & 0xff, QImode); - }") - -;; This is one of those cases where gcc just can't untangle our wishes. We -;; want to add some values but get two copies of the result. In this instance -;; however, the seconds copy can be made more cheaply by combining things. -;; -(define_peephole - [(set (match_operand:HI 0 "ip2k_nonsp_reg_operand" "+&u") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (match_operand:HI 2 "general_operand" "rSi"))) - (set (match_operand:HI 3 "ip2k_gen_operand" "=&uS") - (match_dup 0))] - "(ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && (!REG_P (operands[3]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))))" - "mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\t%L3,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w\;mov\\t%H3,w") - -(define_peephole - [(set (match_operand:HI 0 "ip2k_short_operand" "+&S") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (match_operand:HI 2 "general_operand" "rSi"))) - (set (match_operand:HI 3 "ip2k_nonsp_reg_operand" "=&u") - (match_dup 0))] - "(ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ! rtx_equal_p (operands[0], operands[1]) - && ! rtx_equal_p (operands[0], operands[2]))" - "mov\\tw,%L2\;add\\tw,%L1\;mov\\t%L0,w\;mov\\t%L3,w\;mov\\tw,%H2\;addc\\tw,%H1\;mov\\t%H0,w\;mov\\t%H3,w") - -;; Some splits zero the MSByte of a word that we then use for shifting. We -;; can therefore replace full shifts with zero-extended ones. These are -;; cheaper for us. -;; -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (const_int 0)) - (set (match_operand:HI 1 "nonimmediate_operand" "") - (ashift:HI (match_operand:HI 2 "register_operand" "") - (match_operand 3 "const_int_operand" "")))] - "(rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]) - && peep2_reg_dead_p (2, operands[0]))" - [(set (match_dup 1) - (ashift:HI (zero_extend:HI (match_dup 4)) - (match_dup 3)))] - "{ - operands[4] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (const_int 0)) - (set (match_operand:HI 1 "nonimmediate_operand" "") - (ashift:HI (match_operand:HI 2 "register_operand" "") - (match_operand 3 "const_int_operand" "")))] - "(rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]))" - [(set (match_dup 0) - (const_int 0)) - (set (match_dup 1) - (ashift:HI (zero_extend:HI (match_dup 4)) - (match_dup 3)))] - "{ - operands[4] = ip2k_get_low_half (operands[2], QImode); - }") - -;; Some splits zero the MSByte of a word that we then use for multiplying. We -;; can therefore replace the full multiplies with zero-extended ones. -;; These are cheaper for us. -;; -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (const_int 0)) - (set (match_operand:HI 1 "nonimmediate_operand" "") - (mult:HI (match_operand:HI 2 "register_operand" "") - (zero_extend:HI - (match_operand:QI 3 "const_int_operand" ""))))] - "(rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]) - && (peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (operands[1], operands[2])))" - [(set (match_dup 1) - (mult:HI (zero_extend:HI (match_dup 4)) - (zero_extend:HI (match_dup 3))))] - "{ - operands[4] = ip2k_get_low_half (operands[2], QImode); - }") - -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (const_int 0)) - (set (match_operand:HI 1 "nonimmediate_operand" "") - (mult:HI (match_operand:HI 2 "register_operand" "") - (zero_extend:HI - (match_operand:QI 3 "const_int_operand" ""))))] - "(rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]))" - [(set (match_dup 0) - (const_int 0)) - (set (match_dup 1) - (mult:HI (zero_extend:HI (match_dup 4)) - (zero_extend:HI (match_dup 3))))] - "{ - operands[4] = ip2k_get_low_half (operands[2], QImode); - }") - -;; Merge in a redundant move before a zero-extended multiply. -;; -(define_peephole2 - [(set (match_operand:QI 0 "register_operand" "") - (match_operand:QI 1 "general_operand" "")) - (set (match_operand:HI 2 "nonimmediate_operand" "") - (mult:HI (zero_extend:HI (match_dup 0)) - (zero_extend:HI - (match_operand:QI 3 "const_int_operand" ""))))] - "(peep2_reg_dead_p (2, operands[0]) - || rtx_equal_p (ip2k_get_high_half (operands[2], QImode), operands[0]) - || rtx_equal_p (ip2k_get_low_half (operands[2], QImode), operands[0]))" - [(set (match_dup 2) - (mult:HI (zero_extend:HI (match_dup 1)) - (zero_extend:HI (match_dup 3))))] - "") - -;; Pick up redundant clears followed by adds - these can just become moves. -;; -(define_peephole2 - [(set (match_operand 0 "register_operand" "") - (const_int 0)) - (set (match_operand 2 "nonimmediate_operand" "") - (plus (match_dup 0) - (match_operand 1 "general_operand" "")))] - "peep2_reg_dead_p (2, operands[0])" - [(set (match_dup 2) - (match_dup 1))] - "") - -(define_peephole2 - [(set (match_operand 0 "register_operand" "") - (const_int 0)) - (set (match_dup 0) - (plus (match_dup 0) - (match_operand 1 "general_operand" "")))] - "" - [(set (match_dup 0) - (match_dup 1))] - "") - -;; Clear up an add followed by a push of the result. The fact that this -;; isn't picked up consistently within the combiner suggests a bug somewhere. -;; -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" ""))) - (set (mem:HI (post_dec:HI (reg:HI 6))) - (match_dup 0))] - "peep2_reg_dead_p (2, operands[0])" - [(set (mem:HI (post_dec:HI (reg:HI 6))) - (plus:HI (match_dup 1) - (match_dup 2)))] - "") - -;; Tidy up stack slot addressing where we've eliminated some registers. -;; This looks like something strange going on though as gcc-2.97 didn't -;; exhibit this behaviour, whereas gcc-3.0.4 does. -;; -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand 2 "const_int_operand" ""))) - (set (mem:HI (post_dec:HI (reg:HI 6))) - (plus:HI (match_dup 0) - (match_operand 3 "const_int_operand" "")))] - "peep2_reg_dead_p (2, operands[0])" - [(set (mem:HI (post_dec:HI (reg:HI 6))) - (plus:HI (match_dup 1) - (match_dup 4)))] - "{ - operands[4] = gen_int_mode (INTVAL (operands[2]) + INTVAL (operands[3]), - HImode); - }") - -;; Match duplicate loads of a symbol ref. This isn't something that we want to -;; do at the peephole2 stage because more often than not we'll make one of the -;; two loads redundant after we run peephole2. We catch the remaining cases -;; here though -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+uS") - (match_operand 1 "ip2k_symbol_ref_operand" "i")) - (set (match_operand:HI 2 "nonimmediate_operand" "=uS") - (match_dup 1))] - "((!REG_P (operands[0]) || (REGNO (operands[0]) != REG_DP)) - && (!REG_P (operands[2]) || (REGNO (operands[2]) != REG_DP)))" - "mov\\tw,%L1\;mov\\t%L0,w\;mov\\t%L2,w\;mov\\tw,%H1\;mov\\t%H0,w\;mov\\t%H2,w") - -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "+&uS") - (match_operand 1 "ip2k_symbol_ref_operand" "i")) - (set (match_operand:HI 2 "nonimmediate_operand" "=&uS") - (match_dup 0))] - "" - "*{ - if ((REG_P (operands[0]) - && !(ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), 2) - && ip2k_xexp_not_uses_reg_p (operands[2], - REGNO (operands[0]), 2))) - || (REG_P (operands[2]) - && !(ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 2) - && ip2k_xexp_not_uses_reg_p (operands[1], - REGNO (operands[2]), 2)))) - { - return AS2 (mov, w, %L1) CR_TAB - AS1 (push, %H1%<) CR_TAB - AS1 (push, %H1%<) CR_TAB - AS1 (pop, %H0%>) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS1 (pop, %H2%>) CR_TAB - AS2 (mov, %L2, w); - } - else - { - return AS2 (mov, w, %L1) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, %L2, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (mov, %H2, w); - } - }") - -;; Handle the common array indexing pattern. -;; This is of the form A = X + (Y * C). -;; We use splits earlier in this file to get our interesting cases into the -;; same form (i.e. zero-extended multiply and add). -;; -(define_insn "*mulacchi" - [(set (match_operand:HI 3 "nonimmediate_operand" "=rS") - (plus:HI (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS")) - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n"))) - (match_operand:HI 0 "general_operand" "rSi")))] - "" - "*{ - if (immediate_operand (operands[0], HImode) - && REG_P (operands[3]) - && (REGNO (operands[3]) == REG_DP) - && (INTVAL (operands[2]) == 2)) - return AS2 (mov, w, %1) CR_TAB - AS1 (loadl, %x0) CR_TAB - AS1 (loadh, %x0) CR_TAB - AS2 (add, dpl, w) CR_TAB - AS2 (add, dpl, w); - else - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, w, %L0) CR_TAB - AS2 (mov, %L3, w) CR_TAB - AS2 (mov, w, %H0) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS2 (mov, %H3, w); - }") - -(define_peephole2 - [(set (match_operand:HI 0 "register_operand" "") - (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "")) - (zero_extend:HI - (match_operand 2 "const_int_operand" "")))) - (set (match_operand:HI 3 "nonimmediate_operand" "") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "")))] - "(((! REG_P (operands[3])) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))) - && peep2_reg_dead_p (2, operands[0]))" - [(set (match_dup 3) - (plus:HI (mult:HI (zero_extend:HI - (match_dup 1)) - (zero_extend:HI - (match_dup 2))) - (match_dup 4)))] - "") - -(define_insn "*mulhi_and_accumulate" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS") - (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "rS")) - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n")))) - (set (match_operand:HI 3 "nonimmediate_operand" "=rS") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "%rSi")))] - "((! REG_P (operands[3])) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3])))))" - "*{ - return AS2 (mov, w, %1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (add, w, %L4) CR_TAB - AS2 (mov, %L3, w) CR_TAB - AS2 (mov, w, %H4) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS2 (mov, %H3, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w); - }") - -(define_peephole2 - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (mult:HI (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "")) - (zero_extend:HI - (match_operand 2 "const_int_operand" "")))) - (set (match_operand:HI 3 "nonimmediate_operand" "") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "")))] - "((! REG_P (operands[3])) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3])))))" - [(parallel [(set (match_dup 0) - (mult:HI (zero_extend:HI - (match_dup 1)) - (zero_extend:HI - (match_dup 2)))) - (set (match_dup 3) - (plus:HI (match_dup 0) - (match_dup 4)))])] - "") - -;; Handle the common array indexing pattern. -;; This is of the form A = X + (Y * C). -;; We use splits earlier in this file to get our interesting cases into the -;; same form (i.e. multiply and add). -;; -(define_peephole - [(set (match_operand:HI 0 "register_operand" "=r") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n")))) - (set (match_operand:HI 3 "nonimmediate_operand" "=rS") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "%rSi")))] - "((!REG_P (operands[3]) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))) - && find_regno_note (insn, REG_DEAD, REGNO (operands[0])))" - "*{ - if (immediate_operand (operands[4], HImode) - && REG_P (operands[3]) - && (REGNO (operands[3]) == REG_DP) - && (INTVAL (operands[2]) == 2) - && ip2k_xexp_not_uses_reg_p (operands[1], REG_DP, - GET_MODE_SIZE (HImode))) - return AS2 (clrb, STATUS, 0) CR_TAB - AS1 (loadl, %x4) CR_TAB - AS1 (loadh, %x4) CR_TAB - AS2 (rl, w, %L1) CR_TAB - AS2 (add, dpl, w) CR_TAB - AS2 (rl, w, %H1) CR_TAB - AS2 (add, dph, w); - else if (!REG_P (operands[3]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))) - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, w, %L4) CR_TAB - AS2 (mov, %L3, w) CR_TAB - AS2 (mov, w, %H4) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS2 (mov, %H3, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, %H3, w); - else - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, w, %L4) CR_TAB - AS1 (push, wreg%<) CR_TAB - AS2 (mov, w, %H4) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS1 (push, wreg%<) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS1 (pop, %H3%>) CR_TAB - AS1 (pop, %L3%>) CR_TAB - AS2 (add, %H3, w); - }") - -;; Handle the more complex variant of the preceding multiply and accumulate -;; variant of the preceding multiply-and-add operation. This one would -;; otherwise fail to match because the result never goes dead. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n")))) - (set (match_dup 0) - (plus:HI (match_dup 0) - (match_operand:HI 3 "general_operand" "%rSi")))] - "(!REG_P (operands[0]) - || (ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0]))) - && ip2k_xexp_not_uses_reg_p (operands[3], REGNO (operands[0]), - GET_MODE_SIZE (GET_MODE (operands[0])))))" - "*{ - if (immediate_operand (operands[3], HImode) - && REG_P (operands[0]) - && (REGNO (operands[0]) == REG_DP) - && (INTVAL (operands[2]) == 2)) - return AS2 (clrb, STATUS, 0) CR_TAB - AS1 (loadl, %x3) CR_TAB - AS1 (loadh, %x3) CR_TAB - AS2 (rl, w, %L1) CR_TAB - AS2 (add, dpl, w) CR_TAB - AS2 (rl, w, %H1) CR_TAB - AS2 (add, dph, w); - else - return AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, w, %L3) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (mov, w, %H3) CR_TAB - AS2 (addc, w, MULH) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, %H0, w); - }") - -;; Handle the a complex variant of the preceding multiply and add -;; operations where the intermediate result is also required. -;; -(define_peephole - [(set (match_operand:HI 0 "nonimmediate_operand" "=rS") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "rS") - (zero_extend:HI - (match_operand:QI 2 "const_int_operand" "n")))) - (set (match_operand:HI 3 "nonimmediate_operand" "=rS") - (plus:HI (match_dup 0) - (match_operand:HI 4 "general_operand" "%rSi")))] - "((!REG_P (operands[3]) - || (ip2k_xexp_not_uses_reg_p (operands[4], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))) - && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[3]), - GET_MODE_SIZE (GET_MODE (operands[3]))))) - && (INTVAL (operands[2]) != 2))" - "* return AS2 (mov, w, %H4) CR_TAB - AS2 (mov, %H3, w) CR_TAB - AS2 (mov, w, %L1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (mov, %L0, w) CR_TAB - AS2 (add, w, %L4) CR_TAB - AS2 (mov, %L3, w) CR_TAB - AS2 (mov, w, MULH) CR_TAB - AS2 (mov, %H0, w) CR_TAB - AS2 (addc, %H3, w) CR_TAB - AS2 (mov, w, %H1) CR_TAB - AS2 (mulu, w, %2) CR_TAB - AS2 (add, %H3, w) CR_TAB - AS2 (add, %H0, w);") - -;; Byte swapping! -;; -(define_peephole - [(set (reg:QI 10) - (match_operand:QI 1 "nonimmediate_operand" "rS")) - (set (match_operand:QI 0 "register_operand" "=r") - (reg:QI 10)) - (set (reg:QI 10) - (match_operand:QI 2 "nonimmediate_operand" "rS")) - (set (match_dup 1) - (reg:QI 10)) - (set (reg:QI 10) - (match_dup 0)) - (set (match_dup 2) - (reg:QI 10))] - "find_regno_note (PREV_INSN (insn), REG_DEAD, REGNO (operands[0]))" - "push\\t%1%<\;push\\t%2%<\;pop\\t%1%>\;pop\\t%2%>") - - diff --git a/gcc/config/ip2k/libgcc.S b/gcc/config/ip2k/libgcc.S deleted file mode 100644 index 1af9ef873ce..00000000000 --- a/gcc/config/ip2k/libgcc.S +++ /dev/null @@ -1,1532 +0,0 @@ -; libgcc.S for the Ubicom IP2k architecture. -; -; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. -; Contributed by Red Hat, Inc and Ubicom, Inc. -; -; This file is part of GNU CC. -; -; GNU CC is free software; you can redistribute it and/or modify -; it under the terms of the GNU General Public License as published by -; the Free Software Foundation; either version 2, or (at your option) -; any later version. -; -; In addition to the permissions in the GNU General Public License, the -; Free Software Foundation gives you unlimited permission to link the -; compiled version of this file 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.) -; -; 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. */ - -/******************************************************* - load byte from arbitrary memory - address passed in first bank register, result in W - -*******************************************************/ - .macro movb to, from - mov w, \from - mov \to, w - .endm - - -#if defined (L_indcall) -/* __indcall - given register containing an address, call the function - * at that address. - */ - - .sect .pram.libgcc,"ax" - .global __indcall - .func _indcall,__indcall - -__indcall: - page 1f - call 1f -1: pop callh ; Get the call target - pop calll - ret ; Transfer to new function - - .endfunc -#endif - - -#if defined (L_mulhi3) - .sect .pram.libgcc,"ax" - .global __mulhi3 - .func _mulhi3, __mulhi3 - -__mulhi3: - mov w, 2(SP) ; First upper half partial product - mulu w, 3(SP) - mov 3(SP), w - mov w, 1(SP) ; Second upper half partial product - mulu w, 4(SP) - add 3(SP), w - mov w, 2(SP) ; Lower half partial product - mulu w, 4(SP) - mov 4(SP), w - mov w, MULH - add 3(SP), w - - mov w, #2 ; Adjust the stack leaving the result to - add spl, w ; be popped off later. - ret - - .endfunc - -#endif /* defined (L_mulhi3) */ - -#if defined (L_mulsi3) -/******************************************************* - Multiplication 32 x 32 -*******************************************************/ - - .sect .text.libgcc,"ax" - .global __mulsi3 - .func _mulsi3, __mulsi3 - -__mulsi3: - clr $80 ; Assume zero result - clr $81 - clr $82 - clr $83 - -2: mov w, 1(sp) - or w, 2(sp) - or w, 3(sp) - or w, 4(sp) - snz ; Any more significant bits to multiply? - page 3f - jmp 3f - - sb 4(sp), 0 ; Check LSB of multiplier - page 1f ; zero => scale multiplicand & multiplier - jmp 1f - - mov w, 8(sp) ; Accumulate product - add $83, w - mov w, 7(sp) - addc $82, w - mov w, 6(sp) - addc $81, w - mov w, 5(sp) - addc $80, w -1: clrb status, 0 ; scale multiplier down - rr 1(sp) - rr 2(sp) - rr 3(sp) - rr 4(sp) - clrb status, 0 - rl 8(sp) - rl 7(sp) - rl 6(sp) - rl 5(sp) - page 2b - jmp 2b - -3: mov w, #8 - add spl ,w - ret - - .endfunc - -#endif /* defined (L_mulsi3) */ - -#if defined (L_muldi3) -/******************************************************* - Multiplication 64 x 64 -*******************************************************/ - - .sect .text.libgcc,"ax" - .global __muldi3 - .func _muldi3, __muldi3 - -__muldi3: - clr $80 ; Assume zero result - clr $81 - clr $82 - clr $83 - clr $84 - clr $85 - clr $86 - clr $87 - -2: mov w, 1(sp) - or w, 2(sp) - or w, 3(sp) - or w, 4(sp) - or w, 5(sp) - or w, 6(sp) - or w, 7(sp) - or w, 8(sp) - snz ; Any more significant bits to multiply? - page 3f - jmp 3f - - sb 8(sp), 0 ; Check LSB of multiplier - page 1f ; zero => scale multiplicand & multiplier - jmp 1f - - mov w, 16(sp) ; Accumulate product - add $87, w - mov w, 15(sp) - addc $86, w - mov w, 14(sp) - addc $85, w - mov w, 13(sp) - addc $84, w - mov w, 12(sp) - addc $83, w - mov w, 11(sp) - addc $82, w - mov w, 10(sp) - addc $81, w - mov w, 9(sp) - addc $80, w - -1: clrb status, 0 ; scale multiplier down - rr 1(sp) - rr 2(sp) - rr 3(sp) - rr 4(sp) - rr 5(sp) - rr 6(sp) - rr 7(sp) - rr 8(sp) - clrb status, 0 - rl 16(sp) - rl 15(sp) - rl 14(sp) - rl 13(sp) - rl 12(sp) - rl 11(sp) - rl 10(sp) - rl 9(sp) - page 2b - jmp 2b - -3: mov w, #16 - add spl, w - ret - - .endfunc - -#endif /* defined (L_muldi3) */ - -#if defined (L_divmodhi4) -#define arg1h 1(SP) -#define arg1l 2(SP) -#define arg2h 3(SP) -#define arg2l 4(SP) -#define resl $81 -#define resh $80 -#define reml $83 -#define remh $82 -#define tmp_var $84 -#define cnt $85 -#define arg1_sign $86 -#define res_sign $87 - - .sect .text.libgcc,"ax" - .global __divmodhi4 - .func _divmodhi4, __divmodhi4 - -__divmodhi4: - mov w,arg2h - mov res_sign,w - mov w,arg1h - mov arg1_sign,w - xor res_sign,w - - sb arg1h,7 - page 1f - jmp 1f - - not arg1h - not arg1l - incsnz arg1l - inc arg1h - -1: sb arg2h, 7 - page 1f - jmp 1f - - not arg2h - not arg2l - incsnz arg2l - inc arg2h - -1: page __udivmodhi4 ; Do the unsigned div/mod - call __udivmodhi4 - - sb arg1_sign, 7 - page 1f - jmp 1f - - not reml - not remh - incsnz reml - inc remh - -1: sb res_sign, 7 - ret - - not resl - not resh - incsnz resl - inc resh - ret - - .endfunc - -#undef arg1h -#undef arg1l -#undef arg2h -#undef arg2l -#undef resl -#undef resh -#undef reml -#undef remh -#undef tmp_var -#undef cnt -#undef arg1_sign -#undef res_sign - -#endif /* defined (L_divmodhi4) */ - -#if defined (L_udivmodhi4) - -#define arg1h 1(SP) -#define arg1l 2(SP) -#define arg2h 3(SP) -#define arg2l 4(SP) -#define resl $81 -#define resh $80 -#define reml $83 -#define remh $82 -#define tmp_var $84 -#define cnt $85 - - .sect .text.libgcc,"ax" - .global __udivmodhi4 - .func _udivmodhi4, __udivmodhi4 - -__udivmodhi4: - clr reml - clr remh - mov w, #17 - mov cnt,w - clrb status, 0 - page 1f - jmp 1f - -2: rl reml - rl remh - mov w, arg2l - sub w, reml - mov tmp_var, w - mov w, arg2h - subc w, remh - sc - page 1f - jmp 1f - mov remh, w - mov w, tmp_var - mov reml, w - -1: rl arg1l - rl arg1h - decsz cnt - page 2b - jmp 2b - - pop resh - pop resl - mov w, #2 - add spl, w - ret - - .endfunc - -#undef arg1h -#undef arg1l -#undef arg2h -#undef arg2l -#undef resl -#undef resh -#undef reml -#undef remh -#undef tmp_var -#undef cnt - -#endif /* defined (L_udivmodhi4) */ - -#if defined (L_divmodsi4) - -#define arg1a 1(SP) -#define arg1b 2(SP) -#define arg1c 3(SP) -#define arg1d 4(SP) - -#define arg2a 5(SP) -#define arg2b 6(SP) -#define arg2c 7(SP) -#define arg2d 8(SP) - -#define resa $80 -#define resb $81 -#define resc $82 -#define resd $83 - -#define rema $84 -#define remb $85 -#define remc $86 -#define remd $87 - -#define tmp_var $88 -#define tmp_var1 $89 -#define tmp_var2 $8a -#define cnt $8b -#define arg1_sign $8c -#define res_sign $8d - - .sect .text.libgcc,"ax" - .global __divmodsi4 - .func _divmodsi4, __divmodsi4 - -__divmodsi4: - mov w, arg2a - mov res_sign, w - mov w, arg1a - mov arg1_sign, w - xor res_sign, w - - sb arg1a, 7 - page 1f - jmp 1f - - not arg1d - not arg1c - not arg1b - not arg1a - incsnz arg1d - incsz arg1c - page 1f - jmp 1f - incsnz arg1b - inc arg1a - -1: sb arg2a, 7 - page 1f - jmp 1f - - not arg2d - not arg2c - not arg2b - not arg2a - incsnz arg2d - incsz arg2c - page 1f - jmp 1f - incsnz arg2b - inc arg2a - -1: page __udivmodsi4 ; Do the unsigned div/mod. - call __udivmodsi4 - - sb arg1_sign, 7 - page 1f - jmp 1f - - not remd - not remc - not remb - not rema - incsnz remd - incsz remc - page 1f - jmp 1f - incsnz remb - inc rema - -1: sb res_sign, 7 - ret - - not resd - not resc - not resb - not resa - incsnz resd - incsz resc - ret - incsnz resb - inc resa - ret - - .endfunc - -#undef arg1a -#undef arg1b -#undef arg1c -#undef arg1d - -#undef arg2a -#undef arg2b -#undef arg2c -#undef arg2d - -#undef resa -#undef resb -#undef resc -#undef resd - -#undef rema -#undef remb -#undef remc -#undef remd - -#undef tmp_var -#undef tmp_var1 -#undef tmp_var2 -#undef cnt -#undef arg1_sign -#undef res_sign - -#endif /* defined (L_divmodsi4) */ - -#if defined (L_udivmodsi4) -#define arg1a 1(SP) -#define arg1b 2(SP) -#define arg1c 3(SP) -#define arg1d 4(SP) - -#define arg2a 5(SP) -#define arg2b 6(SP) -#define arg2c 7(SP) -#define arg2d 8(SP) - -#define resa $80 -#define resb $81 -#define resc $82 -#define resd $83 - -#define rema $84 -#define remb $85 -#define remc $86 -#define remd $87 - -#define tmp_var $88 -#define tmp_var1 $89 -#define tmp_var2 $8a -#define cnt $8b - - .sect .text.libgcc,"ax" - .global __udivmodsi4 - .func _udivmodsi4, __udivmodsi4 - -__udivmodsi4: - clr remd - clr remc - clr remb - clr rema - mov w, #33 - mov cnt, w - clrb status, 0 - page 1f - jmp 1f - -2: rl remd - rl remc - rl remb - rl rema - mov w, arg2d - sub w, remd - mov tmp_var, w - mov w, arg2c - subc w, remc - mov tmp_var1, w - mov w, arg2b - subc w, remb - mov tmp_var2, w - mov w, arg2a - subc w, rema - sc - page 1f - jmp 1f - - mov rema, w - mov w, tmp_var2 - mov remb, w - mov w, tmp_var1 - mov remc, w - mov w, tmp_var - mov remd, w - -1: rl arg1d - rl arg1c - rl arg1b - rl arg1a - decsz cnt - page 2b - jmp 2b - - pop resa - pop resb - pop resc - pop resd - mov w, #4 - add spl, w - ret - - .endfunc - -#undef arg1a -#undef arg1b -#undef arg1c -#undef arg1d - -#undef arg2a -#undef arg2b -#undef arg2c -#undef arg2d - -#undef resa -#undef resb -#undef resc -#undef resd - -#undef rema -#undef remb -#undef remc -#undef remd - -#undef tmp_var -#undef tmp_var1 -#undef tmp_var2 -#undef cnt - -#endif /* defined (L_udivmodsi4) */ - -#if defined (L_divmoddi4) - -#define arg1s 1(SP) -#define arg1t 2(SP) -#define arg1u 3(SP) -#define arg1v 4(SP) -#define arg1w 5(SP) -#define arg1x 6(SP) -#define arg1y 7(SP) -#define arg1z 8(SP) - -#define arg2s 9(SP) -#define arg2t 10(SP) -#define arg2u 11(SP) -#define arg2v 12(SP) -#define arg2w 13(SP) -#define arg2x 14(SP) -#define arg2y 15(SP) -#define arg2z 16(SP) - -#define ress $80 -#define rest $81 -#define resu $82 -#define resv $83 -#define resw $84 -#define resx $85 -#define resy $86 -#define resz $87 - -#define rems $88 -#define remt $89 -#define remu $8a -#define remv $8b -#define remw $8c -#define remx $8d -#define remy $8e -#define remz $8f - -#define tmp_var $90 -#define tmp_var1 $91 -#define tmp_var2 $92 -#define tmp_var3 $93 -#define tmp_var4 $94 -#define tmp_var5 $95 -#define tmp_var6 $96 -#define cnt $97 - - .sect .text.libgcc,"ax" - .global __divmoddi4 - .func _divmoddi4, __divmoddi4 - -__divmoddi4: - rl w, arg2s ; Use MULH to track sign bits. - rl MULH - rl w, arg1s - rl WREG - xor MULH, w - rl w, arg1s - rl MULH - - sb arg1s, 7 - page 1f - jmp 1f - - not arg1s - not arg1t - not arg1u - not arg1v - not arg1w - not arg1x - not arg1y - not arg1z - incsnz arg1z - incsz arg1y - page 1f - jmp 1f - incsnz arg1x - incsz arg1w - page 1f - jmp 1f - incsnz arg1v - incsz arg1u - page 1f - jmp 1f - incsnz arg1t - inc arg1s - -1: sb arg2s, 7 - page 1f - jmp 1f - - not arg2s - not arg2t - not arg2u - not arg2v - not arg2w - not arg2x - not arg2y - not arg2z - incsnz arg2z - incsz arg2y - page 1f - jmp 1f - incsnz arg2x - incsz arg2w - page 1f - jmp 1f - incsnz arg2v - incsz arg2u - page 1f - jmp 1f - incsnz arg2t - inc arg2s - -1: page __udivmoddi4 ; Do the unsigned div/mod. - call __udivmoddi4 - - sb MULH, 0 ; Look at the save sign bit for arg 1. - page 1f - jmp 1f - - not rems - not remt - not remu - not remv - not remw - not remx - not remy - not remz - incsnz remz - incsz remy - page 1f - jmp 1f - incsnz remx - incsz remw - page 1f - jmp 1f - incsnz remv - incsz remu - page 1f - jmp 1f - incsnz remt - inc rems - -1: sb MULH, 1 - ret - - not ress - not rest - not resu - not resv - not resw - not resx - not resy - not resz - incsnz resz - incsz resy - ret - incsnz resx - incsz resw - ret - incsnz resv - incsz resu - ret - incsnz rest - inc ress - ret - - .endfunc - -#undef arg1s -#undef arg1t -#undef arg1u -#undef arg1v -#undef arg1w -#undef arg1x -#undef arg1y -#undef arg1z - -#undef arg2s -#undef arg2t -#undef arg2u -#undef arg2v -#undef arg2w -#undef arg2x -#undef arg2y -#undef arg2z - -#undef ress -#undef rest -#undef resu -#undef resv -#undef resw -#undef resx -#undef resy -#undef resz - -#undef rems -#undef remt -#undef remu -#undef remv -#undef remw -#undef remx -#undef remy -#undef remz - -#undef tmp_var -#undef tmp_var1 -#undef tmp_var2 -#undef tmp_var3 -#undef tmp_var4 -#undef tmp_var5 -#undef tmp_var6 -#undef cnt - -#endif /* defined (L_divmoddi4) */ - -#if defined (L_udivmoddi4) -#define arg1s 1(SP) -#define arg1t 2(SP) -#define arg1u 3(SP) -#define arg1v 4(SP) -#define arg1w 5(SP) -#define arg1x 6(SP) -#define arg1y 7(SP) -#define arg1z 8(SP) - -#define arg2s 9(SP) -#define arg2t 10(SP) -#define arg2u 11(SP) -#define arg2v 12(SP) -#define arg2w 13(SP) -#define arg2x 14(SP) -#define arg2y 15(SP) -#define arg2z 16(SP) - -#define ress $80 -#define rest $81 -#define resu $82 -#define resv $83 -#define resw $84 -#define resx $85 -#define resy $86 -#define resz $87 - -#define rems $88 -#define remt $89 -#define remu $8a -#define remv $8b -#define remw $8c -#define remx $8d -#define remy $8e -#define remz $8f - -#define tmp_var $90 -#define tmp_var1 $91 -#define tmp_var2 $92 -#define tmp_var3 $93 -#define tmp_var4 $94 -#define tmp_var5 $95 -#define tmp_var6 $96 -#define cnt $97 - - .sect .text.libgcc,"ax" - .global __udivmoddi4 - .func _udivmoddi4, __udivmoddi4 - -__udivmoddi4: - clr rems - clr remt - clr remu - clr remv - clr remw - clr remx - clr remy - clr remz - mov w, #65 - mov cnt, w - clrb status, 0 - page 1f - jmp 1f - -2: rl remz - rl remy - rl remx - rl remw - rl remv - rl remu - rl remt - rl rems - mov w, arg2z - sub w, remz - mov tmp_var, w - mov w, arg2y - subc w, remy - mov tmp_var1, w - mov w, arg2x - subc w, remx - mov tmp_var2, w - mov w, arg2w - subc w, remw - mov tmp_var3, w - mov w, arg2v - subc w, remv - mov tmp_var4, w - mov w, arg2u - subc w, remu - mov tmp_var5, w - mov w, arg2t - subc w, remt - mov tmp_var6, w - mov w, arg2s - subc w, rems - sc - page 1f - jmp 1f - - mov rems, w - mov w, tmp_var6 - mov remt, w - mov w, tmp_var5 - mov remu, w - mov w, tmp_var4 - mov remv, w - mov w, tmp_var3 - mov remw, w - mov w, tmp_var2 - mov remx, w - mov w, tmp_var1 - mov remy, w - mov w, tmp_var - mov remz, w - -1: rl arg1z - rl arg1y - rl arg1x - rl arg1w - rl arg1v - rl arg1u - rl arg1t - rl arg1s - decsz cnt - page 2b - jmp 2b - - pop ress - pop rest - pop resu - pop resv - pop resw - pop resx - pop resy - pop resz - mov w, #8 - add spl, w - ret - - .endfunc - -#undef arg1s -#undef arg1t -#undef arg1u -#undef arg1v -#undef arg1w -#undef arg1x -#undef arg1y -#undef arg1z - -#undef arg2s -#undef arg2t -#undef arg2u -#undef arg2v -#undef arg2w -#undef arg2x -#undef arg2y -#undef arg2z - -#undef ress -#undef rest -#undef resu -#undef resv -#undef resw -#undef resx -#undef resy -#undef resz - -#undef rems -#undef remt -#undef remu -#undef remv -#undef remw -#undef remx -#undef remy -#undef remz - -#undef tmp_var -#undef tmp_var1 -#undef tmp_var2 -#undef tmp_var3 -#undef tmp_var4 -#undef tmp_var5 -#undef tmp_var6 -#undef cnt - -#endif /* defined (L_udivmoddi4) */ - -#define LT #0 -#define EQ #1 -#define GT #2 - -#if defined(L_cmphi2) -#define arg1l 2(sp) -#define arg1h 1(sp) -#define arg2l 4(sp) -#define arg2h 3(sp) - - .sect .text.libgcc,"ax" - .global __cmphi2 - .global __cmp_ret - .global __cmpqi_ret - .func _cmphi2, __cmphi2 - -__cmphi2: - mov w,arg1l - sub w,arg2l - snz - page 2f - jmp 2f - mov w,arg1h -1: - subc w,arg2h - clr arg2l - rl arg2l - snb arg1h,7 - setb arg2l,2 - snb arg2h,7 - setb arg2l,1 - mov w,#3 - -__cmp_ret: - add spl,w ; sign1 - pop wreg ; sign2 - -__cmpqi_ret: - add pcl,w ; carry of arg1 - arg2 - retw GT ; [000] arg1 > arg2 - retw LT ; [001] arg1 < arg2 - retw GT ; [010] arg1 > arg2 - retw GT ; [011] arg1 > arg2 - retw LT ; [100] arg1 < arg2 - retw LT ; [101] arg1 < arg2 - retw GT ; [110] arg1 > arg2 - retw LT ; [111] arg1 < arg2 -2: - mov w,arg1h - cse w,arg2h - page 1b - jmp 1b - mov w,#4 - add spl,w - retw EQ - - .endfunc -#undef arg1l -#undef arg1h -#undef arg2l -#undef arg2h -#endif /* L_cmphi2 */ - -#if defined(L_cmpqi2) -#define arg1 1(sp) -#define arg2 2(sp) - - .sect .text.libgcc,"ax" - .global __cmpqi2 - .func _cmpqi2, __cmpqi2 - -__cmpqi2: - mov w, arg1 - sub w, arg2 - snz - page 2f - jmp 2f - - clr wreg - rl wreg - snb arg1, 7 - setb wreg, 2 - snb arg2, 7 - setb wreg, 1 - inc spl - inc spl - page __cmpqi_ret - jmp __cmpqi_ret - -2: mov w, #2 - add spl, w - retw EQ - - .endfunc -#undef arg1l -#undef arg2l -#endif /* L_cmpqi2 */ - -#if defined(L_cmpsi2) -#define arg1d 4(sp) -#define arg1c 3(sp) -#define arg1b 2(sp) -#define arg1a 1(sp) -#define arg2d 8(sp) -#define arg2c 7(sp) -#define arg2b 6(sp) -#define arg2a 5(sp) - - .sect .text.libgcc,"ax" - .global __cmpsi2 - .func _cmpsi2, __cmpsi2 - -__cmpsi2: - mov w, arg1d - sub w, arg2d - snz - page 2f - jmp 2f - -1: mov w, arg1c - subc w, arg2c - mov w, arg1b - subc w, arg2b - mov w, arg1a - subc w, arg2a - - clr arg2d - rl arg2d - snb arg1a, 7 - setb arg2d, 2 - snb arg2a, 7 - setb arg2d, 1 - mov w, #7 - page __cmp_ret - jmp __cmp_ret - -2: mov w, arg1c - cse w, arg2c - page 1b - jmp 1b - - mov w, arg1b - cse w, arg2b - page 1b - jmp 1b - - mov w, arg1a - cse w, arg2a - page 1b - jmp 1b - - mov w, #8 - add spl, w - retw EQ - - .endfunc - -#undef arg1d -#undef arg1c -#undef arg1b -#undef arg1a -#undef arg2d -#undef arg2c -#undef arg2b -#undef arg2a -#endif /* L_cmpsi2 */ - -#if defined(L_cmpdi2) -#define arg1z 8(sp) -#define arg1y 7(sp) -#define arg1x 6(sp) -#define arg1w 5(sp) -#define arg1v 4(sp) -#define arg1u 3(sp) -#define arg1t 2(sp) -#define arg1s 1(sp) - -#define arg2z 16(sp) -#define arg2y 15(sp) -#define arg2x 14(sp) -#define arg2w 13(sp) -#define arg2v 12(sp) -#define arg2u 11(sp) -#define arg2t 10(sp) -#define arg2s 9(sp) - - .sect .text.libgcc,"ax" - .global __cmpdi2 - .func _cmpdi2, __cmpdi2 - -__cmpdi2: - mov w, arg1z - sub w, arg2z - snz - page 2f - jmp 2f - -1: mov w, arg1y - subc w, arg2y - mov w, arg1x - subc w, arg2x - mov w, arg1w - subc w, arg2w - mov w, arg1v - subc w, arg2v - mov w, arg1u - subc w, arg2u - mov w, arg1t - subc w, arg2t - mov w, arg1s - subc w, arg2s - clr arg2z - rl arg2z - snb arg1s, 7 - setb arg2z, 2 - snb arg2s, 7 - setb arg2z, 1 - mov w, #15 - page __cmp_ret - jmp __cmp_ret - -2: mov w, arg1y - cse w, arg2y - page 1b - jmp 1b - - mov w, arg1x - cse w, arg2x - page 1b - jmp 1b - - mov w, arg1w - cse w, arg2w - page 1b - jmp 1b - - mov w, arg1v - cse w, arg2v - page 1b - jmp 1b - - mov w, arg1u - cse w, arg2u - page 1b - jmp 1b - - mov w, arg1t - cse w, arg2t - page 1b - jmp 1b - - mov w, arg1s - cse w, arg2s - page 1b - jmp 1b - - mov w, #16 - add spl, w - retw EQ - - .endfunc - -#undef arg1z -#undef arg1y -#undef arg1x -#undef arg1w -#undef arg1v -#undef arg1u -#undef arg1t -#undef arg1s -#undef arg2z -#undef arg2y -#undef arg2x -#undef arg2w -#undef arg2v -#undef arg2u -#undef arg2t -#undef arg2s - -#endif /* L_cmpdi2 */ - -#if defined(L_cmpdi2_dp) - .sect .text.libgcc,"ax" - .global __cmpdi2_dp - .func _cmpdi2_dp, __cmpdi2_dp - -__cmpdi2_dp: - push 7(dp) - push 6(dp) - push 5(dp) - push 4(dp) - push 3(dp) - push 2(dp) - push 1(dp) - push (dp) - page __cmpdi2 - jmp __cmpdi2 - - .endfunc -#endif /* L_cmpdi2_dp */ - -#if defined(L_fp_pop_args_ret) - .sect .pram.libgcc,"ax" - .global __fp_pop_args_ret - .global __pop_args_ret - .func __fp_pop_args_ret, __fp_pop_args_ret - -__fp_pop_args_ret: - pop 0xfd - pop 0xfe -__pop_args_ret: - pop callh - pop calll - add spl, w - ret - - .endfunc -#endif /* L_fp_pop_args_ret */ - -#if defined(L_leaf_fp_pop_args_ret) - .sect .pram.libgcc,"ax" - .global __leaf_fp_pop_args_ret - .func __leaf_fp_pop_args_ret, __leaf_fp_pop_args_ret - -__leaf_fp_pop_args_ret: - pop 0xfd - pop 0xfe - add spl, w - ret - - .endfunc -#endif /* L_leaf_fp_pop_args_ret */ - -#if defined(L_fp_pop2_args_ret) - .sect .pram.libgcc,"ax" - .global __fp_pop2_args_ret - .global __pop2_args_ret - .func __fp_pop2_args_ret, __fp_pop2_args_ret - -__fp_pop2_args_ret: - pop 0xfd - pop 0xfe -__pop2_args_ret: - mov w, #2 - pop callh - pop calll - add spl, w - ret - - .endfunc -#endif /* L_fp_pop2_args_ret */ - -#if defined(L_leaf_fp_pop2_args_ret) - .sect .pram.libgcc,"ax" - .global __leaf_fp_pop2_args_ret - .func __leaf_fp_pop2_args_ret, __leaf_fp_pop2_args_ret - -__leaf_fp_pop2_args_ret: - pop 0xfd - pop 0xfe - mov w, #2 - add spl, w - ret - - .endfunc -#endif /* L_leaf_fp_pop2_args_ret */ - -#if defined(L_movstrhi_countqi) - .sect .pram.libgcc,"ax" - .global __movstrhi_countqi - .func _movstrhi_countqi, __movstrhi_countqi - -__movstrhi_countqi: - push dph ; Save our pointer regs - push dpl - push iph - push ipl - - mov w, 5(SP) ; Get our dest pointer - mov dph, w - mov w, 6(SP) - mov dpl, w - mov w, 7(SP) ; And our source pointer - mov iph, w - mov w, 8(SP) - mov ipl, w - -1: push (IP) ; *dest++ = *src++ - pop 0(DP) - inc ipl - inc dpl - decsz 9(SP) ; Loop until completed - page 1b - jmp 1b - - pop ipl ; Restore our pointer regs - pop iph - pop dpl - pop dph - - mov w, #5 ; Tidy up our stack args - add spl, w - ret - - .endfunc -#endif - -#if defined(L_movstrhi_counthi) - .sect .text.libgcc,"ax" - .global __movstrhi_counthi - .func _movstrhi_counthi, __movstrhi_counthi - -__movstrhi_counthi: - push dph ; Save our pointer regs - push dpl - push iph - push ipl - - mov w, 5(SP) ; Get our dest pointer - mov dph, w - mov w, 6(SP) - mov dpl, w - mov w, 7(SP) ; And our source pointer - mov iph, w - mov w, 8(SP) - mov ipl, w - - test 10(SP) ; If we have a non-zero LSB then adjust the - sz ; MSB of the loop count to allow us to use - inc 9(SP) ; skip tricks! - -1: push (IP) ; *dest++ = *src++ - pop 0(DP) - inc ipl - inc dpl - decsnz 10(SP) ; Loop until completed - note the skip trick - decsz 9(SP) ; on the MSB! - page 1b - jmp 1b - - pop ipl ; Restore our pointer regs - pop iph - pop dpl - pop dph - - mov w, #6 ; Tidy up our stacked args. - add spl, w - ret - - .endfunc -#endif - -#if defined(L_exit) - .sect .text.libgcc,"ax" - .global __exit - .global _exit - .func _exit, __exit - .weak __exit - .weak _exit - -_exit: -__exit: - pop $88 - pop wreg - or w, $88 - push wreg - push #0 - push #1 - system ; Exit wreg - page __exit ; Never return - jmp __exit - - .endfunc -#endif - -#if defined(Labort) - .sect .text.libgcc,"ax" - .global _abort - .func abort, _abort - -_abort: - push #1 - push #0 - push #1 - system ; Exit 1 - ret - - .endfunc -#endif - -#if defined(Lwrite) - /* Dummy entrypoint to suppress problems with glue code. */ - .sect .text.libgcc,"ax" - .global _write - .func write, _write -;; -;; write (fil,buf,len) - say that write succeeds.... -;; -_write: - movb $80, 5(SP) - movb $81, 6(SP) ; Return length written - mov w, #6 - add spl, w - ret - - .endfunc -#endif - diff --git a/gcc/config/ip2k/t-ip2k b/gcc/config/ip2k/t-ip2k deleted file mode 100644 index 7d82126c61f..00000000000 --- a/gcc/config/ip2k/t-ip2k +++ /dev/null @@ -1,50 +0,0 @@ -LIB1ASMSRC = ip2k/libgcc.S - -LIB1ASMFUNCS = \ - _indcall \ - _mulhi3 \ - _mulsi3 \ - _muldi3 \ - _udivmodhi4 \ - _divmodhi4 \ - _udivmodsi4 \ - _divmodsi4 \ - _udivmoddi4 \ - _divmoddi4 \ - _cmpqi2 \ - _cmphi2 \ - _cmpsi2 \ - _cmpdi2 \ - _cmpdi2_dp \ - _fp_pop_args_ret \ - _leaf_fp_pop_args_ret \ - _fp_pop2_args_ret \ - _leaf_fp_pop2_args_ret \ - _movstrhi_countqi \ - _movstrhi_counthi \ - abort \ - _exit - -# libgcc2.h thinks that nobody would have SI mode when -# MIN_UNITS_PER_WORD == 1, so lie to keep from major compiler errors. - -TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -DDF=SF -g -DMIN_UNITS_PER_WORD=2 - -fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/ip2k/t-ip2k crt0.o - echo '#define FLOAT' > fp-bit.c - echo '#define FLOAT_ONLY' >> fp-bit.c - echo '#define DF SF' >> fp-bit.c - echo '#define DI SI' >> fp-bit.c - echo '#define CMPtype QItype' >> fp-bit.c - echo '#define SMALL_MACHINE' >> fp-bit.c - echo 'typedef int QItype __attribute__ ((mode (QI)));' >> fp-bit.c - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - - -FPBIT = fp-bit.c - -# Our crt0 is written in assembler and we don't really support profiling. - -CRT0_S = $(srcdir)/config/ip2k/crt0.S -MCRT0_S = $(CRT0_S) - diff --git a/gcc/testsuite/g++.dg/expr/member-of-incomplete-type-1.C b/gcc/testsuite/g++.dg/expr/member-of-incomplete-type-1.C deleted file mode 100644 index 9fe65bc976a..00000000000 --- a/gcc/testsuite/g++.dg/expr/member-of-incomplete-type-1.C +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (C) 2002 Free Software Foundation -// Origin: jmr@fulcrummicro.com -// Contributed by Gabriel Dos Reis - - -struct A; - -int main() -{ - A::g(); // { dg-error "incomplete" "" } -} - diff --git a/gcc/testsuite/g++.dg/expr/pmf-1.C b/gcc/testsuite/g++.dg/expr/pmf-1.C deleted file mode 100644 index 61457ecbdc6..00000000000 --- a/gcc/testsuite/g++.dg/expr/pmf-1.C +++ /dev/null @@ -1,19 +0,0 @@ -// C++ PR/2521 -// Copyright (C) 2002 Free Software Foundation -// Contributed by Gabriel Dos Reis - -// { dg-do compile } - -struct A -{ - void f(); - void foo(void (A::*)(int)); // { dg-error "candidate" "" } - template - void g(T); - void h() - { - void (A::*p)() = &A::f; - void (A::*q)() = &(A::f); // { dg-error "parenthesis" "" } - foo(&g); // { dg-error "" "" } - } -}; diff --git a/gcc/testsuite/g++.dg/tls/diag-1.C b/gcc/testsuite/g++.dg/tls/diag-1.C deleted file mode 100644 index 697d0b13106..00000000000 --- a/gcc/testsuite/g++.dg/tls/diag-1.C +++ /dev/null @@ -1,30 +0,0 @@ -/* Valid __thread specifiers. */ - -__thread int g1; -extern __thread int g2; -static __thread int g3; - -void foo() -{ - extern __thread int l1; - static __thread int l2; -} - -struct A { - static __thread int i; -}; - -__thread int A::i = 42; - -template struct B { - static __thread T t; -}; - -template -__thread T B::t = 42; - -void bar () -{ - int j = B::t; - int k = B::t; -} diff --git a/gcc/testsuite/g++.dg/tls/diag-2.C b/gcc/testsuite/g++.dg/tls/diag-2.C deleted file mode 100644 index 6365406e2e7..00000000000 --- a/gcc/testsuite/g++.dg/tls/diag-2.C +++ /dev/null @@ -1,25 +0,0 @@ -/* Invalid __thread specifiers. */ - -__thread extern int g1; /* { dg-error "`__thread' before `extern'" } */ -__thread static int g2; /* { dg-error "`__thread' before `static'" } */ -__thread __thread int g3; /* { dg-error "duplicate `__thread'" } */ -typedef __thread int g4; /* { dg-error "multiple storage classes" } */ - -void foo() -{ - __thread int l1; /* { dg-error "implicitly auto and declared `__thread'" } */ - auto __thread int l2; /* { dg-error "multiple storage classes" } */ - __thread extern int l3; /* { dg-error "`__thread' before `extern'" } */ - register __thread int l4; /* { dg-error "multiple storage classes" } */ -} - -__thread void f1 (); /* { dg-error "invalid for function" } */ -extern __thread void f2 (); /* { dg-error "invalid for function" } */ -static __thread void f3 (); /* { dg-error "invalid for function" } */ -__thread void f4 () { } /* { dg-error "invalid for function" } */ - -void bar(__thread int p1); /* { dg-error "(invalid in parameter)|(specified for parameter)" } */ - -struct A { - __thread int i; /* { dg-error "specified for field" } */ -}; diff --git a/gcc/testsuite/g++.dg/tls/init-1.C b/gcc/testsuite/g++.dg/tls/init-1.C deleted file mode 100644 index 74f7641fe27..00000000000 --- a/gcc/testsuite/g++.dg/tls/init-1.C +++ /dev/null @@ -1,13 +0,0 @@ -/* Valid initializations. */ - -__thread int i = 42; - -static int j; -__thread int *p = &j; - -/* Note that this is valid in C++ (unlike C) as a run-time initialization. */ -int *q = &i; - -/* Valid because "const int k" is an integral constant expression in C++. */ -__thread const int k = 42; -__thread const int l = k; diff --git a/gcc/testsuite/g++.dg/tls/init-2.C b/gcc/testsuite/g++.dg/tls/init-2.C deleted file mode 100644 index 49df50147b3..00000000000 --- a/gcc/testsuite/g++.dg/tls/init-2.C +++ /dev/null @@ -1,13 +0,0 @@ -/* Invalid initializations. */ - -extern __thread int i; -__thread int *p = &i; /* { dg-error "run-time initialization" } */ - -extern int f(); -__thread int j = f(); /* { dg-error "run-time initialization" } */ - -struct S -{ - S(); -}; -__thread S s; /* { dg-error "run-time initialization" } */ diff --git a/gcc/testsuite/g++.dg/tls/tls.exp b/gcc/testsuite/g++.dg/tls/tls.exp deleted file mode 100644 index a00dad79dce..00000000000 --- a/gcc/testsuite/g++.dg/tls/tls.exp +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2002 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -# GCC testsuite that uses the `dg.exp' driver. - -# Load support procs. -load_lib g++-dg.exp - -# Test for thread-local data supported by the platform. If it -# isn't, everything will fail with the "not supported" message. - -set comp_output [g++_target_compile \ - "$srcdir/$subdir/trivial.C" "trivial.S" assembly ""] -if { [string match "*not supported*" $comp_output] } { - return 0 -} - -# If a testcase doesn't have special options, use these. -global DEFAULT_CXXFLAGS -if ![info exists DEFAULT_CXXFLAGS] then { - set DEFAULT_CXXFLAGS " -ansi -pedantic-errors -Wno-long-long" -} - -# Initialize `dg'. -dg-init - -# Main loop. -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" $DEFAULT_CXXFLAGS - -# All done. -dg-finish diff --git a/gcc/testsuite/g++.dg/tls/trivial.C b/gcc/testsuite/g++.dg/tls/trivial.C deleted file mode 100644 index 1fd70631f33..00000000000 --- a/gcc/testsuite/g++.dg/tls/trivial.C +++ /dev/null @@ -1 +0,0 @@ -__thread int i; diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb42.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb42.C deleted file mode 100644 index c27aa8d2df7..00000000000 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb42.C +++ /dev/null @@ -1,19 +0,0 @@ -//Build don't link: -#include -#include - -template class Expr -{ -public : -Expr(){}; -Expr(const T&){}; -}; - -template -inline bool compare(const Expr a, const Expr b){ return true; }; - -int main() -{ - std::vector a(3); - std::sort( a.begin(), a.end(), compare ); // ERROR - no matching function -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/Wunused.c b/gcc/testsuite/gcc.dg/cpp/trad/Wunused.c deleted file mode 100644 index 403d617f5d0..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/Wunused.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. */ - -/* { dg-do preprocess } */ -/* { dg-options "-Wunused-macros -traditional-cpp" } */ - -/* Test everything related to -Wunused-macros. - - Source: Neil Booth, 23 Jul 2002. */ - -#include "Wunused.h" - -#define used1 /* { dg-bogus "used" } */ -#define used2 /* { dg-bogus "used" } */ -#define used3 /* { dg-bogus "used" } */ -#define used4 something /* { dg-bogus "used" } */ - -#define unused5 /* { dg-warning "used" } */ -#define unused6 /* { dg-warning "used" } */ -#define unused7() /* { dg-warning "used" } */ - -#if defined used1 -#endif -#ifdef used2 -#endif -#ifndef used3 -#endif -used4 - -unused7; /* This does not count as a use. */ - -#if 0 -unused5 /* This does not count as a use. */ -#endif - -#undef unused5 -#define unused6 -unused6 diff --git a/gcc/testsuite/gcc.dg/cpp/trad/Wunused.h b/gcc/testsuite/gcc.dg/cpp/trad/Wunused.h deleted file mode 100644 index 8b54412bdd4..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/Wunused.h +++ /dev/null @@ -1 +0,0 @@ -#define unused_but_ok diff --git a/gcc/testsuite/gcc.dg/cpp/trad/__STDC__.c b/gcc/testsuite/gcc.dg/cpp/trad/__STDC__.c deleted file mode 100644 index b25bcb9aa76..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/__STDC__.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Test that __STDC__ is not defined. */ - -/* { dg-do preprocess } */ - -#if defined __STDC__ -# error __STDC__ defined /* { dg-bogus "__STDC__" "__STDC__ defined" } */ -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/argcount.c b/gcc/testsuite/gcc.dg/cpp/trad/argcount.c deleted file mode 100644 index 208cd44b3b0..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/argcount.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Test that we correctly complain about an invalid number of macro - arguments. */ - -/* { dg-do preprocess } */ - -#define f(x) x -#define g(x, y) x y -#define h() - -f(); /* { dg-bogus "requires 1" "no arg is 1 empty arg" } */ -f( ); /* { dg-bogus "macro" "1 arg to 1 param macro" } */ -f(1,); /* { dg-error "passed 2" "2 args to 1 param macro" } */ -f(1,2); /* { dg-error "passed 2" "2 args to 1 param macro" } */ -h(); /* { dg-bogus "macro" "no arg to 1 param macro" } */ -h( ); /* { dg-error "passed 1" "1 arg to 0 param macro" } */ -h(1,2); /* { dg-error "passed 2" "2 args to 0 param macro" } */ -g(); /* { dg-error "requires 2" "0 args to 2 param macro" } */ -g( ); /* { dg-error "requires 2" "1 args to 2 param macro" } */ -g( ,2); /* { dg-bogus "requires 2" "2 args to 2 param macro" } */ -g(,); /* { dg-bogus "requires 2" "2 args to 2 param macro" } */ -g(1,2,3); /* { dg-error "passed 3" "3 args to 2 param macro" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/assembler.S b/gcc/testsuite/gcc.dg/cpp/trad/assembler.S deleted file mode 100644 index 729162a5120..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/assembler.S +++ /dev/null @@ -1,25 +0,0 @@ -/* Regression test - in assembly language, # may have some significance - other than 'stringize macro argument' and therefore must be preserved - in the output, and should not be warned about. */ - -/* { dg-do preprocess } */ - -#define foo() mov r0, #5 /* { dg-bogus "not followed" "spurious warning" } */ - -entry: - foo() - -/* Check we don't EOF on an unknown directive. */ -#unknown directive -#error a later diagnostic /* { dg-error "diagnostic" } */ - -/* - { dg-final { if ![file exists 20000510-1.i] { return } } } - { dg-final { set tmp [grep 20000510-1.i # line] } } - { dg-final { if {[string length $tmp] > 0} \{ } } - { dg-final { pass "20000510-1.S: # preservation" } } - { dg-final { \} else \{ } } - { dg-final { fail "20000510-1.S: # preservation" } } - { dg-final { \} } } -*/ - diff --git a/gcc/testsuite/gcc.dg/cpp/trad/assert1.c b/gcc/testsuite/gcc.dg/cpp/trad/assert1.c deleted file mode 100644 index ff7cc620bec..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/assert1.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Basic tests of the #assert preprocessor extension. */ -/* { dg-do compile } */ -/* { dg-options "" } */ - -#define def unused expansion -#define fail int fail - -#assert abc (def) -#assert abc (ghi) -#assert abc (jkl) -#assert space ( s p a c e ) - -/* Basic: */ -#if !#abc (def) || !#abc (ghi) || !#abc (jkl) -fail -#endif - -/* any answer for #abc */ -#if !#abc -fail -#endif - -/* internal whitespace is collapsed, - external whitespace is deleted */ -#if !#space (s p a c e) || !#space ( s p a c e ) || #space (space) -fail -#endif - -/* removing assertions */ -#unassert abc (jkl) -#if !#abc || !#abc (def) || !#abc (ghi) || #abc (jkl) -fail -#endif - -#unassert abc -#if #abc || #abc (def) || #abc (ghi) || #abc (jkl) -fail -#endif - -int gobble - -/* make sure it can succeed too. - also check space before open paren isn't significant */ -#if #space(s p a c e) -; -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/assert2.c b/gcc/testsuite/gcc.dg/cpp/trad/assert2.c deleted file mode 100644 index 9838e149cbf..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/assert2.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Malformed assertion tests. */ -/* { dg-do preprocess } */ - -#assert /* { dg-error "without predicate" "assert w/o predicate" } */ -#assert % /* { dg-error "an identifier" "assert punctuation" } */ -#assert 12 /* { dg-error "an identifier" "assert number" } */ -#assert abc /* { dg-error "missing" "assert w/o answer" } */ - -#if # /* { dg-error "without predicate" "test w/o predicate" } */ -#endif - -#if #% /* { dg-error "an identifier" "test punctuation" } */ -#endif - -#if #12 /* { dg-error "an identifier" "test number" } */ -#endif - -#if #abc -#error /* { dg-bogus "error" "test w/o answer" } */ -#endif - -#if #abc[def] /* { dg-error "not valid in" "bad syntax" } */ -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/assert3.c b/gcc/testsuite/gcc.dg/cpp/trad/assert3.c deleted file mode 100644 index df9b19fdaf9..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/assert3.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright (C) 2000 Free Software Foundation, Inc. */ - -/* { dg-do preprocess } */ -/* { dg-options "-A abc=def -A abc\(ghi\) \"-Aabc = jkl\" -A abc=mno -A -abc=mno" } */ - -/* Test -A command line syntax. Source Neil Booth. 31 Oct 2000. */ - -#if !#abc (def) || !#abc (ghi) || !#abc (jkl) || #abc(mno) -#error Command line -A assertions -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/builtins.c b/gcc/testsuite/gcc.dg/cpp/trad/builtins.c deleted file mode 100644 index df2718983a1..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/builtins.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Test that builtin-macros are OK. */ - -/* { dg-do run } */ - -#include "builtins.h" - -void abort (void); -char *strstr (const char *, const char *); -int strcmp (const char *, const char *); - -#define LINE __LINE__ - -#if __LINE__ != 13 -# error __LINE__ part 1 /* { dg-bogus "__LINE__" } */ -#endif - -#if \ - __LINE__ != 18 -# error __LINE__ part 2 /* { dg-bogus "__LINE__" } */ -#endif - -#if LINE != 22 -# error __LINE__ part 3 /* { dg-bogus "__LINE__" } */ -#endif - -#if __INCLUDE_LEVEL != 0 -# error __INCLUDE_LEVEL__ /* { dg-bogus "__INCLUDE_LEVEL__" } */ -#endif - -#if !defined (__TIME__) -# error __TIME__ /* { dg-bogus "__TIME__" } */ -#endif - -#if !defined (__DATE__) -# error __DATE__ /* { dg-bogus "__DATE__" } */ -#endif - - -int main () -{ - /* level is defined in builtins.h. */ - if (level != 1) - abort (); - - if (!strstr (__FILE__, "builtins.c")) - abort (); - - if (!strcmp (__BASE_FILE__, "builtins.c")) - abort (); - - return 0; -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/builtins.h b/gcc/testsuite/gcc.dg/cpp/trad/builtins.h deleted file mode 100644 index 9f2b9a01402..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/builtins.h +++ /dev/null @@ -1 +0,0 @@ -int level = __INCLUDE_LEVEL__; diff --git a/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C.c b/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C.c deleted file mode 100644 index ff67ddbdb7b..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (C) 2000 Free Software Foundation, Inc. */ - -/* { dg-do preprocess } */ -/* { dg-options "-C -traditional-cpp" } */ - -/* Test -C doesn't fail with #define. #define is the tricky case, - being the only directive that remembers its comments. - - -C treats comments as tokens in their own right, so e.g. comment at - the beginning of a directive turns it into a non-directive. */ - -#define simple no comments - -#define/**/obj_like/**/(some)/**/thing/**/ -#define fun_like(/**/x/**/,/**/y/**/)/**/ -/**/#define not_a_macro - -#if !defined simple || !defined obj_like || !defined fun_like -#error Missed some macros with -C -#endif - -#ifdef not_a_macro -#error not_a_macro is! -#endif - -/* Check obj_like doesn't expect arguments, and fun_like does. */ -obj_like -fun_like (foo, bar) - -/* Check OK to redefine fun_like without comments in the params. */ -#define fun_like(x, y)/**/ - -/* Check comments in macros in directives are OK. */ -#define ZERO 0 /* A trailing comment. */ - -#if ZERO -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C2.c b/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C2.c deleted file mode 100644 index 6836e9e9357..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-C2.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. */ - -/* { dg-do preprocess } */ -/* { dg-options "-C -traditional-cpp" } */ - -/* Test that comments are actually written out - - Neil Booth, 24 Jun 2002. */ - -/* - { dg-final { if ![file exists cmdlne-C2.i] { return } } } - { dg-final { if { [grep cmdlne-C2.i "dg-final"] != "" } { return } } } - { dg-final { fail "cmdlne-C2.i: C comments output with -C" } } -*/ - diff --git a/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dD.c b/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dD.c deleted file mode 100644 index 1e4c8c867c9..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dD.c +++ /dev/null @@ -1,9 +0,0 @@ -/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. */ - -/* { dg-do preprocess } */ -/* { dg-options "-dD -traditional-cpp" } */ - -/* Test -dD does not fail. */ - -#define objlike obj like -#define funlike(like) fun like diff --git a/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dM.c b/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dM.c deleted file mode 100644 index 0fb5bd9ddb5..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/cmdlne-dM.c +++ /dev/null @@ -1,9 +0,0 @@ -/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. */ - -/* { dg-do preprocess } */ -/* { dg-options "-dM -traditional-cpp" } */ - -/* Test -dM does not fail. */ - -#define objlike obj like -#define funlike(like) fun like diff --git a/gcc/testsuite/gcc.dg/cpp/trad/comment-2.c b/gcc/testsuite/gcc.dg/cpp/trad/comment-2.c deleted file mode 100644 index 8d54e3a0f32..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/comment-2.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Test for warning of nested comments. */ - -/* { dg-do preprocess } */ - -/* { dg-options "-traditional-cpp -Wcomments" } - -/* /* */ /* { dg-warning "within comment" } */ - -/* - - /* { dg-warning "within comment" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/comment.c b/gcc/testsuite/gcc.dg/cpp/trad/comment.c deleted file mode 100644 index ce9d7f18e1c..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/comment.c +++ /dev/null @@ -1,5 +0,0 @@ -/* Test for warning of unterminated comment. */ - -/* { dg-do preprocess } */ - -/* { dg-warning "unterminated comment" } diff --git a/gcc/testsuite/gcc.dg/cpp/trad/define.c b/gcc/testsuite/gcc.dg/cpp/trad/define.c deleted file mode 100644 index d83288df23e..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/define.c +++ /dev/null @@ -1,2 +0,0 @@ -/* { dg-do preprocess } */ -/* { dg-options "-traditional-cpp -DDEFINE1DEFINE -DDEFINE2DEFIN=" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/defined.c b/gcc/testsuite/gcc.dg/cpp/trad/defined.c deleted file mode 100644 index a24ecd519ea..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/defined.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (C) 2000 Free Software Foundation, Inc. */ - -/* { dg-do preprocess } */ - -/* Tests tradcpp0 with defined. The defined operator in traditional C - works just the same as the defined operator in Standard C. */ - -/* Source: Zack Weinberg, glibc, Neil Booth 11 Dec 2000. */ - -#if defined REGPARMS -#error REGPARMS should not be defined -#endif - -#define REGPARMS 1 -#if !defined REGPARMS -#error REGPARMS should be defined -#endif - -#define defined /* { dg-error "defined" } */ - -/* No diagnostics, though you could argue there should be. */ -#if defined defined -#error defined is defined! -#endif - -#define is_Z_defined defined Z - -#if defined Z -#error Z is not defined -#endif - -/* The behaviour of "defined" when it comes from a macro expansion is - now documented. */ -#if is_Z_defined -#error Macro expanding into defined operator test 1 -#endif - -#define Z - -#if !defined Z -#error Z is defined -#endif - -#if !is_Z_defined -#error Macro expanding into defined operator test 2 -#endif - -#undef is_Z_defined -#undef Z - -/* Do all the tests over again with the () form of defined. */ - -/* No diagnostics, though you could argue there should be. */ -#if defined(defined) -#error defined is defined! -#endif - -#define is_Z_defined defined ( Z ) - -#if defined(Z) -#error Z is not defined -#endif - -/* The behaviour of "defined" when it comes from a macro expansion is - now documented. */ -#if is_Z_defined -#error Macro expanding into defined operator test 1 -#endif - -#define Z - -#if !defined(Z) -#error Z is defined -#endif - -#if !is_Z_defined -#error Macro expanding into defined operator test 2 -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/directive.c b/gcc/testsuite/gcc.dg/cpp/trad/directive.c deleted file mode 100644 index 04203097b24..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/directive.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Test for some basic aspects of -traditional directive processing. */ - -/* { dg-do preprocess } */ - -/* There is a #error directive. */ - -#error bad /* { dg-error "bad" } */ - -/* Directives with their #s indented are not recognized. */ - #if 0 /* { dg-bogus "unterminated" } */ - -#wrong /* { dg-error "invalid" } */ - -#define foo 2 -#define bar + 3 -#define foobar 6 - -#if foo/**/bar != 5 -# error Comments in directive is a separator /* { dg-bogus "error" } */ -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c b/gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c deleted file mode 100644 index 37ca95c6918..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/escaped-eof.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Test for warning of escaped EOF. */ - -/* { dg-do preprocess } */ - -/* { dg-warning "backslash-new" "escaped EOF warning" { target *-*-* } 7 } */ -\ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/escaped-nl.c b/gcc/testsuite/gcc.dg/cpp/trad/escaped-nl.c deleted file mode 100644 index be8cc53fe65..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/escaped-nl.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Test escaped newlines at start of macro definition are properly - skipped (buglet in skip_whitespace () in cpptrad.c). */ - -/* { dg-do preprocess } */ - -#define NUM \ -100 -#if NUM != 100 -# error NUM not defined properly /* { dg-bogus "error" } */ -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/funlike-2.c b/gcc/testsuite/gcc.dg/cpp/trad/funlike-2.c deleted file mode 100644 index edcf2abf200..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/funlike-2.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Test that nested commas and parentheses in macro arguments are - OK. */ - -/* { dg-do preprocess } */ - -#define f(x) x -#define g(x, y) x y - -#if f((1)) != 1 -# error /* { dg-bogus "error" "nested parens 1" } */ -#endif - -#if f((1, 2)) != 2 -# error /* { dg-bogus "error" "nested comma 1" } */ -#endif - -#if g(, (1)) != 1 -# error /* { dg-bogus "error" "nested parens 2" } */ -#endif - -#if g((1, 2), + 3) != 5 -# error /* { dg-bogus "error" "nested comma 2" } */ -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/funlike-3.c b/gcc/testsuite/gcc.dg/cpp/trad/funlike-3.c deleted file mode 100644 index 5300afba708..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/funlike-3.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Test that function-like macros are restricted to directives, and - that unterminated ones are warned about. */ - -/* { dg-do preprocess } */ - -#define f(x) x - -#if 2 f(/* { dg-error "unterminated" "unterminated macro in directive" } */ -) -#endif - -f( /* { dg-error "unterminated" "unterminated macro" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c b/gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c deleted file mode 100644 index fcc65a8d60d..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Test that undefined names evaluate to zero, that macros after a - funlike macro are expanded, and that if it is a '(' the funlike - macro is not treated as such. */ - -/* { dg-do run } */ - -extern void abort (void); - -#define f(x) x - -int main () -{ -#if f(1) == f /**/ (/**/1/**/) - int x; -#endif - - x = 0; - if (f - /**/ ( - /**/ 0/**/ - /**/) - ) - abort (); - - return 0; -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/funlike.c b/gcc/testsuite/gcc.dg/cpp/trad/funlike.c deleted file mode 100644 index db550d53c76..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/funlike.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Test that undefined names evaluate to zero, that macros after a - funlike macro are expanded, and that if it is a '(' the funlike - macro is not treated as such. */ - -/* { dg-do preprocess } */ - -#define f(x) x -#define h != 0 -#define i -#define paren ( - -#if f != 0 -# error /* { dg-bogus "error" "undefined name" } */ -#endif - -#if f h -# error /* { dg-bogus "error" "h not expanded" } */ -#endif - -#if f i -# error /* { dg-bogus "error" "empty macro" } */ -#endif - -#if f paren 6) /* { dg-error "missing binary" "macro-expanded parenthesis" } */ -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/hash.c b/gcc/testsuite/gcc.dg/cpp/trad/hash.c deleted file mode 100644 index 8108c89fbfc..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/hash.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Test for erroneously thinking comments are token-pastes. - From XFree86 4.0. */ -/* { dg-do preprocess } */ - -#ifndef foo -#define foo /**/ -#endif - -#ifndef foo -#define foo /* as nothing */ -#endif - -/* { dg-bogus "(start|end) of macro" "paste at end" { target *-*-* } 7 } */ -/* { dg-bogus "(start|end) of macro" "comment at end" { target *-*-* } 11 } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/include.c b/gcc/testsuite/gcc.dg/cpp/trad/include.c deleted file mode 100644 index 9ca184b5d82..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/include.c +++ /dev/null @@ -1,9 +0,0 @@ -/* Copyright (c) 2002 Free Software Foundation Inc. */ - -/* Test that macros are not expanded in the <> quotes of #inlcude. */ - -/* { dg-do preprocess } */ - -#define __STDC__ 1 /* Stop complaints about non-ISO compilers. */ -#define stdio 1 -#include /* { dg-bogus "o such file or directory" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/literals-1.c b/gcc/testsuite/gcc.dg/cpp/trad/literals-1.c deleted file mode 100644 index 7fde0d5422e..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/literals-1.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Test that (what looks like) comments are not recognised in literals - and that quotes within quotes do not confused the preprocessor. */ - -/* { dg-do run } */ - -extern void abort (void); - -int main () -{ - const char *str1 = "/*"; - const char *str2 = "'"; - - if (str1[0] != '/' || str1[1] != '*' || str1[2] != '\0') - abort (); - - if (str2[0] != '\'' || str2[1] != '\0') - abort (); - -#if '"' != '\"' -# error /* { dg-bogus "error" "double quote in charconst" } */ -#endif - -#if !'\'' -# error quote /* { dg-bogus "quote" "quote in charconst" } */ -#endif - - return 0; -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/literals-2.c b/gcc/testsuite/gcc.dg/cpp/trad/literals-2.c deleted file mode 100644 index 807bb0db0a8..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/literals-2.c +++ /dev/null @@ -1,8 +0,0 @@ -/* Test that unterminated quotes in CPP expressions are - recognized. */ - -/* { dg-do preprocess } */ - -/* { dg-error "missing terminating" "bad charconst" { target *-*-* } 7 } */ -#if 'x -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/maccom1.c b/gcc/testsuite/gcc.dg/cpp/trad/maccom1.c deleted file mode 100644 index da9c4a1e7dd..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/maccom1.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do preprocess } */ -/* { dg-options "-CC -traditional-cpp" } */ - -/* This tests to make sure that comments are ignored between # and the - directive name when the -CC option is used. - - Jason R. Thorpe, 6 Apr 2002 */ - -#/**/define def passed - -def - -/* - { dg-final { if ![file exists maccom1.i] { return } } } - { dg-final { if { [grep maccom1.i "^passed"] != "" } { return } } } - { dg-final { fail "maccom1.c: comment between # and directive name with -CC" } } -*/ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/maccom2.c b/gcc/testsuite/gcc.dg/cpp/trad/maccom2.c deleted file mode 100644 index 331c9fc8c83..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/maccom2.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do preprocess } */ -/* { dg-options "-CC -traditional-cpp" } */ - -/* This tests to make sure that comments between the #define directive - and the macro identifier are ignored (i.e. treated like whitespace) - when the -CC option is used. - - Jason R. Thorpe, 6 Apr 2002 */ - -#define/**/def passed - -def - -/* - { dg-final { if ![file exists maccom2.i] { return } } } - { dg-final { if { [grep maccom2.i "^passed"] != "" } { return } } } - { dg-final { fail "maccom2.c: comment between #define and identifier with -CC" } } -*/ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/maccom3.c b/gcc/testsuite/gcc.dg/cpp/trad/maccom3.c deleted file mode 100644 index b3dd3acba41..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/maccom3.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do preprocess } */ -/* { dg-options "-CC -traditional-cpp" } */ - -/* This tests to make sure that comments in the definition of a macro - parameter list are ignored when the -CC option is used. - - Jason R. Thorpe, 6 Apr 2002 */ - -#define def(x /**/, y) passed - -def(x,y) - -/* - { dg-final { if ![file exists maccom3.i] { return } } } - { dg-final { if { [grep maccom3.i "^passed"] != "" } { return } } } - { dg-final { fail "maccom3.c: comment in macro parameter list with -CC" } } -*/ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/maccom4.c b/gcc/testsuite/gcc.dg/cpp/trad/maccom4.c deleted file mode 100644 index e962d2824dd..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/maccom4.c +++ /dev/null @@ -1,19 +0,0 @@ -/* { dg-do preprocess } */ -/* { dg-options "-CC -traditional-cpp" } */ - -/* This tests to make sure the comment is saved in the macro and copied - to the output file when the macro is expanded when the -CC option is - used. - - Jason R. Thorpe, 6 Apr 2002 */ - -#define def /* passed */ - -def - -/* - /* The + in the regexp prevents it from matching itself. */ - { dg-final { if ![file exists maccom4.i] { return } } } - { dg-final { if { [grep maccom4.i "p+assed"] != "" } { return } } } - { dg-final { fail "maccom4.c: comment in macro expansion with -CC" } } -*/ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/maccom6.c b/gcc/testsuite/gcc.dg/cpp/trad/maccom6.c deleted file mode 100644 index 13f0fc59bdc..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/maccom6.c +++ /dev/null @@ -1,24 +0,0 @@ -/* { dg-do preprocess } */ -/* { dg-options "-CC -traditional-cpp" } */ - -/* This tests to make sure that expressions function properly - when used with macros containing comments and the -CC option - is being used. - - Jason R. Thorpe, 6 Apr 2002 */ - -#define ONE 1 /* one */ -#define TWO 2 /* two */ -#define THREE 3 /* three */ - -#if (ONE + TWO) != THREE -failed -#else -passed -#endif - -/* - { dg-final { if ![file exists maccom6.i] { return } } } - { dg-final { if { [grep maccom6.i "^passed"] != "" } { return } } } - { dg-final { fail "maccom6.c: comments in macro expressions with -CC" } } -*/ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/macroargs.c b/gcc/testsuite/gcc.dg/cpp/trad/macroargs.c deleted file mode 100644 index ce28cccf995..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/macroargs.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Test that whitespace in arguments is preserved, and that each - newline in macro arguments become a space. */ - -/* { dg-do run } */ - -#define f(x, y) "x y" -#define g(x) x - -extern void abort (void); - -int main () -{ - const char *str1 = f( foo ,bar); - const char *str2 = f( -foo -,bar); - - if (strcmp (str1, " foo bar")) - abort (); - - if (strcmp (str1, str2)) - abort (); - - /* Verify that quoted state is preserved over a newline. */ - if (strcmp (g /* { dg-bogus "unterminated 2" } */ ("1 -, 2"), "1 , 2")) - abort (); - - return 0; -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi1.c b/gcc/testsuite/gcc.dg/cpp/trad/mi1.c deleted file mode 100644 index deb992920f8..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi1.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Test "ignore redundant include" facility. - - We must test with C comments, and null directives, outside - the guard conditional; also, we test guarding with #ifndef and #if - !defined. -H is used because cpp might confuse the issue by - optimizing out #line markers. This test only passes if each of the - headers is read exactly once. - - The disgusting regexp in the dg-error line, when stuck into - dg.exp's compiler-output regexp, matches the correct -H output and - only the correct -H output. It has to be all on one line because - otherwise it will not be interpreted all in one unit. */ - -/* { dg-do compile } - { dg-options "-H -traditional-cpp" } - { dg-error "mi1c\.h\n\[^\n\]*mi1nd\.h\n\[^\n\]*mi1ndp\.h\n\[^\n\]*mi1x\.h" "redundant include check" { target *-*-* } 0 } */ - -#include "mi1c.h" -#include "mi1c.h" -#include "mi1c.h" - -#include "mi1nd.h" -#include "mi1nd.h" - -#include "mi1ndp.h" -#include "mi1ndp.h" - -#define MIX_H -#include "mi1x.h" -#include "mi1x.h" - -int -main (void) -{ - return a + c + d; -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi1c.h b/gcc/testsuite/gcc.dg/cpp/trad/mi1c.h deleted file mode 100644 index 2956286eb22..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi1c.h +++ /dev/null @@ -1,12 +0,0 @@ -/* Redundant header include test with C comments at top. */ -# /* And a null directive at the top. */ - -#ifndef CPP_MIC_H -#define CPP_MIC_H - -int a; - -#endif - -# /* And at the end, too! */ -/* And at the end too! */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi1nd.h b/gcc/testsuite/gcc.dg/cpp/trad/mi1nd.h deleted file mode 100644 index c14c1a3c661..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi1nd.h +++ /dev/null @@ -1,8 +0,0 @@ -/* Redundant include check with #if !defined. */ - -#if !defined CPP_MIND_H -#define CPP_MIND_H - -int c; - -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi1ndp.h b/gcc/testsuite/gcc.dg/cpp/trad/mi1ndp.h deleted file mode 100644 index b84202c6d33..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi1ndp.h +++ /dev/null @@ -1,7 +0,0 @@ -#if !defined ( CPP_MINDP_H) -#define CPP_MINDP_H - -/* Redundant include check with #if !defined and parentheses. */ -int d; - -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi1x.h b/gcc/testsuite/gcc.dg/cpp/trad/mi1x.h deleted file mode 100644 index a317cf852bf..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi1x.h +++ /dev/null @@ -1,9 +0,0 @@ -/* This header is never to have its contents visible, but it should - still receive the optimization. */ - -#ifndef MIX_H -#define MIX_H - -#define main wibble - -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi2.c b/gcc/testsuite/gcc.dg/cpp/trad/mi2.c deleted file mode 100644 index 916d5a949d0..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi2.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Test for overly eager multiple include optimization. - Problem distilled from glibc 2.0.7's time.h, sys/time.h, timebits.h. - Problem noted by Tom Tromey . */ -/* { dg-do compile } */ - -#include "mi2a.h" -#include "mi2b.h" - -int main (void) -{ - return x; -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi2a.h b/gcc/testsuite/gcc.dg/cpp/trad/mi2a.h deleted file mode 100644 index e3f53b6cb2e..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi2a.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Test for overly eager multiple include optimization. - Problem distilled from glibc 2.0.7's time.h, sys/time.h, timebits.h. - Problem noted by Tom Tromey . */ - -#include "mi2c.h" diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi2b.h b/gcc/testsuite/gcc.dg/cpp/trad/mi2b.h deleted file mode 100644 index 1d9a8b9b1c5..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi2b.h +++ /dev/null @@ -1,6 +0,0 @@ -/* Test for overly eager multiple include optimization. - Problem distilled from glibc 2.0.7's time.h, sys/time.h, timebits.h. - Problem noted by Tom Tromey . */ - -#define need_x -#include "mi2c.h" diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi2c.h b/gcc/testsuite/gcc.dg/cpp/trad/mi2c.h deleted file mode 100644 index 521792bee2f..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi2c.h +++ /dev/null @@ -1,15 +0,0 @@ -/* Test for overly eager multiple include optimization. - Problem distilled from glibc 2.0.7's time.h, sys/time.h, timebits.h. - Problem noted by Tom Tromey . */ -#ifdef need_x -#undef need_x -#ifndef have_x -#define have_x -extern int x; -#endif -#endif - -#ifndef t_h -#define t_h -extern int y; -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi3.c b/gcc/testsuite/gcc.dg/cpp/trad/mi3.c deleted file mode 100644 index f33fd7887e9..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi3.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Another test case for over-eager multiple include optimization. - This one distilled from glibc's setlocale.c and categories.def. */ -/* { dg-do compile } */ - -#define X a -#include "mi3.def" -#undef X - -#define X b -#include "mi3.def" -#undef X - -#include "mi3.h" -#include "mi3.h" /* The second include declares variable c. */ - -int -main(void) -{ - return a + b + c; -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi3.def b/gcc/testsuite/gcc.dg/cpp/trad/mi3.def deleted file mode 100644 index 375d9c7fe34..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi3.def +++ /dev/null @@ -1,10 +0,0 @@ -/* Another test case for over-eager multiple include optimization. - This one distilled from glibc's setlocale.c and categories.def. - The #ifdef block doesn't cover the entire file, so it must not be - taken for a reinclude guard. */ - -#ifndef NO_POSTLOAD -#define NO_POSTLOAD NULL -#endif - -int X; diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi3.h b/gcc/testsuite/gcc.dg/cpp/trad/mi3.h deleted file mode 100644 index 8774fcf486a..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi3.h +++ /dev/null @@ -1,7 +0,0 @@ -/* Another test case for over-eager multiple include optimization. */ - -#ifndef GUARD -#define GUARD -#elif 1 /* #elif kills optimisation */ -int c; -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi4.c b/gcc/testsuite/gcc.dg/cpp/trad/mi4.c deleted file mode 100644 index c886cc2c8e5..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi4.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright (C) 2000 Free Software Foundation, Inc. */ - -/* { dg-do preprocess } */ - -/* Undefining a macro guard and re-including the file used to confuse - file caching in cppfiles.c, and attempt to open a bad fd. */ - -#include "mi1c.h" -#undef CPP_MIC_H -#include "mi1c.h" diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi5.c b/gcc/testsuite/gcc.dg/cpp/trad/mi5.c deleted file mode 100644 index fe3c8d202d3..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi5.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Test "ignore redundant include" facility, with -C on. - - The disgusting regexp in the dg-error line, when stuck into - dg.exp's compiler-output regexp, matches the correct -H output and - only the correct -H output. It has to be all on one line because - otherwise it will not be interpreted all in one unit. */ - -/* { dg-do preprocess } - { dg-options "-H -C -traditional-cpp" } - { dg-error "mi1c\.h" "redundant include check with -C" { target *-*-* } 0 } */ - -#include "mi1c.h" -#include "mi1c.h" diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi6.c b/gcc/testsuite/gcc.dg/cpp/trad/mi6.c deleted file mode 100644 index aa1c8ed2ec5..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi6.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Another test case for over-eager multiple include optimization, - where the leading "#if !defined" expression is obtained partially, - or wholly, from macros. Neil Booth, 30 Sep 2001. */ - -/* { dg-do compile } */ -/* { dg-options "" } */ - -/* Each include file should not be subject to MI optimisation, since - macro definitions can change. Each header increments the variable - VAR if it is defined. - - The first set of inclusions gets the headers into CPP's cache, but - does nothing since VAR is not defined. The second set should each - increment VAR, since none of the initial set should have been - flagged as optimizable. */ - -#define EMPTYL -#define EMPTYR -#define NOT ! -#define DEFINED defined (guard) -#define NOT_DEFINED ! defined (guard) - -#include "mi6a.h" -#include "mi6b.h" -#include "mi6c.h" -#include "mi6d.h" -#include "mi6e.h" - -/* Define the macro guard, and redefine the macros to something that - forces compilation of the conditional blocks. */ -#define guard -#undef EMPTYL -#define EMPTYL 1 || -#undef EMPTYR -#define EMPTYR || 1 -#undef NOT -#define NOT -#undef DEFINED -#define DEFINED 0 -#undef NOT_DEFINED -#define NOT_DEFINED 1 - -#define VAR five - -int -main(void) -{ - unsigned int five = 0; - -#include "mi6a.h" -#include "mi6b.h" -#include "mi6c.h" -#include "mi6d.h" -#include "mi6e.h" - - if (five != 5) - abort (); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi6a.h b/gcc/testsuite/gcc.dg/cpp/trad/mi6a.h deleted file mode 100644 index 68a2fce4758..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi6a.h +++ /dev/null @@ -1,5 +0,0 @@ -#if NOT_DEFINED - #ifdef VAR - VAR++; - #endif -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi6b.h b/gcc/testsuite/gcc.dg/cpp/trad/mi6b.h deleted file mode 100644 index d2fe8be1784..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi6b.h +++ /dev/null @@ -1,5 +0,0 @@ -#if NOT defined (guard) - #ifdef VAR - VAR++; - #endif -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi6c.h b/gcc/testsuite/gcc.dg/cpp/trad/mi6c.h deleted file mode 100644 index d19cb54335f..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi6c.h +++ /dev/null @@ -1,5 +0,0 @@ -#if !DEFINED - #ifdef VAR - VAR++; - #endif -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi6d.h b/gcc/testsuite/gcc.dg/cpp/trad/mi6d.h deleted file mode 100644 index a1eabba8e92..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi6d.h +++ /dev/null @@ -1,5 +0,0 @@ -#if EMPTYL !defined (guard) - #ifdef VAR - VAR++; - #endif -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi6e.h b/gcc/testsuite/gcc.dg/cpp/trad/mi6e.h deleted file mode 100644 index 26ba7151475..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi6e.h +++ /dev/null @@ -1,5 +0,0 @@ -#if !defined (guard) EMPTYR - #ifdef VAR - VAR++; - #endif -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi7.c b/gcc/testsuite/gcc.dg/cpp/trad/mi7.c deleted file mode 100644 index 8a079d9dd57..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi7.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Test "ignore redundant include" facility. - - -H is used because cpp might confuse the issue by optimizing out - #line markers. This test only passes if the headers is read - twice. - - The disgusting regexp in the dg-error line, when stuck into - dg.exp's compiler-output regexp, matches the correct -H output and - only the correct -H output. It has to be all on one line because - otherwise it will not be interpreted all in one unit. */ - -/* { dg-do preprocess } - { dg-options "-H -traditional-cpp" } - { dg-error "mi7a\.h\n\[^\n\]*mi7a\.h\n\[^\n\]*mi7b\.h\n\[^\n\]*mi7b\.h" "redundant include check" { target *-*-* } 0 } */ - -#include "mi7a.h" -#include "mi7a.h" -#include "mi7b.h" -#include "mi7b.h" diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi7a.h b/gcc/testsuite/gcc.dg/cpp/trad/mi7a.h deleted file mode 100644 index 0c701d7e645..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi7a.h +++ /dev/null @@ -1,4 +0,0 @@ -: -#ifndef GUARD1 -#define GUARD1 -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/mi7b.h b/gcc/testsuite/gcc.dg/cpp/trad/mi7b.h deleted file mode 100644 index 1747e54825e..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/mi7b.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef GUARD2 -#define GUARD2 -#endif -: diff --git a/gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c b/gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c deleted file mode 100644 index 99fd251f2e3..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Test that the null directive doesn't swallow the following line. */ - -/* { dg-do preprocess } */ - -# -#error OK /* { dg-error "OK" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/num-sign.c b/gcc/testsuite/gcc.dg/cpp/trad/num-sign.c deleted file mode 100644 index 7522bbf41e2..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/num-sign.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. */ - -/* { dg-do preprocess { target i?86-*-* } } */ - -/* Tests that traditional numbers are signed, unless otherwise - specified. This test assumes a 32 bit target. - - Neil Booth, 5 Aug 2001. Inspired by PR 3824. */ - -#if 0xffffffffffffffff >= 0 -# error 0xffffffffffffffff /* { dg-bogus "0xffffffffffffffff" "0xffffffffffffffff positive" } */ -#endif - -#if 0xffffffffffffffffU <= 0 -# error 0xffffffffffffffffU /* { dg-bogus "0xffffffffffffffffU" "0xffffffffffffffffU negative" } */ -#endif diff --git a/gcc/testsuite/gcc.dg/cpp/trad/paste.c b/gcc/testsuite/gcc.dg/cpp/trad/paste.c deleted file mode 100644 index 9f1c0db3291..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/paste.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Test for proper comment elimination semantics from cpplib's -traditional. - This should compile and link with compiled with `gcc -traditional-cpp'. - Test case by Jason R. Thorpe . */ - -/* { dg-do compile } */ - -#define A(name) X/**/name - -#define B(name) \ -void A(Y/**/name)() { A(name)(); } - -void Xhello() { printf("hello world\n"); } - -B(hello) - -int main() { XYhello(); return (0); } diff --git a/gcc/testsuite/gcc.dg/cpp/trad/quote.c b/gcc/testsuite/gcc.dg/cpp/trad/quote.c deleted file mode 100644 index f8e61700fd7..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/quote.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Test that unterminated quotes are OK when only preprocessing. */ - -/* { dg-do preprocess } */ - -/* { dg-bogus "unterminated" } */ 'x -/* { dg-bogus "unterminated" } */ "x diff --git a/gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c b/gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c deleted file mode 100644 index b5fd7af7f5f..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Test for warning of and recovery from recursion in object-like - macros. */ - -/* { dg-do preprocess } */ - -#define foo foo -foo /* { dg-error "detected recursion" } */ - -#define bar a bar b -bar /* { dg-error "detected recursion" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c b/gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c deleted file mode 100644 index 5c6550fae2a..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Test for warning of and recovery from recursion in function-like - macros. */ - -/* { dg-do preprocess } */ - -#define foo() foo() -foo(); /* { dg-error "detected recursion" } */ - -#define bar() bar baz() bar -bar(); /* { dg-bogus "detected recursion" } */ - -#define baz() foo() -baz(); /* { dg-error "detected recursion" } */ - -#define a(x) x(a) -a(a); /* { dg-error "detected recursion" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c b/gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c deleted file mode 100644 index 91485ae5f45..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Tests that macros that look recursive but are not are accepted. */ - -/* { dg-do preprocess } */ - -#define g(x) x -g(g(g(g(g(g(g)))))); /* { dg-bogus "detected recursion" } */ - -/* This macro gets longer with each loop, to thwart tests for - recursion based on length. */ -#define f(a,b,c,d,e,f,g,h,i) a(b,c,d,e,f,g,h,i,2 3 4 5) -f(f,f,f,f,f,f,f,f,f) /* { dg-bogus "detected recursion" } */ - -/* The above cases should be enough, but this is taken from cccp - sources so let's try it too. */ -#define foo(x,y) bar (x (y,0), y) -foo (foo, baz); /* { dg-bogus "detected recursion" } */ - -#define mac mac/**/ro -mac /* { dg-bogus "detected recursion" } */ - -#define mac2 mac2 -"mac2" /* { dg-bogus "detected recursion" } */ - -#define macro "macro -macro mac2 /* { dg-bogus "detected recursion" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/redef1.c b/gcc/testsuite/gcc.dg/cpp/trad/redef1.c deleted file mode 100644 index ce5dde0bb37..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/redef1.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Test for redefining traditional macros with insignificant - (i.e. whitespace) differences. */ - -/* { dg-do preprocess } */ - - -#define foo bar -#define /* x */ foo /* x */ bar /* x */ - -#define quux(thud) a one and a thud and a two -#define /**/ quux( thud ) /**/ a one and a /**/ thud /**/ and /**/ a two -#define quux(thud) a one and a thud and a two /* bah */ - -#define f(x, y)x "x y z" y -#define f(x, y) x "x y z" y - -#define baz() whiz bang -#define baz() whiz bang - -#define g foo -#undef g -#define g - -/* { dg-bogus "redefined" "foo redefined" { target *-*-* } 8 } */ -/* { dg-bogus "redefined" "quux redefined" { target *-*-* } 11 } */ -/* { dg-bogus "redefined" "quux redefined" { target *-*-* } 12 } */ -/* { dg-bogus "redefined" "f redefined" { target *-*-* } 15 } */ -/* { dg-bogus "redefined" "baz redefined" { target *-*-* } 18 } */ -/* { dg-bogus "redefined" "g redefined" { target *-*-* } 22 } */ - -/* { dg-bogus "previous def" "foo prev def" { target *-*-* } 7 } */ -/* { dg-bogus "previous def" "quux prev def" { target *-*-* } 10 } */ -/* { dg-bogus "previous def" "quux prev def" { target *-*-* } 11 } */ -/* { dg-bogus "previous def" "f prev def" { target *-*-* } 14 } */ -/* { dg-bogus "previous def" "baz prev def" { target *-*-* } 17 } */ -/* { dg-bogus "previous def" "g prev def" { target *-*-* } 20 } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/redef2.c b/gcc/testsuite/gcc.dg/cpp/trad/redef2.c deleted file mode 100644 index 269a846266f..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/redef2.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Test for redefining traditional macros with significant differences. */ - -/* { dg-do preprocess } */ - -#define foo bar /* { dg-warning "previous def" "foo prev def" } */ -#define foo barr /* { dg-warning "redefined" "foo redefined" } */ - -#undef foo -#define foo bar /* { dg-warning "previous def" "foo prev def 2" } */ -#define foo() bar /* { dg-warning "redefined" "foo redefined 2" } */ - -#undef foo -#define foo() bar /* { dg-warning "previous def" "foo prev def" } */ -#define foo() barr /* { dg-warning "redefined" "foo redefined" } */ - -#define quux(thud) a thud b /* { dg-warning "previous def" "quux prev def" } */ -#define quux(thu) a thud b /* { dg-warning "redefined" "quux redefined" } */ - -#define bar(x, y) x+y /* { dg-warning "previous def" "bar prev def" } */ -#define bar(x, y) x+x /* { dg-warning "redefined" "bar redefined" } */ - -#define bat(x, y) x+y /* { dg-warning "previous def" "bat prev def" } */ -#define bat(x, y) x+ y /* { dg-warning "redefined" "bat redefined" } */ - -#define baz(x, y) x+y /* { dg-warning "previous def" "baz prev def" } */ -#define baz(x, y) x +y /* { dg-warning "redefined" "baz redefined" } */ - -#define f(x, y) "x y" /* { dg-warning "previous def" "f prev def" } */ -#define f(x, y) "x y" /* { dg-warning "redefined" "f redefined" } */ - -#define g(x, y) 'x' /* { dg-warning "previous def" "g prev def" } */ -#define g(x, y) ' x' /* { dg-warning "redefined" "g redefined" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/trad/strify.c b/gcc/testsuite/gcc.dg/cpp/trad/strify.c deleted file mode 100644 index 500ef1ea32f..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/strify.c +++ /dev/null @@ -1,17 +0,0 @@ -/* Test whether traditional stringify works. */ -/* { dg-do run } */ - -#define foo(a, b) c="a"; d="b"; - -extern void abort (); - -int main () -{ - char *c, *d; - - foo (p,q); - if (c[0] != 'p' || d[0] != 'q') - abort (); - - exit (0); -} diff --git a/gcc/testsuite/gcc.dg/cpp/trad/trad.exp b/gcc/testsuite/gcc.dg/cpp/trad/trad.exp deleted file mode 100644 index 60d90023007..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/trad.exp +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 1997, 2000 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -# GCC testsuite that uses the `dg.exp' driver. - -# There's a bunch of headers we need. -if [is_remote host] { - foreach header [glob -nocomplain $srcdir/$subdir/*.{h,def} ] { - remote_download host $header - } -} - -# Load support procs. -load_lib gcc-dg.exp - -# If a testcase doesn't have special options, use these. -global DEFAULT_TRADCPPFLAGS -if ![info exists DEFAULT_TRADCPPFLAGS] then { - set DEFAULT_TRADCPPFLAGS " -traditional-cpp" -} - -# Initialize `dg'. -dg-init - -# Main loop. -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ - "" $DEFAULT_TRADCPPFLAGS - -# All done. -dg-finish diff --git a/gcc/testsuite/gcc.dg/cpp/trad/uchar.c b/gcc/testsuite/gcc.dg/cpp/trad/uchar.c deleted file mode 100644 index 8ea54a1f43c..00000000000 --- a/gcc/testsuite/gcc.dg/cpp/trad/uchar.c +++ /dev/null @@ -1,8 +0,0 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. */ - -/* { dg-do preprocess } */ -/* { dg-options "-funsigned-char -fsigned-char -traditional-cpp" } */ - -#if defined (__CHAR_UNSIGNED__) -# error __CHAR_UNSIGNED__ defined -#endif diff --git a/gcc/testsuite/gcc.dg/tls/diag-1.c b/gcc/testsuite/gcc.dg/tls/diag-1.c deleted file mode 100644 index ae4f3d4a3c2..00000000000 --- a/gcc/testsuite/gcc.dg/tls/diag-1.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Valid __thread specifiers. */ - -__thread int g1; -extern __thread int g2; -static __thread int g3; - -void foo() -{ - extern __thread int l1; - static __thread int l2; -} diff --git a/gcc/testsuite/gcc.dg/tls/diag-2.c b/gcc/testsuite/gcc.dg/tls/diag-2.c deleted file mode 100644 index 4f2b90b8f7e..00000000000 --- a/gcc/testsuite/gcc.dg/tls/diag-2.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Invalid __thread specifiers. */ - -__thread extern int g1; /* { dg-error "`__thread' before `extern'" } */ -__thread static int g2; /* { dg-error "`__thread' before `static'" } */ -__thread __thread int g3; /* { dg-error "duplicate `__thread'" } */ -typedef __thread int g4; /* { dg-error "multiple storage classes" } */ - -void foo() -{ - __thread int l1; /* { dg-error "implicitly auto and declared `__thread'" } */ - auto __thread int l2; /* { dg-error "multiple storage classes" } */ - __thread extern int l3; /* { dg-error "`__thread' before `extern'" } */ - register __thread int l4; /* { dg-error "multiple storage classes" } */ -} - -__thread void f1 (); /* { dg-error "invalid storage class for function" } */ -extern __thread void f2 (); /* { dg-error "invalid storage class for function" } */ -static __thread void f3 (); /* { dg-error "invalid storage class for function" } */ -__thread void f4 () { } /* { dg-error "function definition declared `__thread'" } */ - -void bar(__thread int p1); /* { dg-error "storage class specified for parameter" } */ diff --git a/gcc/testsuite/gcc.dg/tls/diag-3.c b/gcc/testsuite/gcc.dg/tls/diag-3.c deleted file mode 100644 index 89d1bea8ede..00000000000 --- a/gcc/testsuite/gcc.dg/tls/diag-3.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Report invalid extern and __thread combinations. */ - -extern int j; /* { dg-error "previous declaration" } */ -__thread int j; /* { dg-error "follows non thread-local" } */ - -extern __thread int i; /* { dg-error "previous declaration" } */ -int i; /* { dg-error "follows thread-local" } */ - -extern __thread int k; /* This is fine. */ -__thread int k; diff --git a/gcc/testsuite/gcc.dg/tls/init-1.c b/gcc/testsuite/gcc.dg/tls/init-1.c deleted file mode 100644 index 97258643bf2..00000000000 --- a/gcc/testsuite/gcc.dg/tls/init-1.c +++ /dev/null @@ -1,4 +0,0 @@ -/* Invalid initializations. */ - -extern __thread int i; -int *p = &i; /* { dg-error "initializer element is not constant" } */ diff --git a/gcc/testsuite/gcc.dg/tls/opt-2.c b/gcc/testsuite/gcc.dg/tls/opt-2.c deleted file mode 100644 index 713fb7f360c..00000000000 --- a/gcc/testsuite/gcc.dg/tls/opt-2.c +++ /dev/null @@ -1,53 +0,0 @@ -/* This testcase generated invalid assembly on IA-32, - since %gs:0 memory load was not exposed to the compiler - as memory load and mem to mem moves are not possible - on IA-32. */ -/* { dg-do link } */ -/* { dg-options "-O2 -ftls-model=initial-exec" } */ -/* { dg-options "-O2 -ftls-model=initial-exec -march=i686" { target i?86-*-* } } */ - -__thread int thr; - -struct A -{ - unsigned int a, b, c, d, e; -}; - -int bar (int x, unsigned long y, void *z) -{ - return 0; -} - -int -foo (int x, int y, const struct A *z) -{ - struct A b; - int d; - - b = *z; - d = bar (x, y, &b); - if (d == 0 && y == 0x5402) - { - int e = thr; - d = bar (x, 0x5401, &b); - if (d) - { - thr = e; - d = 0; - } - else if ((z->c & 0600) != (b.c & 0600) - || ((z->c & 060) && ((z->c & 060) != (b.c & 060)))) - { - thr = 22; - d = -1; - } - } - - return d; -} - -int main (void) -{ - foo (1, 2, 0); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/tls/section-1.c b/gcc/testsuite/gcc.dg/tls/section-1.c deleted file mode 100644 index 741eadba536..00000000000 --- a/gcc/testsuite/gcc.dg/tls/section-1.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Verify that we get errors for trying to put TLS data in - sections which can't work. */ - -#define A(X) __attribute__((section(X))) - -__thread int i A("foo"); /* Ok */ - -__thread int j A(".data"); /* { dg-error "causes a section type conflict" "conflict with .data section" { xfail *-*-* } } */ - -int k A("bar"); -__thread int l A("bar"); /* { dg-error "causes a section type conflict" "conflict with user-defined section" } */ diff --git a/gcc/testsuite/gcc.dg/tls/tls.exp b/gcc/testsuite/gcc.dg/tls/tls.exp deleted file mode 100644 index 4c2627dbcf8..00000000000 --- a/gcc/testsuite/gcc.dg/tls/tls.exp +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (C) 2002 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -# GCC testsuite that uses the `dg.exp' driver. - -# Load support procs. -load_lib gcc-dg.exp - -# Test for thread-local data supported by the platform. If it -# isn't, everything will fail with the "not supported" message. - -set comp_output [gcc_target_compile \ - "$srcdir/$subdir/trivial.c" "trivial.S" assembly ""] -if { [string match "*not supported*" $comp_output] } { - return 0 -} - -# If a testcase doesn't have special options, use these. -global DEFAULT_CFLAGS -if ![info exists DEFAULT_CFLAGS] then { - set DEFAULT_CFLAGS " -ansi -pedantic-errors" -} - -# Initialize `dg'. -dg-init - -# Main loop. -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ - "" $DEFAULT_CFLAGS - -# All done. -dg-finish diff --git a/gcc/testsuite/gcc.dg/tls/trivial.c b/gcc/testsuite/gcc.dg/tls/trivial.c deleted file mode 100644 index 1fd70631f33..00000000000 --- a/gcc/testsuite/gcc.dg/tls/trivial.c +++ /dev/null @@ -1 +0,0 @@ -__thread int i; diff --git a/gcc/testsuite/gcc.dg/weak/typeof-2.c b/gcc/testsuite/gcc.dg/weak/typeof-2.c deleted file mode 100644 index 34d67b20fdc..00000000000 --- a/gcc/testsuite/gcc.dg/weak/typeof-2.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Test typeof with __asm redirection. */ -/* { dg-do compile } */ -/* { dg-options "-O2" } */ - -extern int foo1 (int x) __asm ("baz1"); -int bar1 (int x) { return x; } -extern __typeof (bar1) foo1 __attribute ((weak, alias ("bar1"))); - -extern int foo2 (int x) __attribute__ ((const)); -extern __typeof (foo2) foo2 __asm ("baz2"); -int bar2 (int x) -{ - return foo2 (x) + foo2 (x) + foo2 (x) + foo2 (x) + foo2 (x) + foo2 (x); -} - -extern int foo3 (int x); -extern __typeof (foo3) foo3 __asm ("baz3"); -int bar3 (int x) -{ - return foo3 (x) + foo3 (x) + foo3 (x) + foo3 (x) + foo3 (x) + foo3 (x); -} - -// { dg-final { scan-assembler-not "foo1" } } -// { dg-final { scan-assembler "baz1" } } -// { dg-final { scan-assembler-not "foo2" } } -// { dg-final { scan-assembler "baz2" } } -// { dg-final { scan-assembler-not "baz2.*baz2.*baz2.*baz2.*baz2.*baz2" } } -// { dg-final { scan-assembler-not "foo3" } } -// { dg-final { scan-assembler "baz3.*baz3.*baz3.*baz3.*baz3.*baz3" } } diff --git a/gcc/testsuite/gcc.dg/weak/weak-1.c b/gcc/testsuite/gcc.dg/weak/weak-1.c deleted file mode 100644 index 52d7230ed04..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak-1.c +++ /dev/null @@ -1,50 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-fno-common" } */ - -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?a" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?b" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?c" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?d" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?e" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?g" } } */ -/* { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]_?i" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?j" } } */ - -#pragma weak a -int a; - -int b; -#pragma weak b - -#pragma weak c -extern int c; -int c; - -extern int d; -#pragma weak d -int d; - -#pragma weak e -void e(void) { } - -#if 0 -/* This permutation is illegal. */ -void f(void) { } -#pragma weak f -#endif - -#pragma weak g -int g = 1; - -#if 0 -/* This permutation is illegal. */ -int h = 1; -#pragma weak h -#endif - -#pragma weak i -extern int i; - -#pragma weak j -extern int j; -int use_j() { return j; } diff --git a/gcc/testsuite/gcc.dg/weak/weak-2.c b/gcc/testsuite/gcc.dg/weak/weak-2.c deleted file mode 100644 index 37fa19a1a65..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak-2.c +++ /dev/null @@ -1,46 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-fno-common" } */ - -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1a" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1b" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1c" } } */ -/* { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]_?ffoo1d" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1e" } } */ - -/* test function addresses with #pragma weak */ - -#pragma weak ffoo1a -extern void * ffoo1a (void); -void * foo1a (void) -{ - return (void *)ffoo1a; -} - -extern void * ffoo1b (void); -#pragma weak ffoo1b -void * foo1b (void) -{ - return (void *)ffoo1b; -} - -extern void * ffoo1c (void); /* { dg-warning "applying #pragma weak" "applying #pragma weak" } */ -void * foo1c (void) -{ - return (void *)ffoo1c; -} -#pragma weak ffoo1c - - -int ffoo1d (void); -#pragma weak ffoo1d - - -extern void * ffoo1e (void); -#pragma weak ffoo1e -void * foo1e (void) -{ - if (ffoo1e) - ffoo1e (); - return 0; -} - diff --git a/gcc/testsuite/gcc.dg/weak/weak-3.c b/gcc/testsuite/gcc.dg/weak/weak-3.c deleted file mode 100644 index 47359edcd09..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak-3.c +++ /dev/null @@ -1,71 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-fno-common" } */ - -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1a" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1b" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1c" } } */ -/* { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]_?ffoo1d" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1e" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1f" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?ffoo1g" } } */ - -/* test function addresses with __attribute__((weak)) */ - -extern void * ffoo1a (void) __attribute__((weak)); -extern void * ffoo1a (void); -void * foo1a (void) -{ - return (void *)ffoo1a; -} - - -extern void * ffoo1b (void); -extern void * ffoo1b (void) __attribute__((weak)); -void * foo1b (void) -{ - return (void *)ffoo1b; -} - - -extern void * ffoo1c (void); -void * foo1c (void) -{ - return (void *)ffoo1c; -} -extern void * ffoo1c (void) __attribute__((weak)); /* { dg-warning "weak declaration" "weak declaration" } */ - - -int ffoo1d (void); -int ffoo1d (void) __attribute__((weak)); - - -extern void * ffoo1e (void); -extern void * ffoo1e (void) __attribute__((weak)); -void * foo1e (void) -{ - if (ffoo1e) - ffoo1e (); - return 0; -} - - -extern void * ffoo1f (void); -extern void * ffoox1f (void); -void * foo1f (void) -{ - if (ffoo1f) - ffoo1f (); - return 0; -} -extern void * ffoo1f (void) __attribute__((weak, alias ("ffoox1f"))); /* { dg-warning "weak declaration" "weak declaration" } */ - - -extern void * ffoo1g (void); -extern void * ffoox1g (void); -extern void * ffoo1g (void) __attribute__((weak, alias ("ffoox1g"))); -void * foo1g (void) -{ - if (ffoo1g) - ffoo1g (); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/weak/weak-4.c b/gcc/testsuite/gcc.dg/weak/weak-4.c deleted file mode 100644 index bd530ab5940..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak-4.c +++ /dev/null @@ -1,104 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-fno-common" } */ - -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1a" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1b" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1c" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1d" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1e" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1f" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1g" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1h" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1i" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1j" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1k" } } */ - -/* test variable addresses with #pragma weak */ - -#pragma weak vfoo1a -extern int vfoo1a; -void * foo1a (void) -{ - return (void *)&vfoo1a; -} - - -extern int vfoo1b; -#pragma weak vfoo1b -void * foo1b (void) -{ - return (void *)&vfoo1b; -} - - -extern int vfoo1c; /* { dg-warning "applying #pragma weak" "applying #pragma weak" } */ -void * foo1c (void) -{ - return (void *)&vfoo1c; -} -#pragma weak vfoo1c - - -#pragma weak vfoo1d -int vfoo1d; -void * foo1d (void) -{ - return (void *)&vfoo1d; -} - - -int vfoo1e; -#pragma weak vfoo1e -void * foo1e (void) -{ - return (void *)&vfoo1e; -} - - -int vfoo1f; -void * foo1f (void) -{ - return (void *)&vfoo1f; -} -#pragma weak vfoo1f - - -extern int vfoo1g; /* { dg-warning "applying #pragma weak" "applying #pragma weak" } */ -void * foo1g (void) -{ - return (void *)&vfoo1g; -} -#pragma weak vfoo1g -int vfoo1g; - - -extern int vfoo1h; -void * foo1h (void) -{ - return (void *)&vfoo1h; -} -int vfoo1h; -#pragma weak vfoo1h - - -int vfoo1i; -extern int vfoo1i; -void * foo1i (void) -{ - return (void *)&vfoo1i; -} -#pragma weak vfoo1i - - -extern int vfoo1j; -int vfoo1j; -void * foo1j (void) -{ - return (void *)&vfoo1j; -} -#pragma weak vfoo1j - - -#pragma weak vfoo1k -int vfoo1k = 1; - diff --git a/gcc/testsuite/gcc.dg/weak/weak-5.c b/gcc/testsuite/gcc.dg/weak/weak-5.c deleted file mode 100644 index c4f67e59c76..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak-5.c +++ /dev/null @@ -1,107 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-fno-common" } */ - -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1a" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1b" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1c" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1d" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1e" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1f" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1g" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1h" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1i" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1j" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1k" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?vfoo1l" } } */ - -/* test variable addresses with __attribute__ ((weak)) */ - -extern int vfoo1a __attribute__((weak)); -extern int vfoo1a; -void * foo1a (void) -{ - return (void *)&vfoo1a; -} - - -extern int vfoo1b; -extern int vfoo1b __attribute__((weak)); -void * foo1b (void) -{ - return (void *)&vfoo1b; -} - - -extern int vfoo1c; -void * foo1c (void) -{ - return (void *)&vfoo1c; -} -extern int vfoo1c __attribute__((weak)); /* { dg-warning "unspecified behavior" } */ - - -extern int vfoo1d __attribute__((weak)); -int vfoo1d; -void * foo1d (void) -{ - return (void *)&vfoo1d; -} - - -int vfoo1e; -extern int vfoo1e __attribute__((weak)); -void * foo1e (void) -{ - return (void *)&vfoo1e; -} - - -int vfoo1f; -void * foo1f (void) -{ - return (void *)&vfoo1f; -} -extern int vfoo1f __attribute__((weak)); /* { dg-warning "unspecified behavior" } */ - - -extern int vfoo1g; -void * foo1g (void) -{ - return (void *)&vfoo1g; -} -int vfoo1g __attribute__((weak)); /* { dg-warning "unspecified behavior" } */ - - -extern int vfoo1h __attribute__((weak)); -void * foo1h (void) -{ - return (void *)&vfoo1h; -} -extern int vfoo1h __attribute__((weak)); -int vfoo1h; - - -extern int vfoo1i __attribute__((weak)); -void * foo1i (void) -{ - return (void *)&vfoo1i; -} -extern int vfoo1i __attribute__((weak)); -extern int vfoo1i; - - -extern int vfoo1j __attribute__((weak)); -void * foo1j (void) -{ - return (void *)&vfoo1j; -} -extern int vfoo1j; -extern int vfoo1j __attribute__((weak)); - - -extern int vfoo1k __attribute__((weak)); -int vfoo1k = 1; - - -int vfoox1l = 1; -extern int vfoo1l __attribute__((weak, alias ("vfoox1l"))); diff --git a/gcc/testsuite/gcc.dg/weak/weak-6.c b/gcc/testsuite/gcc.dg/weak/weak-6.c deleted file mode 100644 index 8f88a675d31..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak-6.c +++ /dev/null @@ -1,6 +0,0 @@ -/* { dg-do compile } */ - -extern void * foo (void); -void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */ - -#pragma weak foo diff --git a/gcc/testsuite/gcc.dg/weak/weak-7.c b/gcc/testsuite/gcc.dg/weak/weak-7.c deleted file mode 100644 index 64d6155a890..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak-7.c +++ /dev/null @@ -1,6 +0,0 @@ -/* { dg-do compile } */ - -extern void * foo (void); -void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */ - -extern void * foo (void) __attribute__((weak)); diff --git a/gcc/testsuite/gcc.dg/weak/weak-8.c b/gcc/testsuite/gcc.dg/weak/weak-8.c deleted file mode 100644 index 6e9c267bd21..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak-8.c +++ /dev/null @@ -1,7 +0,0 @@ -/* { dg-do assemble } */ - -__attribute__ ((weak)) int i; - -int f() { - return i; -} diff --git a/gcc/testsuite/gcc.dg/weak/weak-9.c b/gcc/testsuite/gcc.dg/weak/weak-9.c deleted file mode 100644 index e5cbdb8bc87..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak-9.c +++ /dev/null @@ -1,20 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-fno-common" } */ - -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?f1" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?f2" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?f3" } } */ -/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?f4" } } */ -/* { dg-final { scan-assembler "notf1" } } */ -/* { dg-final { scan-assembler "notf2" } } */ -/* { dg-final { scan-assembler "notf3" } } */ -/* { dg-final { scan-assembler "notf4" } } */ - -void f1() __attribute__((weak, alias("notf1"))); -void f2() __attribute__((alias("notf2"), weak)); - -#pragma weak f3=notf3 -void f3(); - -void f4(); -#pragma weak f4=notf4 diff --git a/gcc/testsuite/gcc.dg/weak/weak.exp b/gcc/testsuite/gcc.dg/weak/weak.exp deleted file mode 100644 index 595ca92c005..00000000000 --- a/gcc/testsuite/gcc.dg/weak/weak.exp +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) 1997 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -# GCC testsuite that uses the `dg.exp' driver. - -# Load support procs. -load_lib gcc-dg.exp - -# If a testcase doesn't have special options, use these. -global DEFAULT_CFLAGS -if ![info exists DEFAULT_CFLAGS] then { - set DEFAULT_CFLAGS " -ansi -pedantic-errors" -} - -if { [ check_weak_available ] == 1 } { - - dg-init - - dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ - "" $DEFAULT_CFLAGS - - dg-finish - -} elseif { [ check_weak_available ] == 0 } { - unsupported "gcc.dg/weak" -} else { - unresolved "gcc.dg/weak" -} diff --git a/gcc/testsuite/treelang/ChangeLog b/gcc/testsuite/treelang/ChangeLog deleted file mode 100644 index 09a69046ad4..00000000000 --- a/gcc/testsuite/treelang/ChangeLog +++ /dev/null @@ -1,49 +0,0 @@ -2002-05-07 Tim Josling - - * Makefile.in: Fix copyright - * a01gcci01.c: Ditto - * a01gcci01.tree: Ditto - * treetests.exp: Ditto - -2002-04-13 Tim Josling - - * treetree.c (tree_code_create_function_initial) - Remove duplicate call to layout_decl - -2001-12-02 Tim Josling - - * Make-lang.in - Ensure directory is built during install (installdirs dependency) - - * lex.l - Work around poisoned malloc (undef IN_GCC) - Remove fake definition of tree. - - * parse.y - Work around poisoned malloc (undef IN_GCC) - - * tree1.c - New front end interface. - (top level) New structure lang_hooks. - (tree_post_options) Remove. - errorcount now a macro so do not define it. - current_nesting_level => work_nesting_level due to clash. - - * treelang.h - errorcount now a macro so do not reference it. - - * treetree.c - Replace NULL_PTR by NULL. - (tree_code_get_expression) Mark op3 unused. - Do not init builtins. - -2001-06-11 Tim Josling - - * treelang.exp (global) remove COBOL specific code. - -2001-05-24 Tim Josling - - Created this directory and its tests. All derived from the cobol - test swamp which was also all written by me. - - diff --git a/gcc/testsuite/treelang/Makefile.in b/gcc/testsuite/treelang/Makefile.in deleted file mode 100644 index e74b8bdf10e..00000000000 --- a/gcc/testsuite/treelang/Makefile.in +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2001, 2002 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software -# Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. -# -# In other words, you are welcome to use, share and improve this program. -# You are forbidden to forbid anyone else to use, share and improve -# what you give them. Help stamp out software-hoarding! -# -# -all: - -clean: - -rm -f *.o *.diff *~ *.bad core *.x - -distclean: clean - -rm -f Makefile config.status diff --git a/gcc/testsuite/treelang/a01gcci01.c b/gcc/testsuite/treelang/a01gcci01.c deleted file mode 100644 index 4d857fac9cb..00000000000 --- a/gcc/testsuite/treelang/a01gcci01.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Driver for treelang test pgm */ - -/* - - Copyright (C) 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! -*/ - -int add(int, int); -int subtract(int, int); -int first_nonzero(int, int); - -int -main (int argc, char *argv[]) -{ - printf("2:%d\n", add(1,1)); - printf("7:%d\n", add(3,4)); - printf("-1:%d\n", subtract(3,4)); - printf("1:%d\n", subtract(2,1)); - printf("3:%d\n", first_nonzero(0,3)); - printf("0:%d\n", first_nonzero(0,0)); - printf("1:%d\n", first_nonzero(1,0)); - printf("15:%d\n", double_plus_one(7)); - return 0; -} diff --git a/gcc/testsuite/treelang/a01gcci01.tree b/gcc/testsuite/treelang/a01gcci01.tree deleted file mode 100644 index 81d130999a1..00000000000 --- a/gcc/testsuite/treelang/a01gcci01.tree +++ /dev/null @@ -1,60 +0,0 @@ -// -*- c -*- c mode in emacs - -// Copyright (C) 2001, 2002 Free Software Foundation, Inc. -// This program is free software; you can redistribute it and/or modify it -// under the terms of the GNU General Public License as published by the -// Free Software Foundation; either version 2, or (at your option) any -// later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software -// Foundation, 59 Temple Place - Suite 330, -// Boston, MA 02111-1307, USA. -// -// In other words, you are welcome to use, share and improve this program. -// You are forbidden to forbid anyone else to use, share and improve -// what you give them. Help stamp out software-hoarding! - - -external_definition int add(int arg1, int arg2); -external_definition int subtract(int arg3, int arg4); -external_definition int first_nonzero(int arg5, int arg6); -external_definition int double_plus_one(int arg7); - -add -{ - return arg1 + arg2; -} - - -subtract -{ - return arg3 - arg4; -} - -double_plus_one -{ - automatic int aaa; - aaa=add(arg7, arg7); - aaa=add(aaa, aaa); - aaa=subtract(subtract(aaa, arg7), arg7) + 1; - return aaa; -} - -first_nonzero -{ - if (arg5) - { - return arg5; - } - else - { - } - return arg6; -} - diff --git a/gcc/testsuite/treelang/a01gcco01runpgm b/gcc/testsuite/treelang/a01gcco01runpgm deleted file mode 100644 index 3c2c743c77d..00000000000 --- a/gcc/testsuite/treelang/a01gcco01runpgm +++ /dev/null @@ -1,8 +0,0 @@ -2:2 -7:7 --1:-1 -1:1 -3:3 -0:0 -1:1 -15:15 diff --git a/gcc/testsuite/treelang/treetests.exp b/gcc/testsuite/treelang/treetests.exp deleted file mode 100644 index e5c2a85989f..00000000000 --- a/gcc/testsuite/treelang/treetests.exp +++ /dev/null @@ -1,307 +0,0 @@ - -# Tests for treelang; run from gcc/treelang/Make-lang.in => gcc/Makefile -# find ttt for the actual tests - -# Copyright (C) 1999, 2000, 2001, 2002 by The Free Software Foundation - -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software -# Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. -# -# In other words, you are welcome to use, share and improve this program. -# You are forbidden to forbid anyone else to use, share and improve -# what you give them. Help stamp out software-hoarding! - -# Check the pgm is even there and set up the basics -proc init_utility {pgm} { - global transform - global pgm_actual - global pgm_base - global fix_progname - global path -# maybe add "X" to front of fail to say it is an expected failure - global X - - set pgm_base ${pgm} - set pgm_actual ${pgm} - - if { ${transform} != "s,x,x,"} { - verbose "1. program name was ${pgm}" 2 - set sed_rc [catch {eval exec sed -e "${transform}" <<${pgm} } catch_res] - if { ${sed_rc} != "0" } { - verbose "2. Program name transform failed rc=${sed_rc} stat=${catch_res}" 1 - ${X}fail "${pgm} sed" - return 0 - } - set pgm_actual ${catch_res} - verbose "3. program name after transformation is ${pgm_actual}" 2 - } - - set which_rc [catch {exec which ${pgm_actual}} stat] - if { ${which_rc} != "0" } { - verbose "4. ${pgm_base} cannot be found rc=${which_rc} stat=${stat}" 1 - ${X}fail "${pgm} = ${pgm_actual} not found in path (${path})" - return 0 - } - set fix_progname "s,${pgm_actual},${pgm_base}," - verbose "5. fix program name value = ${fix_progname}" 4 - return 1 -} - -#run pgm, option to remove file names from outputs -proc run3 {srcdd testdd parms group_nbr item_nbr nonzero_RC_expected check_file sanitize_output tree1 pipe} { - - global transform - global pgm_actual - global pgm_base - global fix_progname - global X - global extras - - set error_msg 0 - set basefile "a${group_nbr}${pgm_base}.out${item_nbr}" - set infile "" - set outfile "" - set suffix "" - set temp_extras "-O3 " - set real_pgm_actual ${pgm_actual} - - if {${tree1} > 0} { - if {"${pgm_actual}" == "gcc"} { - set real_pgm_actual "xgcc" - set temp_extras "${extras}" - } - set infile "${srcdd}/a${group_nbr}${pgm_base}i${item_nbr}.tree" - set mainfile "${srcdd}/a${group_nbr}${pgm_base}i${item_nbr}.c" - set outfile "-o ${testdd}/a${group_nbr}${pgm_base}o${item_nbr}${suffix}" - } - - verbose "6. exec ${real_pgm_actual} ${temp_extras} ${parms} ${mainfile} ${infile} ${outfile} >${testdd}/${basefile} 2>${testdd}/${basefile}err" 2 - set run_rc [catch {eval exec ${real_pgm_actual} ${temp_extras} ${parms} ${mainfile} ${infile} ${outfile} >${testdd}/${basefile} 2>${testdd}/${basefile}err} catch_res] - if {${run_rc} == 1} { - if {${nonzero_RC_expected} == 0} { - verbose "7. ${real_pgm_actual} ${group_nbr} ${item_nbr} failed due to rc=${run_rc} status=${catch_res}" 1 - ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} rc!=0" - return - } - } else { - if {${nonzero_RC_expected} == 1} { - verbose "8. ${pgm_actual} ${group_nbr} ${item_nbr} failed - did not produce nonzero return code as expected rc=${run_rc} status=${catch_res}" 1 - ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} rc=0" - return - } - } - -# change the filenames to (file) in output if needed to allow testing - set checkfile1 "${srcdd}/${basefile}" - set checkfile2 "${testdd}/${basefile}" - if {${sanitize_output} != 0} { - set oldcheckfile1 "${checkfile1}" - set oldcheckfile2 "${checkfile2}" - set checkfile1 "${testdd}/${basefile}.test.nofilename" - set checkfile2 "${testdd}/${basefile}.run.nofilename" - set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile1} >${checkfile1}} catch_res] - if {${run_rc} == 1} { - verbose "9. sed to cleanup filenames (std 1) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1 - if {${error_msg} == 0} { - set error_msg "9. sed to cleanup filenames (std 1) in pgm output failed due to rc=${run_rc} status=${catch_res}" - } - } - set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile2} | sed -e "${fix_progname}" >${checkfile2}} catch_res] - if {${run_rc} == 1} { - verbose "10. sed to cleanup filenames (std 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1 - if {${error_msg} == 0} { - set error_msg "10. sed to cleanup filenames (std 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" - } - } - } - set diff [diff ${checkfile1} ${checkfile2}] - if {${diff} != 1} { - verbose "11. ${pgm_actual} ${group_nbr} ${item_nbr} diff stdout failed rc=${diff}" 1 - if {${error_msg} == 0} { - set error_msg "11. ${pgm_actual} ${group_nbr} ${item_nbr} diff stdout failed rc=${diff}" - } - } - - set checkfile1 "${srcdd}/${basefile}err" - set checkfile2 "${testdd}/${basefile}err" - if {${sanitize_output} != 0} { - set oldcheckfile1 "${checkfile1}" - set oldcheckfile2 "${checkfile2}" - set checkfile1 "${testdd}/${basefile}err.test.nofilename" - set checkfile2 "${testdd}/${basefile}err.run.nofilename" - set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile1} >${checkfile1}} catch_res] - if {${run_rc} == 1} { - verbose "12. sed to cleanup filenames (err 1) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1 - if {${error_msg} == 0} { - set error_msg "12. sed to cleanup filenames (err 1) in pgm output failed due to rc=${run_rc} status=${catch_res}" - } - } - set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile2} | sed -e "${fix_progname}" >${checkfile2}} catch_res] - if {${run_rc} == 1} { - verbose "13. sed to cleanup filenames (err 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1 - if {${error_msg} == 0} { - set error_msg "13. sed to cleanup filenames (err 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" - } - } - } - set diff [diff ${checkfile1} ${checkfile2}] - if {${diff} != 1} { - verbose "14. ${pgm_actual} ${group_nbr} ${item_nbr} diff stderr failed rc=${diff}" 1 - if {${error_msg} == 0} { - set error_msg "14. ${pgm_actual} ${group_nbr} ${item_nbr} diff stderr failed rc=${diff}" - } - } - - if {${check_file} >0} { - if {${tree1} == 0} { - set checkfile1 "${srcdd}/${basefile}file" - set checkfile2 "${testdd}/${basefile}file" - if {${sanitize_output} != 0} { - set oldcheckfile1 "${checkfile1}" - set oldcheckfile2 "${checkfile2}" - set checkfile1 "${testdd}/${basefile}file.test.nofilename" - set checkfile2 "${testdd}/${basefile}file.run.nofilename" - set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile1} >${checkfile1}} catch_res] - if {${run_rc} == 1} { - verbose "15. sed to cleanup filenames (err 1) in pgm stdout failed due to rc=${run_rc} status=${catch_res}" 1 - if {${error_msg} == 0} { - set error_msg "15. sed to cleanup filenames (err 1) in pgm stdout failed due to rc=${run_rc} status=${catch_res}" - } - } - set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile2} | sed -e "${fix_progname}" >${checkfile2}} catch_res] - if {${run_rc} == 1} { - verbose "16. sed to cleanup filenames (err 2) in pgm stdout failed due to rc=${run_rc} status=${catch_res}" 1 - if {${error_msg} == 0} { - set error_msg "16. sed to cleanup filenames (err 2) in pgm stdout failed due to rc=${run_rc} status=${catch_res}" - } - } - } - set diff [diff ${checkfile1} ${checkfile2}] - if {${diff} != 1} { - verbose "17. ${pgm_actual} ${group_nbr} ${item_nbr} diff stdout file failed rc=${diff}" 1 - if {${error_msg} == 0} { - set error_msg "17. ${pgm_actual} ${group_nbr} ${item_nbr} diff stdout file failed rc=${diff}" - } - } - } - } - - if {${check_file} >1} { - if {${tree1} == 0} { - set checkfile1 "${srcdd}/${outfile}" - set checkfile2 "${testdd}/${outfile}" - if {${sanitize_output} != 0} { - set oldcheckfile1 "${checkfile1}" - set oldcheckfile2 "${checkfile2}" - set checkfile1 "${testdd}/${basefile}out.test.nofilename" - set checkfile2 "${testdd}/${basefile}out.run.nofilename" - set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile1} >${checkfile1}} catch_res] - if {${run_rc} == 1} { - verbose "18. sed to cleanup filenames (err 1) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1 - if {${error_msg} == 0} { - set error_msg "18. sed to cleanup filenames (err 1) in pgm output failed due to rc=${run_rc} status=${catch_res}" - } - } - set run_rc [catch {eval exec sed -f ${srcdd}/filefix.sed <${oldcheckfile2} | sed -e "${fix_progname}" >${checkfile2}} catch_res] - if {${run_rc} == 1} { - verbose "19. sed to cleanup filenames (err 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" 1 - if {${error_msg} == 0} { - set error_msg "19. sed to cleanup filenames (err 2) in pgm output failed due to rc=${run_rc} status=${catch_res}" - } - } - } - set diff [diff ${checkfile1} ${checkfile2}] - if {${diff} != 1} { - verbose "20. ${pgm_actual} ${group_nbr} ${item_nbr} diff output file failed rc=${diff}" 1 - if {${error_msg} == 0} { - set error_msg "20. ${pgm_actual} ${group_nbr} ${item_nbr} diff output file failed rc=${diff}" - } - } - } - } - - if {${check_file} >2} { - set outfile "a${group_nbr}${pgm_base}o${item_nbr}${suffix}" - set pgmrun "${testdd}/a${group_nbr}${pgm_base}o${item_nbr}${suffix}" - set checkfile1 "${srcdd}/${outfile}runpgm" - set checkfile2 "${testdd}/${outfile}runpgm" - verbose "21. exec ${pgmrun} >${checkfile2} 2>${checkfile2}err" 2 - set run_rc [catch {eval exec ${pgmrun} >${checkfile2} 2>${checkfile2}err} catch_res] - if {${run_rc} == 1} { - if {${nonzero_RC_expected} == 0} { - verbose "22. ${pgm_actual} ${group_nbr} ${item_nbr} failed due to rc=${run_rc} status=${catch_res}" 1 - ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} run" - return - } - } else { - if {${nonzero_RC_expected} == 1} { - verbose "23. ${pgm_actual} ${group_nbr} ${item_nbr} failed - did not produce nonzero return code as expected rc=${run_rc} status=${catch_res}" 1 - ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} run" - return - } - } - set diff [diff ${checkfile1} ${checkfile2}] - if {${diff} != 1} { - verbose "24. ${pgm_actual} ${group_nbr} ${item_nbr} diff run output file failed rc=${diff}" 1 - if {${error_msg} == 0} { - set error_msg "24. ${pgm_actual} ${group_nbr} ${item_nbr} diff run output file failed rc=${diff}" - } - } - set diff [diff ${checkfile1}err ${checkfile2}err] - if {${diff} != 1} { - verbose "25. ${pgm_actual} ${group_nbr} ${item_nbr} diff run stderr file failed rc=${diff}" 1 - if {${error_msg} == 0} { - set error_msg "25. ${pgm_actual} ${group_nbr} ${item_nbr} diff run stderr file failed rc=${diff}" - } - } - } - - if {${error_msg}>0} { - ${X}fail "${pgm_base} ${group_nbr} ${item_nbr} fail code=${error_msg}" - } else { - pass "${pgm_base} ${group_nbr} ${item_nbr}" - } - return -} - -set extras "$env(gcc_extras)" -set path $env(PATH) -set transform $env(TRANSFORM) -set srcdir $env(srcdir) -verbose "source directory ${srcdir}\n" 2 -verbose "transform ${transform}\n" 2 -set sourcedir "${srcdir}/testsuite/treelang" -set testdir "treelang" - -set pgm_actual "" - -# srcdd testdd parms group_nbr item_nbr nonzero_RC_expected check_file sanitize_output tree1 - -# ttt - -#GCC - main C compiler tests via GCC - -set X "" - -set check_rc [init_utility "gcc"] - -if {${check_rc} == 1} { -# -#set X "x" -set X "" - run3 "${sourcedir}" "${testdir}" " -g -O3 " 01 01 0 3 0 1 0 -set X "" -} - diff --git a/gcc/treelang/.cvsignore b/gcc/treelang/.cvsignore deleted file mode 100644 index 6e2fad745bf..00000000000 --- a/gcc/treelang/.cvsignore +++ /dev/null @@ -1,5 +0,0 @@ -lex.c -parse.c -parse.h -parse.output -*.info* diff --git a/gcc/treelang/ChangeLog b/gcc/treelang/ChangeLog deleted file mode 100644 index 138a96dd8fa..00000000000 --- a/gcc/treelang/ChangeLog +++ /dev/null @@ -1,164 +0,0 @@ -2002-09-09 Tim Josling - - * treetree.c (objc_is_id): New. - -2002-08-16 Tim Josling - - Remove variables and functions now defined elsewhere. - - * treetree.c (maybe_objc_comptypes): Remove. - (warn_format, warn_format_y2k, warn_format_extra_args, - warn_format_nonliteral, warn_format_security, - warn_format_zero_length): Remove. - (maybe_building_objc_message_expr): Remove. - (cpp_post_options): Remove. - (maybe_objc_check_decl): Remove. - (integer_types): Remove. - - -2002-08-13 Neil Booth - - * treelang.c: Remove cpp_post_options. - -2002-08-13 Tim Josling - - * parse.y: Provide dummy definition of rtx for use by config.h. - * Make-lang.in (treetree.o): Remove dependency on non-existent - gt-treelang-treelang.h. - (gt-treelang-treelang.h): Remove. - -2002-08-08 Nathan Sidwell - - * treelang/Make-lang.in (treelang.mostlyclean): Remove coverage files. - -2002-07-11 Tim Josling - - Remove front end hard coding from gengtype.c. - - * config-lang.in (gtfiles): Add files needed for this front - end. - -2002-07-09 Tim Josling - - Support new attributes regime (Fix for PR c++/7099). - - * treetree.c (handle_format_attribute): Return NULL_TREE instead - of aborting. - (top level): Define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE - LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE - LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES as the standard C routines. - -2002-06-21 Andreas Jaeger - - * Make-lang.in (treelang/tree1.o, treelang/treetree.o, - treelang/parse.o, treelang/lex.o): Add dependency on $(CONFIG_H). - -2002-06-19 Paolo Bonzini - - * lex.l (yyparse) Return AUTOMATIC for 'automatic' token rather - than STATIC. - -2002-06-10 Tim Josling - - Cleanup - - * Make-lang.in (check-treelang). Add. Remove direct dependency of - 'check' on 'treelang.check' as redundant. - - PCH Garbage collection regime (gengtypes.c) phase 1. - - * Make-lang.in (treelang/tree1.o). Depend on gt-treelang-tree1.h - gt-treelang-treelang.h gtype-treelang.h. - (gt-treelang-tree1.h) Depend on s-gtype. - (gt-treelang-treelang.h) Depend on s-gtype. - (gtype-treelang.h) Depend on s-gtype. - - * config-lang.in (gtfiles): Define. - - * lex.l (main): Remove '#if 0' dead code. - (main): Move undef of IN_GCC so define of tree typedef works. - (all): Replace token and production by prod_token_parm_item. - - * parse.y - (all): Replace token and production by prod_token_parm_item. - - * tree1.c (main): Remove include of "output.h". - (symbol_table): Add GTY details. - (symbol_table_ggc): Remove. - (treelang_init): Remove root definitions for garbage collection. - (mark_production_used): Remove. - (mark_token_used): Remove. - (main, at end): include generated garage collection routines. - - * treelang.h (category_enum ): Add parameter_category. - (all): Replace token and production and parameters by union - prod_token_parm_item containing production_part, token_part, - parameter_part. - (STATIC_STORAGE AUTOMATIC_STORAGE EXTERNAL_REFERENCE_STORAGE - EXTERNAL_DEFINITION_STORAGE SIGNED_CHAR UNSIGNED_CHAR SIGNED_INT - UNSIGNED_INT VOID_TYPE EXP_PLUS EXP_REFERENCE EXP_ASSIGN - EXP_FUNCTION_INVOCATION EXP_MINUS EXP_EQUALS): Move here from - treetree.h. - - * treetree.c - (tm_p.h): Do not include. - (ansidecl.h): Move include after config.h. - (treelang.h): Include it. - (ADDROOT): Remove. - (all): Replace token, production and parameter by prod_token_parm_item. - (tree_parameter_list): Move to treelang.h as part of - prod_token_parm_item. - (STATIC_STORAGE AUTOMATIC_STORAGE EXTERNAL_REFERENCE_STORAGE - EXTERNAL_DEFINITION_STORAGE SIGNED_CHAR UNSIGNED_CHAR SIGNED_INT - UNSIGNED_INT VOID_TYPE EXP_PLUS EXP_REFERENCE EXP_ASSIGN - EXP_FUNCTION_INVOCATION EXP_MINUS EXP_EQUALS): Move from here to - treelang.h. - -2002-05-19 Tim Josling - - * treetree.c (warn_format_zero_length): Add. - -2002-05-14 Tim Josling - - * Make-lang.in: Fix build for .info files, add target for manpages. - A bug report and a suggested patch came from Magnus Fromreide - . - -2002-05-16 Rainer Orth - - * Make-lang.in: Allow for PWDCMD to override hardcoded pwd. - -2002-05-11 Tim Josling - - * treetree.c: (cpp_define) Add. - (cpp_get_callbacks) Add. - -2002-05-07 Tim Josling - - * treetree.c: (cpp_get_options) Add. - -2002-05-06 Tim Josling - - * .cvsignore: Add. - -2002-05-05 Tim Josling - - * Updated for gcc3.2 experimental. Major changes throughout. - -2002-03-31 Tim Josling - - * Make-lang.in: Changes so build and check work more reliably - -2001-07-30 Tim Josling - - * root.texi: remove - * treelang.texi: updates based on feedback - -2001-06-11 Tim Josling - - * all (all) Revamp code to conform to GCC coding standards, fix - typos in texi files. - -2001-05-11 Tim Josling - - Create the new language. diff --git a/gcc/treelang/Make-lang.in b/gcc/treelang/Make-lang.in deleted file mode 100644 index a1337672872..00000000000 --- a/gcc/treelang/Make-lang.in +++ /dev/null @@ -1,308 +0,0 @@ -# Top level makefile fragment for TREELANG For GCC. -*- makefile -*- - -# Copyright (C) 1994, 1995, 1997, 1998, 1999 2000, 2001, 2002 Free -# Software Foundation, Inc. - -#This file is part of GCC. - -#GCC is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2, or (at your option) -#any later version. - -#GCC is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with GCC; see the file COPYING. If not, write to -#the Free Software Foundation, 59 Temple Place - Suite 330, -#Boston, MA 02111-1307, USA. - -# This file provides the language dependent support in the main Makefile. -# Each language makefile fragment must provide the following targets: -# -# foo.all.build, foo.all.cross, foo.start.encap, foo.rest.encap, -# foo.info, foo.dvi, -# foo.install-normal, foo.install-common, foo.install-info, foo.install-man, -# foo.uninstall, foo.distdir, -# foo.mostlyclean, foo.clean, foo.distclean, foo.extraclean, -# foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4 -# -# where `foo' is the name of the language. -# -# It should also provide rules for: -# -# - making any compiler driver (eg: GCC) -# - the compiler proper (eg: treelang) -# - define the names for selecting the language in LANGUAGES. -# - -## note program-prefix and program-suffix options are not supported -## just program_transform_name which is a sed script to transform the -## names - -TREELANGSED = sed -TREELANGSEDFLAGS = -n - -# back end compiler libraries etc -TREE_BE_LIBS = $(BACKEND) $(LIBIBERTY) $(INTLLIBS) $(LIBS) $(LIBDEPS) -GCC_EXTRAS = -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include - -# ./xgcc is the just built compiler. See GCC_FOR_TARGET in the GCC Makefile.in. -# If this can't be found, you probably have not done a bootstrap of GCC, -# which you need to do. - -# GCC_FOR_TREELANG = ./xgcc $(GCC_EXTRAS) - -TREE_GENERATED = $(srcdir)/treelang/lex.c $(srcdir)/treelang/parse.c\ - $(srcdir)/treelang/parse.h $(srcdir)/treelang/parse.output $(srcdir)/treelang/TAGS - -TREE_SOURCE = ${srcdir}/treelang/parse.y ${srcdir}/treelang/lex.l ${srcdir}/treelang/tree1.c ${srcdir}/treelang/treelang.h ${srcdir}/treelang/treetree.c $(srcdir)/treelang/treetree.h - -TREE_EXES = tree1$(exeext) - -#no -Wtraditional warnings, allow long long -treelang-warn = $(LOOSE_WARN) -pedantic -Wno-long-long -Wmissing-prototypes -Wmissing-declarations - -# -# Define the names for selecting treelang in LANGUAGES. - -.phony: treelang TREELANG - -treelang TREELANG:treelang.done - -treelang.done: tree1$(exeext) - $(STAMP) treelang.done - -# no preprocessor - -# core compiler -tree1$(exeext): treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o\ - $(TREE_BE_LIBS) c-convert.o c-typeck.o c-common.o c-decl.o attribs.o - $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \ - treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o c-convert.o\ - c-typeck.o c-common.o c-decl.o attribs.o $(TREE_BE_LIBS) - -# -# Compiling object files from source files. - -# object file makes - -treelang/tree1.o: $(srcdir)/treelang/tree1.c $(srcdir)/treelang/treelang.h \ - $(srcdir)/treelang/parse.h $(CONFIG_H) \ - gt-treelang-tree1.h gtype-treelang.h - $(CC) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< - -treelang/treetree.o: $(srcdir)/treelang/treetree.c $(srcdir)/treelang/treetree.h \ - $(CONFIG_H) - $(CC) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< - -treelang/parse.o: $(srcdir)/treelang/parse.c $(srcdir)/treelang/treelang.h \ - $(srcdir)/treelang/treetree.h $(CONFIG_H) - $(CC) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< - -treelang/lex.o: $(srcdir)/treelang/lex.c $(srcdir)/treelang/parse.h \ - $(srcdir)/treelang/treelang.h $(CONFIG_H) - $(CC) -o $@ -c $(ALL_CFLAGS) $(INCLUDES) $< - -# generated files the files from lex and yacc are put into the source -# directory in case someone wants to build but does not have -# lex/yacc - -$(srcdir)/treelang/lex.c: $(srcdir)/treelang/lex.l - $(LEX) $(LEXFLAGS) -o$(srcdir)/treelang/lex.c $(srcdir)/treelang/lex.l - -$(srcdir)/treelang/parse.c $(srcdir)/treelang/parse.h: $(srcdir)/treelang/parse.y - $(BISON) $(BISONFLAGS) -v $(srcdir)/treelang/parse.y\ - --output=$(srcdir)/treelang/parse.c --defines -# -v - -gt-treelang-tree1.h gtype-treelang.h : s-gtype; @true - -# -# Build hooks: - -treelang.all.build: treelang -treelang.all.cross: - _error_not_here_yet - havent even thought about it - it may even work - -treelang.start.encap: -treelang.rest.encap: - -.phony:treelang.info -treelang.info: $(srcdir)/treelang/treelang.info - -$(srcdir)/treelang/treelang.info: $(srcdir)/treelang/treelang.texi - cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -Idoc/include \ - -o treelang/treelang.info treelang/treelang.texi - -treelang.dvi: $(srcdir)/treelang/treelang.texi - TEXINPUTS=$(srcdir)/treelang:$(srcdir):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/treelang/treelang.texi; \ - texindex treelang.??; \ - TEXINPUTS=$(srcdir)/treelang:$(srcdir):$$TEXINPUTS $(TEXI2DVI) $(srcdir)/treelang/treelang.texi; \ - mv treelang.dvi treelang; - -treelang.generated-manpages: - -# -# Install hooks: - -# Nothing to do here. -treelang.install-normal: treelang.install.common - -# Install -.phony:treelang.install.common -.phony:treelang.install - -treelang.install treelang.install.common treelang.install-common: treelang.install.common.done - -treelang.install.common.done: installdirs treelang.done - for name in $(TREE_EXES); \ - do \ - if [ -f $$name ] ; then \ - name2="`echo \`basename $$name\` | sed -e '$(program_transform_name)' `"; \ - rm -f $(bindir)/$$name2$(exeext); \ - echo $(INSTALL_PROGRAM) $$name$(exeext) $(bindir)/$$name2$(exeext); \ - $(INSTALL_PROGRAM) $$name$(exeext) $(bindir)/$$name2$(exeext); \ - chmod a+x $(bindir)/$$name2$(exeext); \ - fi ; \ - done - $(STAMP) treelang.install.common.done - -treelang.install-info: $(srcdir)/treelang/treelang.info - for name in $(srcdir)/treelang/treelang.info; \ - do \ - if [ -f $$name ] ; then \ - name2="`echo \`basename $$name\` | sed -e '$(program_transform_name)' `"; \ - rm -f $(libsubdir)/$$name2$(exeext); \ - $(INSTALL_PROGRAM) $$name$(exeext) $(libsubdir)/$$name2$(exeext); \ - chmod a+x $(libsubdir)/$$name2$(exeext); \ - fi ; \ - done - -treelang.install-man: - -treelang.uninstall: - for name in $(TREE_EXES); \ - do \ - echo $$name; \ - name2="`echo $$name | sed -e '$(program_transform_name)' `"; \ - echo becomes $$name2; \ - echo -rm -rf $(bindir)/$$name2$(exeext); \ - rm -rf $(bindir)/$$name2$(exeext); \ - done - -rm treelang.install.common.done - -# -# Clean hooks: -# A lot of the ancillary files are deleted by the main makefile. -# We just have to delete files specific to us. - -treelang.mostlyclean: - for name in $(TREE_EXES); \ - do \ - echo deleting $$name; \ - if [ -f treelang/$$name$(exeext) ] ; then \ - rm -f treelang/$$name$(exeext); \ - fi ; \ - done - -rm -f treelang/*$(objext) - -rm -f treelang/*$(coverageexts) - -rm treelang.done - - -treelang.clean: treelang.mostlyclean - -treelang.distclean: treelang.clean - -rm -f treelang/config.status - -rm -f treelang/*.output - -treelang.extraclean: treelang.distclean - -treelang.maintainer-clean: treelang.extraclean - for name in $(TREE_GENERATED); \ - do \ - if [ -f $(srcdir)/treelang/$$name ] ; then \ - echo deleting $(srcdir)/treelang/$$name; \ - rm -f $(srcdir)/treelang/$$name; \ - fi ; \ - done - -rm -R $(srcdir)/treelang/*~ - - -# -# Stage hooks: -# The main makefile has already created stage?/treelang. - -treelang.stage1: stage1-start - -mv treelang/*$(objext) stage1/treelang -treelang.stage2: stage2-start - -mv treelang/*$(objext) stage2/treelang -treelang.stage3: stage3-start - -mv treelang/*$(objext) stage3/treelang -treelang.stage4: stage4-start - -mv treelang/*$(objext) stage4/treelang -# -# Maintenance hooks: - -# This target creates the files that can be rebuilt, but go in the -# distribution anyway. It then copies the files to the distdir directory. -treelang.distdir: -# not here yet sorry not sure if this is needed or not??? - -# test hook -# the other languages are hard coded in the main makefile.in - that seems to be wrong - -check-treelang: treelang.check - -TESTSUITEDIR = testsuite - -treelang.check: $(TESTSUITEDIR)/site.exp - -mkdir testsuite/treelang - -# these three files are empty and it seems diff has trouble generating -# patch files for new empty files as required for cvs. -# STAMP does not cut it here as I need an empty file. - touch $(srcdir)/testsuite/treelang/{a01gcco01runpgmerr,a01gcc.out01,a01gcc.out01err} - -rootme=`${PWD}`; export rootme; \ - srcdir=`cd ${srcdir}; ${PWD}` ; export srcdir ; \ - cd testsuite; \ - EXPECT=${EXPECT} ; export EXPECT ; \ - TRANSFORM=$(program_transform_name); export TRANSFORM; \ - if [ -f $${rootme}/../expect/expect ] ; then \ - TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD}` ; \ - export TCL_LIBRARY ; fi ; \ - PATH=`cd ..;${PWD}`:$$PATH; export PATH; \ - gcc_extras="-B`cd ..;${PWD}` -B`cd ..;${PWD}`/treelang"; export gcc_extras; \ - $(RUNTEST) --tool treelang $(RUNTESTFLAGS) - rm $(srcdir)/testsuite/treelang/{a01gcco01runpgmerr,a01gcc.out01,a01gcc.out01err} -# GCC_EXTRAS="$(GCC_EXTRAS)"; export GCC_EXTRAS; \ - -# copy the output files from the current test to source ie say the new results are OK -treelang.check.fix: force - srcdir=`cd ${srcdir}; ${PWD}` ; export srcdir ; - -cp testsuite/treelang/*.out* t - -cp testsuite/treelang/*runpgm* t - -rm -f t/*nofilename - -treelang.wc: force - wc ${TREE_SOURCE} - -# - -# Update the tags table for emacs find label (alt-.) function -TAGS: treelang.tags - -.PHONY: treelang.tags - -treelang.tags: - cd $(srcdir)/treelang; \ - etags -l c ${TREE_SOURCE} - -.PHONY: treelang.html - -treelang.html: - cd $(srcdir)/treelang && texi2html -I ../doc/include -verbose -menu -split_chapter -number treelang.texi -# mv treelang*.html $(srcdir)/treelang diff --git a/gcc/treelang/README b/gcc/treelang/README deleted file mode 100644 index 87dce1ae85e..00000000000 --- a/gcc/treelang/README +++ /dev/null @@ -1,19 +0,0 @@ -This is a sample language front end for GCC. - -This is a replacement for 'toy' which had potential copyright issues, -but more importantly it did not exercise very much of GCC. The intent -of this language is that it should provide a cookbook of language -elements that you can use in any language front end. - -To this end, treelang is essentially an implementation of a subset of -the GCC back end 'tree' interface in syntax. - -Thanks to Richard Kenner, Joachim Nadler and many others for helping -me to understand enough of GCC to do this. - -Please note, the documentation is not a good model to use for GCC -front end documentation. - -Tim Josling -19 June 2002 - diff --git a/gcc/treelang/config-lang.in b/gcc/treelang/config-lang.in deleted file mode 100644 index 4f5a82e1668..00000000000 --- a/gcc/treelang/config-lang.in +++ /dev/null @@ -1,39 +0,0 @@ -# Top level configure fragment for GNU C++. -# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. - -#This file is part of GCC. - -#GCC is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 2, or (at your option) -#any later version. - -#GCC is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with GCC; see the file COPYING. If not, write to -#the Free Software Foundation, 59 Temple Place - Suite 330, -#Boston, MA 02111-1307, USA. - -# Configure looks for the existence of this file to auto-config each language. -# We define several parameters used by configure: -# -# language - name of language as it would appear in $(LANGUAGES) -# compilers - value to add to $(COMPILERS) -# stagestuff - files to add to $(STAGESTUFF) -# diff_excludes - files to ignore when building diffs between two versions. - -language="treelang" - -compilers="tree1\$(exeext)" - -stagestuff= - -diff_excludes="-x lex.c -x parse.c -x parse.h" -headers= -build_by_default="no" - -gtfiles="\$(srcdir)/c-decl.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/treelang/tree1.c \$(srcdir)/treelang/treelang.h" diff --git a/gcc/treelang/lang-options.h b/gcc/treelang/lang-options.h deleted file mode 100644 index 2d60c3ef35b..00000000000 --- a/gcc/treelang/lang-options.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Definitions for switches for TREELANG. - - Copyright (C) 1995, 96-98, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -DEFINE_LANG_NAME ("treelang") - -/* This is the contribution to the `lang_options' array in gcc.c for - treelang. */ - {"-fparser-trace", N_("(debug) trace parsing process")}, - {"-flexer-trace", N_("(debug) trace lexical analysis")}, - - diff --git a/gcc/treelang/lang-specs.h b/gcc/treelang/lang-specs.h deleted file mode 100644 index 4bf8e5df927..00000000000 --- a/gcc/treelang/lang-specs.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Definitions for specs for TREELANG - - The format of the specs file is documented in gcc.c - - Copyright (C) 1995, 96-98, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* - This is the contribution to the `default_compilers' array in GCC.c for - treelang. - - This file must compile with 'traditional', so no ANSI string concatenations - -*/ - -{".tree", "@treelang", NULL}, -{".TREE", "@treelang", NULL}, -{".tre", "@treelang", NULL}, -{".TRE", "@treelang", NULL}, -{"@treelang", - "tree1\ - %{!Q:-quiet}\ - %{d*}\ - %{m*}\ - %{a}\ - %{g*}\ - %{O*}\ - %{W*}\ - %{w}\ - %{ansi}\ - %{v}\ - %{--help:--help}\ - %{pg:-p}\ - %{p}\ - %{f*}\ - %{pg|p:%{fomit-frame-pointer:%e-pg or -p and -fomit-frame-pointer are incompatible}}\ - %{S:%W{o*}%{!o*:-o %b.s}}\ - %{!S:-o %g.s}\ - %i\n\ - %{!S:as %a\ - %Y\ - %{c:%W{o*}%{!o*:-o %w%b%O}}\ - %{!c:-o %d%w%u%O}\ - %g.s\ - %A\n}\ - ", NULL -}, diff --git a/gcc/treelang/lex.l b/gcc/treelang/lex.l deleted file mode 100644 index b1881dc9f3d..00000000000 --- a/gcc/treelang/lex.l +++ /dev/null @@ -1,291 +0,0 @@ -%{ /* -*- c -*- = mode for emacs editor -/* - - TREELANG lexical analysis - - --------------------------------------------------------------------- - - Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! - - --------------------------------------------------------------------- - - Written by Tim Josling 1999-2001, based in part on other parts of - the GCC compiler. - -*/ - -#include -#include -#include "ansidecl.h" -#include "config.h" -#include "system.h" - -/* Avoid poisoned malloc problem. */ -#undef IN_GCC - -#include "config.h" -#include "diagnostic.h" -#include "tree.h" - -/* Token defs. */ -#include "treelang.h" -#include "parse.h" - -extern int option_lexer_trace; - -int yylex (void); -void update_yylval (int a); - -static int next_tree_lineno=1; -static int next_tree_charno=1; - -static void update_lineno_charno (void); -static void dump_lex_value (int lexret); - -#define SAVE_RETURN(a) {update_yylval (a); if (option_lexer_trace)\ - {fprintf (stderr, "\nlexer returning"); dump_lex_value (a);} return a;} -#define NOT_RETURN(a) {update_yylval (a); if (option_lexer_trace)\ - {fprintf (stderr, "\nlexer swallowing"); dump_lex_value (a);}} - -%} - -%option nostack -%option nounput -%option noyywrap -%option pointer -%option nodefault - -%% - - { - /* Should really allocate only what we need. lll;. */ - yylval = my_malloc (sizeof (struct prod_token_parm_item)); - ((struct prod_token_parm_item *)yylval)->tp.tok.lineno = next_tree_lineno; - ((struct prod_token_parm_item *)yylval)->tp.tok.charno = next_tree_charno; - } - -[ \n]+ { - update_lineno_charno (); - NOT_RETURN (WHITESPACE); -} - -"//".* { - /* Comment. */ - update_lineno_charno (); - NOT_RETURN (COMMENT); -} - -"{" { - update_lineno_charno (); - SAVE_RETURN (LEFT_BRACE); -} - -"}" { - update_lineno_charno (); - SAVE_RETURN (RIGHT_BRACE); -} - -"(" { - update_lineno_charno (); - SAVE_RETURN (LEFT_PARENTHESIS); -} - -")" { - update_lineno_charno (); - SAVE_RETURN (RIGHT_PARENTHESIS); -} - -"," { - update_lineno_charno (); - SAVE_RETURN (COMMA); -} - -";" { - update_lineno_charno (); - SAVE_RETURN (SEMICOLON); -} - -"+" { - update_lineno_charno (); - SAVE_RETURN (PLUS); -} - -"-" { - update_lineno_charno (); - SAVE_RETURN (MINUS); -} - -"=" { - update_lineno_charno (); - SAVE_RETURN (ASSIGN); -} - -"==" { - update_lineno_charno (); - SAVE_RETURN (EQUALS); -} - -[+-]?[0-9]+ { - update_lineno_charno (); - SAVE_RETURN (INTEGER); -} - -"external_reference" { - update_lineno_charno (); - SAVE_RETURN (EXTERNAL_REFERENCE); -} - -"external_definition" { - update_lineno_charno (); - SAVE_RETURN (EXTERNAL_DEFINITION); -} - -"static" { - update_lineno_charno (); - SAVE_RETURN (STATIC); -} - -"automatic" { - update_lineno_charno (); - SAVE_RETURN (AUTOMATIC); -} - -"int" { - update_lineno_charno (); - SAVE_RETURN (INT); -} - -"char" { - update_lineno_charno (); - SAVE_RETURN (CHAR); -} - -"void" { - update_lineno_charno (); - SAVE_RETURN (VOID); -} - -"unsigned" { - update_lineno_charno (); - SAVE_RETURN (UNSIGNED); -} - -"return" { - update_lineno_charno (); - SAVE_RETURN (RETURN); -} - -"if" { - update_lineno_charno (); - SAVE_RETURN (IF); -} - -"else" { - update_lineno_charno (); - SAVE_RETURN (ELSE); -} - -[A-Za-z_]+[A-Za-z_0-9]* { - update_lineno_charno (); - update_yylval (NAME); - if (option_lexer_trace) - { - fprintf (stderr, "\nlexer returning"); - dump_lex_value (NAME); - } - return NAME; -} - -[^\n] { - update_lineno_charno (); - fprintf (stderr, "%s:%i:%i: Unrecognized character %c\n", in_fname, - ((struct prod_token_parm_item *)yylval)->tp.tok.lineno, - ((struct prod_token_parm_item *)yylval)->tp.tok.charno, yytext[0]); - errorcount++; -} - -%% - -/* - Update line number (1-) and character number (1-). Call this - before processing the token. */ - -static void -update_lineno_charno (void) -{ - /* Update the values we send to caller in case we sometimes don't - tell them about all the 'tokens' eg comments etc. */ - int yyl; - ((struct prod_token_parm_item *)yylval)->tp.tok.lineno = next_tree_lineno; - ((struct prod_token_parm_item *)yylval)->tp.tok.charno = next_tree_charno; - for ( yyl = 0; yyl < yyleng; ++yyl ) - { - if ( yytext[yyl] == '\n' ) - { - ++next_tree_lineno; - next_tree_charno = 1; - } - else - next_tree_charno++; - } -} - -/* Fill in the fields of yylval - the value of the token. The token - type is A. */ -void -update_yylval (int a) -{ - struct prod_token_parm_item * tok; - tok=yylval; - - tok->category = token_category; - tok->type = a; - tok->tp.tok.length = yyleng; - /* Have to copy yytext as it is just a ptr into the buffer at the - moment. */ - tok->tp.tok.chars = my_malloc (yyleng + 1); - memcpy (tok->tp.tok.chars, yytext, yyleng); -} - -/* Trace the value LEXRET and the position and token details being - returned by the lexical analyser. */ - -static void -dump_lex_value (int lexret) -{ - int ix; - fprintf (stderr, " %d l:%d c:%d ln:%d text=", lexret, - ((struct prod_token_parm_item *) yylval)->tp.tok.lineno, - ((struct prod_token_parm_item *) yylval)->tp.tok.charno, - ((struct prod_token_parm_item *) yylval)->tp.tok.length); - for (ix = 0; ix < yyleng; ix++) - { - fprintf (stderr, "%c", yytext[ix]); - } - fprintf (stderr, " in hex:"); - for (ix = 0; ix < yyleng; ix++) - { - fprintf (stderr, " %2.2x", yytext[ix]); - } - fprintf (stderr, "\n"); -} - diff --git a/gcc/treelang/parse.y b/gcc/treelang/parse.y deleted file mode 100644 index 7d7400f72bb..00000000000 --- a/gcc/treelang/parse.y +++ /dev/null @@ -1,1005 +0,0 @@ -%{ /* -*- c -*- emacs mode c */ - /* - - TREELANG Compiler parser. - - --------------------------------------------------------------------- - - Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! - - --------------------------------------------------------------------- - - Written by Tim Josling 1999-2001, based in part on other parts of - the GCC compiler. - - */ - - /* - - Grammar Conflicts - ***************** - - There are no conflicts in this grammar. Please keep it that way. - - */ - -/* Undefine IN_GCC so malloc etc work. The alternative is to redefine - the out of stack routine in bison. */ -#undef IN_GCC -/* Front ends should not have to see these, but config.h needs everything. */ -typedef void *tree; -typedef void *rtx; - -#include -#include -#include - -#include "ansidecl.h" -#include "config.h" -#include "system.h" -#include "diagnostic.h" - -#include "treelang.h" -#include "treetree.h" - -#define YYDEBUG 1 -#define YYPRINT(file, type, value) print_token (file, type, value) -#define YYERROR_VERBOSE YES - - -extern int option_parser_trace; - -/* Local prototypes. */ - -static void yyerror (const char *error_message); -int yylex (void); -int yyparse (void); -void print_token (FILE * file, unsigned int type ATTRIBUTE_UNUSED, YYSTYPE value); -static struct prod_token_parm_item *reverse_prod_list (struct prod_token_parm_item *old_first); -static void ensure_not_void (unsigned int type, struct prod_token_parm_item* name); -static int check_type_match (int type_num, struct prod_token_parm_item *exp); -static int get_common_type (struct prod_token_parm_item *type1, struct prod_token_parm_item *type2); -static struct prod_token_parm_item *make_integer_constant (struct prod_token_parm_item* value); -static void set_storage (struct prod_token_parm_item *prod); - -/* File global variables. */ - -static struct prod_token_parm_item *current_function=NULL; - -%} - -/* Not %raw - seems to have bugs. */ -%token_table - -/* Punctuation. */ -%token RIGHT_BRACE -%token LEFT_BRACE -%token RIGHT_SQUARE_BRACKET -%token LEFT_SQUARE_BRACKET -%token RIGHT_PARENTHESIS -%token LEFT_PARENTHESIS -%token SEMICOLON -%token ASTERISK -%token COMMA -%right EQUALS -%right ASSIGN -%left PLUS -%left MINUS - -/* Literals. */ -%token INTEGER - -/* Keywords. */ -%token IF -%token ELSE -%token RETURN -%token CHAR -%token INT -%token UNSIGNED -%token VOID -%token TYPEDEF -%token NAME -%token STATIC -%token AUTOMATIC -%token EXTERNAL_DEFINITION -%token EXTERNAL_REFERENCE - -/* Tokens not passed to parser. */ -%token WHITESPACE -%token COMMENT - -/* Pseudo tokens - productions. */ -%token PROD_VARIABLE_NAME -%token PROD_TYPE_NAME -%token PROD_FUNCTION_NAME -%token PROD_INTEGER_CONSTANT -%token PROD_PLUS_EXPRESSION -%token PROD_MINUS_EXPRESSION -%token PROD_ASSIGN_EXPRESSION -%token PROD_VARIABLE_REFERENCE_EXPRESSION -%token PROD_PARAMETER -%token PROD_FUNCTION_INVOCATION -%expect 0 -%% - -file: -/* Nil. */ { - /* Nothing to do. */ -} -|declarations { - /* Nothing to do. */ -} -; - - -declarations: -declaration { - /* Nothing to do. */ -} -| declarations declaration { - /* Nothing to do. */ -} -; - -declaration: -variable_def { - /* Nothing to do. */ -} -|function_prototype { - /* Nothing to do. */ -} -|function { - /* Nothing to do. */ -} -; - -variable_def: -storage typename NAME init_opt SEMICOLON { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - tok = $3; - prod = make_production (PROD_VARIABLE_NAME, tok); - SYMBOL_TABLE_NAME (prod) = tok; - EXPRESSION_TYPE (prod) = $2; - VAR_INIT (prod) = $4; - NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct prod_token_parm_item*)EXPRESSION_TYPE (prod))); - ensure_not_void (NUMERIC_TYPE (prod), tok); - if (insert_tree_name (prod)) - { - YYERROR; - } - STORAGE_CLASS_TOKEN (prod) = $1; - set_storage (prod); - - if (VAR_INIT (prod)) - { - if (! ((struct prod_token_parm_item*)VAR_INIT (prod))->tp.pro.code) - abort (); - if (STORAGE_CLASS (prod) == EXTERNAL_REFERENCE_STORAGE) - { - fprintf (stderr, "%s:%i:%i: External reference variables may not have initial value\n", in_fname, - tok->tp.tok.lineno, tok->tp.tok.charno); - print_token (stderr, 0, tok); - errorcount++; - YYERROR; - } - } - prod->tp.pro.code = tree_code_create_variable - (STORAGE_CLASS (prod), - ((struct prod_token_parm_item*)SYMBOL_TABLE_NAME (prod))->tp.tok.chars, - ((struct prod_token_parm_item*)SYMBOL_TABLE_NAME (prod))->tp.tok.length, - NUMERIC_TYPE (prod), - VAR_INIT (prod)? ((struct prod_token_parm_item*)VAR_INIT (prod))->tp.pro.code:NULL, - in_fname, - tok->tp.tok.lineno); - if (!prod->tp.pro.code) - abort (); -} -; - -storage: -STATIC -|AUTOMATIC -|EXTERNAL_DEFINITION -|EXTERNAL_REFERENCE -; - -parameter: -typename NAME { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - struct prod_token_parm_item *prod2; - tok = $2; - prod = make_production (PROD_VARIABLE_NAME, tok); - SYMBOL_TABLE_NAME (prod) = $2; - EXPRESSION_TYPE (prod) = $1; - NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct prod_token_parm_item*)EXPRESSION_TYPE (prod))); - ensure_not_void (NUMERIC_TYPE (prod), tok); - if (insert_tree_name (prod)) - { - YYERROR; - } - prod2 = make_production (PROD_PARAMETER, tok); - VARIABLE (prod2) = prod; - $$ = prod2; -} -; - -function_prototype: -storage typename NAME LEFT_PARENTHESIS parameters RIGHT_PARENTHESIS SEMICOLON { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - struct prod_token_parm_item *type; - struct prod_token_parm_item* first_parms; - struct prod_token_parm_item* last_parms; - struct prod_token_parm_item* this_parms; - struct prod_token_parm_item *this_parm; - struct prod_token_parm_item *this_parm_var; - tok = $3; - prod = make_production (PROD_FUNCTION_NAME, $3); - SYMBOL_TABLE_NAME (prod) = $3; - EXPRESSION_TYPE (prod) = $2; - NUMERIC_TYPE (prod) = NUMERIC_TYPE (( (struct prod_token_parm_item*)EXPRESSION_TYPE (prod))); - PARAMETERS (prod) = reverse_prod_list ($5); - insert_tree_name (prod); - STORAGE_CLASS_TOKEN (prod) = $1; - set_storage (prod); - switch (STORAGE_CLASS (prod)) - { - case STATIC_STORAGE: - case EXTERNAL_DEFINITION_STORAGE: - break; - - case AUTOMATIC_STORAGE: - fprintf (stderr, "%s:%i:%i: A function cannot be automatic\n", in_fname, - tok->tp.tok.lineno, tok->tp.tok.charno); - print_token (stderr, 0, tok); - errorcount++; - YYERROR; - break; - - default: - abort (); - } - type = EXPRESSION_TYPE (prod); - /* Create a parameter list in a non-front end specific format. */ - for (first_parms = NULL, last_parms = NULL, this_parm = PARAMETERS (prod); - this_parm; - this_parm = this_parm->tp.pro.next) - { - if (this_parm->category != production_category) - abort (); - this_parm_var = VARIABLE (this_parm); - if (!this_parm_var) - abort (); - if (this_parm_var->category != production_category) - abort (); - this_parms = my_malloc (sizeof (struct prod_token_parm_item)); - if (!this_parm_var->tp.pro.main_token) - abort (); - this_parms->tp.par.variable_name = this_parm_var->tp.pro.main_token->tp.tok.chars; - this_parms->type = NUMERIC_TYPE (( (struct prod_token_parm_item*)EXPRESSION_TYPE (this_parm_var))); - if (last_parms) - { - last_parms->tp.par.next = this_parms; - last_parms = this_parms; - } - else - { - first_parms = this_parms; - last_parms = this_parms; - } - this_parms->tp.par.where_to_put_var_tree = - & (( (struct prod_token_parm_item*)VARIABLE (this_parm))->tp.pro.code); - } - FIRST_PARMS (prod) = first_parms; - - prod->tp.pro.code = tree_code_create_function_prototype - (tok->tp.tok.chars, STORAGE_CLASS (prod), NUMERIC_TYPE (type), - first_parms, in_fname, tok->tp.tok.lineno); - -} -; - -function: -NAME LEFT_BRACE { - struct prod_token_parm_item *proto; - struct prod_token_parm_item search_prod; - struct prod_token_parm_item* tok; - struct prod_token_parm_item *this_parm; - tok = $1; - SYMBOL_TABLE_NAME ((&search_prod)) = tok; - current_function = proto = lookup_tree_name (&search_prod); - if (!proto) - { - fprintf (stderr, "%s:%i:%i: Function prototype not found\n", in_fname, - tok->tp.tok.lineno, tok->tp.tok.charno); - print_token (stderr, 0, tok); - errorcount++; - YYERROR; - } - if (!proto->tp.pro.code) - abort (); - tree_code_create_function_initial - (proto->tp.pro.code, in_fname, tok->tp.tok.lineno, - FIRST_PARMS (current_function)); - - /* Check all the parameters have code. */ - for (this_parm = PARAMETERS (proto); - this_parm; - this_parm = this_parm->tp.pro.next) - { - if (! (struct prod_token_parm_item*)VARIABLE (this_parm)) - abort (); - if (! (( (struct prod_token_parm_item*)VARIABLE (this_parm))->tp.pro.code)) - abort (); - } -} -variable_defs_opt statements_opt RIGHT_BRACE { - struct prod_token_parm_item* tok; - tok = $1; - tree_code_create_function_wrapup (in_fname, tok->tp.tok.lineno); - current_function = NULL; -} -; - -variable_defs_opt: -/* Nil. */ { - $$ = 0; -} -|variable_defs { - $$ = $1; -} -; - -statements_opt: -/* Nil. */ { - $$ = 0; -} -|statements { - $$ = $1; -} -; - -variable_defs: -variable_def { - /* Nothing to do. */ -} -|variable_defs variable_def { - /* Nothing to do. */ -} -; - -typename: -INT { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - tok = $1; - prod = make_production (PROD_TYPE_NAME, tok); - NUMERIC_TYPE (prod) = SIGNED_INT; - prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); - $$ = prod; -} -|UNSIGNED INT { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - tok = $1; - prod = make_production (PROD_TYPE_NAME, tok); - NUMERIC_TYPE (prod) = UNSIGNED_INT; - prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); - $$ = prod; -} -|CHAR { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - tok = $1; - prod = make_production (PROD_TYPE_NAME, tok); - NUMERIC_TYPE (prod) = SIGNED_CHAR; - prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); - $$ = prod; -} -|UNSIGNED CHAR { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - tok = $1; - prod = make_production (PROD_TYPE_NAME, tok); - NUMERIC_TYPE (prod) = UNSIGNED_CHAR; - prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); - $$ = prod; -} -|VOID { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - tok = $1; - prod = make_production (PROD_TYPE_NAME, tok); - NUMERIC_TYPE (prod) = VOID_TYPE; - prod->tp.pro.code = tree_code_get_type (NUMERIC_TYPE (prod)); - $$ = prod; -} -; - -parameters: -parameter { - /* Nothing to do. */ - $$ = $1; -} -|parameters COMMA parameter { - struct prod_token_parm_item *prod1; - prod1 = $3; - prod1->tp.pro.next = $1; /* Insert in reverse order. */ - $$ = prod1; -} -; - -statements: -statement { - /* Nothing to do. */ -} -|statements statement { - /* Nothing to do. */ -} -; - -statement: -expression SEMICOLON { - struct prod_token_parm_item *exp; - exp = $1; - tree_code_output_expression_statement (exp->tp.pro.code, in_fname, exp->tp.pro.main_token->tp.tok.lineno); -} -|return SEMICOLON { - /* Nothing to do. */ -} -|if_statement { - /* Nothing to do. */ -} -; - -if_statement: -IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *exp; - tok = $1; - exp = $3; - ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token); - tree_code_if_start (exp->tp.pro.code, in_fname, tok->tp.tok.lineno); -} -LEFT_BRACE statements_opt RIGHT_BRACE { - /* Just let the statements flow. */ -} -ELSE { - struct prod_token_parm_item* tok; - tok = $1; - tree_code_if_else (in_fname, tok->tp.tok.lineno); -} -LEFT_BRACE statements_opt RIGHT_BRACE { - struct prod_token_parm_item* tok; - tok = $12; - tree_code_if_end (in_fname, tok->tp.tok.lineno); -} -; - - -return: -RETURN expression_opt { - struct prod_token_parm_item *type_prod; - struct prod_token_parm_item* ret_tok; - ret_tok = $1; - type_prod = EXPRESSION_TYPE (current_function); - if (NUMERIC_TYPE (type_prod) == VOID) - if ($2 == NULL) - tree_code_generate_return (type_prod->tp.pro.code, NULL); - else - { - fprintf (stderr, "%s:%i:%i: Redundant expression in return\n", in_fname, - ret_tok->tp.tok.lineno, ret_tok->tp.tok.charno); - print_token (stderr, 0, ret_tok); - errorcount++; - tree_code_generate_return (type_prod->tp.pro.code, NULL); - } - else - if ($2 == NULL) - { - fprintf (stderr, "%s:%i:%i: Expression missing in return\n", in_fname, - ret_tok->tp.tok.lineno, ret_tok->tp.tok.charno); - print_token (stderr, 0, ret_tok); - errorcount++; - } - else - { - struct prod_token_parm_item *exp; - exp = $2; - /* Check same type. */ - if (check_type_match (NUMERIC_TYPE (type_prod), $2)) - { - if (!type_prod->tp.pro.code) - abort (); - if (!exp->tp.pro.code) - abort (); - /* Generate the code. */ - tree_code_generate_return (type_prod->tp.pro.code, exp->tp.pro.code); - } - } -} -; - -expression_opt: -/* Nil. */ { - $$ = 0; -} -|expression { - struct prod_token_parm_item *exp; - exp = $1; - if (!exp->tp.pro.code) - abort (); - - $$ = $1; -} -; - -expression: -INTEGER { - $$ = make_integer_constant ($1); -} -|variable_ref { - $$ = $1; -} -|expression PLUS expression { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - struct prod_token_parm_item *op1; - struct prod_token_parm_item *op2; - tree type; - - op1 = $1; - op2 = $3; - tok = $2; - ensure_not_void (NUMERIC_TYPE (op1), op1->tp.pro.main_token); - ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token); - prod = make_production (PROD_PLUS_EXPRESSION, tok); - NUMERIC_TYPE (prod) = get_common_type (op1, op2); - if (!NUMERIC_TYPE (prod)) - YYERROR; - else - { - type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); - if (!type) - abort (); - OP1 (prod) = $1; - OP2 (prod) = $3; - - prod->tp.pro.code = tree_code_get_expression - (EXP_PLUS, type, op1->tp.pro.code, op2->tp.pro.code, NULL); - } - $$ = prod; -} -|expression MINUS expression %prec PLUS { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - struct prod_token_parm_item *op1; - struct prod_token_parm_item *op2; - tree type; - - op1 = $1; - op2 = $3; - ensure_not_void (NUMERIC_TYPE (op1), op1->tp.pro.main_token); - ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token); - tok = $2; - prod = make_production (PROD_PLUS_EXPRESSION, tok); - NUMERIC_TYPE (prod) = get_common_type (op1, op2); - if (!NUMERIC_TYPE (prod)) - YYERROR; - else - { - type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); - if (!type) - abort (); - OP1 (prod) = $1; - OP2 (prod) = $3; - - prod->tp.pro.code = tree_code_get_expression (EXP_MINUS, - type, op1->tp.pro.code, op2->tp.pro.code, NULL); - } - $$ = prod; -} -|expression EQUALS expression { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - struct prod_token_parm_item *op1; - struct prod_token_parm_item *op2; - tree type; - - op1 = $1; - op2 = $3; - ensure_not_void (NUMERIC_TYPE (op1), op1->tp.pro.main_token); - ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token); - tok = $2; - prod = make_production (PROD_PLUS_EXPRESSION, tok); - NUMERIC_TYPE (prod) = SIGNED_INT; - if (!NUMERIC_TYPE (prod)) - YYERROR; - else - { - type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); - if (!type) - abort (); - OP1 (prod) = $1; - OP2 (prod) = $3; - - prod->tp.pro.code = tree_code_get_expression (EXP_EQUALS, - type, op1->tp.pro.code, op2->tp.pro.code, NULL); - } - $$ = prod; -} -|variable_ref ASSIGN expression { - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - struct prod_token_parm_item *op1; - struct prod_token_parm_item *op2; - tree type; - - op1 = $1; - op2 = $3; - tok = $2; - ensure_not_void (NUMERIC_TYPE (op2), op2->tp.pro.main_token); - prod = make_production (PROD_ASSIGN_EXPRESSION, tok); - NUMERIC_TYPE (prod) = NUMERIC_TYPE (op1); - if (!NUMERIC_TYPE (prod)) - YYERROR; - else - { - type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); - if (!type) - abort (); - OP1 (prod) = $1; - OP2 (prod) = $3; - prod->tp.pro.code = tree_code_get_expression (EXP_ASSIGN, - type, op1->tp.pro.code, op2->tp.pro.code, NULL); - } - $$ = prod; -} -|function_invocation { - $$ = $1; -} -; - -function_invocation: -NAME LEFT_PARENTHESIS expressions_with_commas RIGHT_PARENTHESIS { - struct prod_token_parm_item *prod; - struct prod_token_parm_item* tok; - struct prod_token_parm_item search_prod; - struct prod_token_parm_item *proto; - struct prod_token_parm_item *exp; - struct prod_token_parm_item *exp_proto; - struct prod_token_parm_item *var; - int exp_proto_count; - int exp_count; - tree parms; - tree type; - - tok = $1; - prod = make_production (PROD_FUNCTION_INVOCATION, tok); - SYMBOL_TABLE_NAME (prod) = tok; - PARAMETERS (prod) = reverse_prod_list ($3); - SYMBOL_TABLE_NAME ((&search_prod)) = tok; - proto = lookup_tree_name (&search_prod); - if (!proto) - { - fprintf (stderr, "%s:%i:%i: Function prototype not found\n", in_fname, - tok->tp.tok.lineno, tok->tp.tok.charno); - print_token (stderr, 0, tok); - errorcount++; - YYERROR; - } - EXPRESSION_TYPE (prod) = EXPRESSION_TYPE (proto); - NUMERIC_TYPE (prod) = NUMERIC_TYPE (proto); - /* Count the expressions and ensure they match the prototype. */ - for (exp_proto_count = 0, exp_proto = PARAMETERS (proto); - exp_proto; exp_proto = exp_proto->tp.pro.next) - exp_proto_count++; - - for (exp_count = 0, exp = PARAMETERS (prod); exp; exp = exp->tp.pro.next) - exp_count++; - - if (exp_count != exp_proto_count) - { - fprintf (stderr, "%s:%i:%i: expression count mismatch with prototype\n", in_fname, - tok->tp.tok.lineno, tok->tp.tok.charno); - print_token (stderr, 0, tok); - errorcount++; - YYERROR; - } - parms = tree_code_init_parameters (); - for (exp_proto = PARAMETERS (proto), exp = PARAMETERS (prod); - exp_proto; - exp = exp->tp.pro.next, exp_proto = exp_proto->tp.pro.next) - { - if (!exp) - abort (); - if (!exp_proto) - abort (); - if (!exp->tp.pro.code) - abort (); - var = VARIABLE (exp_proto); - if (!var) - abort (); - if (!var->tp.pro.code) - abort (); - parms = tree_code_add_parameter (parms, var->tp.pro.code, exp->tp.pro.code); - } - type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); - prod->tp.pro.code = tree_code_get_expression - (EXP_FUNCTION_INVOCATION, type, proto->tp.pro.code, parms, NULL); - $$ = prod; -} -; - -expressions_with_commas: -expression { - struct prod_token_parm_item *exp; - exp = $1; - ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token); - $$ = $1; -} -|expressions_with_commas COMMA expression { - struct prod_token_parm_item *exp; - exp = $3; - ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token); - exp->tp.pro.next = $1; /* Reverse order. */ - $$ = exp; -} -; - -variable_ref: -NAME { - struct prod_token_parm_item search_prod; - struct prod_token_parm_item *prod; - struct prod_token_parm_item *symbol_table_entry; - struct prod_token_parm_item* tok; - tree type; - - tok = $1; - SYMBOL_TABLE_NAME ((&search_prod)) = tok; - symbol_table_entry = lookup_tree_name (&search_prod); - if (!symbol_table_entry) - { - fprintf (stderr, "%s:%i:%i: Variable referred to but not defined\n", in_fname, - tok->tp.tok.lineno, tok->tp.tok.charno); - print_token (stderr, 0, tok); - errorcount++; - YYERROR; - } - - prod = make_production (PROD_VARIABLE_REFERENCE_EXPRESSION, tok); - NUMERIC_TYPE (prod) = NUMERIC_TYPE (symbol_table_entry); - type = get_type_for_numeric_type (NUMERIC_TYPE (prod)); - if (!NUMERIC_TYPE (prod)) - YYERROR; - OP1 (prod) = $1; - - prod->tp.pro.code = tree_code_get_expression (EXP_REFERENCE, type, - symbol_table_entry->tp.pro.code, NULL, NULL); - $$ = prod; -} -; - -init_opt: -/* Nil. */ { - $$ = 0; -} -|init { - /* Nothing to do. */ -}; - -init: -ASSIGN init_element { -} -; - -init_element: -INTEGER { - $$ = make_integer_constant ($1); -} -; - -%% - -/* Print a token VALUE to file FILE. Ignore TYPE which is the token - type. */ - -void -print_token (FILE * file, unsigned int type ATTRIBUTE_UNUSED, YYSTYPE value) -{ - struct prod_token_parm_item *tok; - unsigned int ix; - - tok = value; - fprintf (file, "%d \"", tok->tp.tok.lineno); - for (ix = 0; ix < tok->tp.tok.length; ix++) - fprintf (file, "%c", tok->tp.tok.chars[ix]); - fprintf (file, "\""); -} - -/* Output a message ERROR_MESSAGE from the parser. */ -void -yyerror (const char *error_message) -{ - struct prod_token_parm_item *tok; - - tok = yylval; - if (tok) - { - fprintf (stderr, "%s:%i:%i: %s\n", in_fname, tok->tp.tok.lineno, tok->tp.tok.charno, error_message); - print_token (stderr, 0, tok); - } - else - fprintf (stderr, "%s\n", error_message); - - errorcount++; - -} - -/* Reverse the order of a token list, linked by parse_next, old first - token is OLD_FIRST. */ - -static struct prod_token_parm_item* -reverse_prod_list (struct prod_token_parm_item *old_first) -{ - struct prod_token_parm_item *current; - struct prod_token_parm_item *next; - struct prod_token_parm_item *prev = NULL; - - current = old_first; - prev = NULL; - - while (current) - { - if (current->category != production_category) - abort (); - next = current->tp.pro.next; - current->tp.pro.next = prev; - prev = current; - current = next; - } - return prev; -} - -/* Ensure TYPE is not VOID. Use NAME as the token for the error location. */ - -static void -ensure_not_void (unsigned int type, struct prod_token_parm_item* name) -{ - if (type == VOID) - { - fprintf (stderr, "%s:%i:%i: Type must not be void in this context\n", in_fname, - name->tp.tok.lineno, name->tp.tok.charno); - print_token (stderr, 0, name); - errorcount++; - } -} - -/* Check TYPE1 and TYPE2 which are integral types. Return the lowest - common type (min is signed int). */ - -static int -get_common_type (struct prod_token_parm_item *type1, struct prod_token_parm_item *type2) -{ - if (NUMERIC_TYPE (type1) == UNSIGNED_INT) - return UNSIGNED_INT; - if (NUMERIC_TYPE (type2) == UNSIGNED_INT) - return UNSIGNED_INT; - - return SIGNED_INT; -} - -/* Check type (TYPE_NUM) and expression (EXP) match. Return the 1 if - OK else 0. Must be exact match - same name unless it is an - integral type. */ - -static int -check_type_match (int type_num, struct prod_token_parm_item *exp) -{ - switch (type_num) - { - case SIGNED_INT: - case UNSIGNED_INT: - case SIGNED_CHAR: - case UNSIGNED_CHAR: - switch (NUMERIC_TYPE (exp)) - { - case SIGNED_INT: - case UNSIGNED_INT: - case SIGNED_CHAR: - case UNSIGNED_CHAR: - return 1; - - case VOID: - abort (); - - default: - abort (); - } - break; - - case VOID: - abort (); - - default: - abort (); - - } -} - -/* Make a production for an integer constant VALUE. */ - -static struct prod_token_parm_item * -make_integer_constant (struct prod_token_parm_item* value) -{ - struct prod_token_parm_item* tok; - struct prod_token_parm_item *prod; - tok = value; - prod = make_production (PROD_INTEGER_CONSTANT, tok); - if ((tok->tp.tok.chars[0] == (unsigned char)'-')|| (tok->tp.tok.chars[0] == (unsigned char)'+')) - NUMERIC_TYPE (prod) = SIGNED_INT; - else - NUMERIC_TYPE (prod) = UNSIGNED_INT; - prod->tp.pro.code = tree_code_get_integer_value (tok->tp.tok.chars, tok->tp.tok.length); - return prod; -} - -/* Set STORAGE_CLASS in PROD according to CLASS_TOKEN. */ - -static void -set_storage (struct prod_token_parm_item *prod) -{ - struct prod_token_parm_item* stg_class; - stg_class = STORAGE_CLASS_TOKEN (prod); - switch (stg_class->type) - { - case STATIC: - STORAGE_CLASS (prod) = STATIC_STORAGE; - break; - - case AUTOMATIC: - STORAGE_CLASS (prod) = AUTOMATIC_STORAGE; - break; - - case EXTERNAL_DEFINITION: - STORAGE_CLASS (prod) = EXTERNAL_DEFINITION_STORAGE; - break; - - case EXTERNAL_REFERENCE: - STORAGE_CLASS (prod) = EXTERNAL_REFERENCE_STORAGE; - break; - - default: - abort (); - } -} - -/* Set parse trace. */ - -void -treelang_debug (void) -{ - if (option_parser_trace) - yydebug = 1; -} diff --git a/gcc/treelang/tree1.c b/gcc/treelang/tree1.c deleted file mode 100644 index bc54710f15a..00000000000 --- a/gcc/treelang/tree1.c +++ /dev/null @@ -1,319 +0,0 @@ - /* - - TREELANG Compiler almost main (tree1) - Called by GCC's toplev.c - - Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! - - --------------------------------------------------------------------------- - - Written by Tim Josling 1999, 2000, 2001, based in part on other - parts of the GCC compiler. - -*/ - -#include "config.h" -#include "system.h" -#include "ansidecl.h" -#include "flags.h" -#include "toplev.h" - -#include "ggc.h" -#include "tree.h" -#include "diagnostic.h" - -#include -#include -#include -#include -#include -#include - -#include "treelang.h" -#include "treetree.h" - -extern int yyparse (void); -/* Linked list of symbols - all must be unique in treelang. */ - -static GTY(()) struct prod_token_parm_item *symbol_table = NULL; - -/* Language for usage for messages. */ - -const char *const language_string = "TREELANG - sample front end for GCC "; - -/* Local prototypes. */ - -void version (void); - -/* Global variables. */ - -extern struct cbl_tree_struct_parse_tree_top* parse_tree_top; - -/* - Options. -*/ - -/* Trace the parser. */ -unsigned int option_parser_trace = 0; - -/* Trace the lexical analysis. */ - -unsigned int option_lexer_trace = 0; - -/* Warning levels. */ - -/* Local variables. */ - -unsigned char *in_fname = NULL; /* Input file name. */ - -/* This is 1 if we have output the version string. */ - -static int version_done = 0; - -/* Variable nesting level. */ - -static unsigned int work_nesting_level = 0; - -/* Process one switch - called by toplev.c. */ - -int -treelang_decode_option (num_options_left, first_option_left) - int num_options_left ATTRIBUTE_UNUSED; - char** first_option_left; -{ - - /* - Process options - bear in mind I may get options that are really - meant for someone else (eg the main compiler) so I have to be very - permissive. - - */ - - if (first_option_left[0][0] != '-') - return 0; - - switch (first_option_left[0][1]) - { - case '-': - if (!strcmp (first_option_left[0],"--help")) - { - if (!version_done) - { - fputs (language_string, stdout); - fputs (version_string, stdout); - fputs ("\n", stdout); - version_done = 1; - } - fprintf (stdout, "Usage: tree1 [switches] -o output input\n"); - return 1; - } - case 'v': - if (!strcmp (first_option_left[0],"-v")) - { - if (!version_done) - { - fputs (language_string, stdout); - fputs (version_string, stdout); - fputs ("\n", stdout); - version_done = 1; - } - return 1; - } - case 'y': - if (!strcmp (first_option_left[0],"-y")) - { - option_lexer_trace = 1; - option_parser_trace = 1; - return 1; - } - case 'f': - if (!strcmp (first_option_left[0],"-fparser-trace")) - { - option_parser_trace = 1; - return 1; - } - if (!strcmp (first_option_left[0],"-flexer-trace")) - { - option_lexer_trace = 1; - return 1; - } - return 0; - - case 'w': - if (!strcmp (first_option_left[0],"-w")) - { - /* Tolerate this option but ignore it - we always put out - all warnings. */ - return 1; - } - return 0; - - case 'W': - if (!strcmp (first_option_left[0],"-Wall")) - { - return 1; - } - return 0; - - default: - return 0; - } - - return 0; - -} - -/* Language dependent parser setup. */ - -const char* -treelang_init (const char* filename) -{ - /* Set up the declarations needed for this front end. */ - - input_filename = ""; - lineno = 0; - - treelang_init_decl_processing (); - - /* This error will not happen from GCC as it will always create a - fake input file. */ - if (!filename || (filename[0] == ' ') || (!filename[0])) - { - if (!version_done) - { - fprintf (stderr, "No input file specified, try --help for help\n"); - exit (1); - } - - in_fname = NULL; - return NULL; - } - yyin = fopen (filename, "r"); - if (!yyin) - { - fprintf (stderr, "Unable to open input file %s\n", filename); - exit (1); - } - input_filename = filename; - return (char*) (in_fname = (unsigned char*)filename); -} - -/* Language dependent wrapup. */ - -void -treelang_finish (void) -{ - fclose (yyin); -} - -/* Parse a file. Debug flag doesn't seem to work. */ - -void -treelang_parse_file (int debug_flag ATTRIBUTE_UNUSED) -{ - treelang_debug (); - yyparse (); -} - -/* Allocate SIZE bytes and clear them. */ - -void * -my_malloc (size_t size) -{ - void *mem; - mem = ggc_alloc (size); - if (!mem) - { - fprintf (stderr, "\nOut of memory\n"); - abort (); - } - memset (mem, 0, size); - return mem; -} - -/* Look up a name in PROD->SYMBOL_TABLE_NAME in the symbol table; - return the symbol table entry from the symbol table if found there, - else 0. */ - -struct prod_token_parm_item* -lookup_tree_name (struct prod_token_parm_item *prod) -{ - struct prod_token_parm_item *this; - struct prod_token_parm_item *this_tok; - struct prod_token_parm_item *tok; - tok = SYMBOL_TABLE_NAME (prod); - for (this = symbol_table; this; this = this->tp.pro.next) - { - this_tok = this->tp.pro.main_token; - if (tok->tp.tok.length != this_tok->tp.tok.length) - continue; - if (memcmp (tok->tp.tok.chars, this_tok->tp.tok.chars, this_tok->tp.tok.length)) - continue; - if (option_parser_trace) - fprintf (stderr, "Found symbol %s (%i:%i) as %i \n", tok->tp.tok.chars, - tok->tp.tok.lineno, tok->tp.tok.charno, NUMERIC_TYPE (this)); - return this; - } - if (option_parser_trace) - fprintf (stderr, "Not found symbol %s (%i:%i) as %i \n", tok->tp.tok.chars, - tok->tp.tok.lineno, tok->tp.tok.charno, tok->type); - return NULL; -} - -/* Insert name PROD into the symbol table. Return 1 if duplicate, 0 if OK. */ - -int -insert_tree_name (struct prod_token_parm_item *prod) -{ - struct prod_token_parm_item *tok; - tok = SYMBOL_TABLE_NAME (prod); - if (lookup_tree_name (prod)) - { - fprintf (stderr, "%s:%i:%i duplicate name %s\n", in_fname, tok->tp.tok.lineno, - tok->tp.tok.charno, tok->tp.tok.chars); - errorcount++; - return 1; - } - prod->tp.pro.next = symbol_table; - NESTING_LEVEL (prod) = work_nesting_level; - symbol_table = prod; - return 0; -} - -/* Create a struct productions of type TYPE, main token MAIN_TOK. */ - -struct prod_token_parm_item * -make_production (int type, struct prod_token_parm_item *main_tok) -{ - struct prod_token_parm_item *prod; - prod = my_malloc (sizeof (struct prod_token_parm_item)); - prod->category = production_category; - prod->type = type; - prod->tp.pro.main_token = main_tok; - return prod; -} - - -/* New garbage collection regime see gty.texi. */ -#include "gt-treelang-tree1.h" -/*#include "gt-treelang-treelang.h"*/ -#include "gtype-treelang.h" diff --git a/gcc/treelang/treelang.h b/gcc/treelang/treelang.h deleted file mode 100644 index f42a2e2e2e9..00000000000 --- a/gcc/treelang/treelang.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - - TREELANG Compiler common definitions (treelang.h) - - Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! - - --------------------------------------------------------------------------- - - Written by Tim Josling 1999, 2000, 2001, based in part on other - parts of the GCC compiler. - -*/ - -/* Parse structure type. */ -enum category_enum -{ /* These values less likely to be there by chance unlike 0/1, - make checks more meaningful */ - token_category = 111, - production_category = 222, - parameter_category = 333 -}; - -/* Input file name and FILE. */ -extern unsigned char* in_fname; -extern FILE* yyin; - -/* Forward references to satisfy mutually recursive definitions. */ -struct token_part; -struct production_part; -struct prod_token_parm_item; -typedef struct GTY(()) prod_token_parm_item item; - -/* A token from the input file. */ - -struct token_part GTY(()) -{ - unsigned int lineno; - unsigned int charno; - unsigned int length; /* The value. */ - unsigned char* chars; -}; - -/* Definitions for fields in production. */ -#define NESTING_LEVEL(a) a->tp.pro.info[0] /* Level used for variable definitions. */ -#define NUMERIC_TYPE(a) a->tp.pro.info[1] /* Numeric type used in type definitions and expressions. */ -#define SUB_COUNT 5 -#define SYMBOL_TABLE_NAME(a) (a->tp.pro.sub[0]) /* Name token. */ -#define EXPRESSION_TYPE(a) (a->tp.pro.sub[1]) /* Type identifier. */ -#define OP1(a) (a->tp.pro.sub[2]) /* Exp operand1. */ -#define PARAMETERS(a) (a->tp.pro.sub[2]) /* Function parameters. */ -#define VARIABLE(a) (a->tp.pro.sub[2]) /* Parameter variable ptr. */ -#define VAR_INIT(a) (a->tp.pro.sub[2]) /* Variable init. */ -#define OP2(a) (a->tp.pro.sub[3]) /* Exp operand2. */ -#define FIRST_PARMS(a) (a->tp.pro.sub[3]) /* Function parameters linked via struct tree_parameter_list. */ -#define OP3(a) (a->tp.pro.sub[4]) /* Exp operand3. */ -#define STORAGE_CLASS_TOKEN(a) (a->tp.pro.sub[4]) /* Storage class token. */ -#define STORAGE_CLASS(a) a->tp.pro.flag1 /* Values in treetree.h. */ - -struct production_part GTY(()) -{ - struct prod_token_parm_item *main_token; /* Main token for error msgs; variable name token. */ - - unsigned int info[2]; /* Extra information. */ - - struct prod_token_parm_item *sub[SUB_COUNT]; /* Sub productions or tokens. */ - tree code; /* Back end hook for this item. */ - struct prod_token_parm_item *next; /* Next in chains of various types. */ - - unsigned int flag1:2; - unsigned int flag2:1; - unsigned int flag3:1; - unsigned int flag4:1; - unsigned int flag5:1; - unsigned int flag6:1; - unsigned int flag7:1; - -}; - -/* Storage modes. */ -#define STATIC_STORAGE 0 -#define AUTOMATIC_STORAGE 1 -#define EXTERNAL_REFERENCE_STORAGE 2 -#define EXTERNAL_DEFINITION_STORAGE 3 - -/* Numeric types. */ -#define SIGNED_CHAR 1 -#define UNSIGNED_CHAR 2 -#define SIGNED_INT 3 -#define UNSIGNED_INT 4 -#define VOID_TYPE 5 - -/* Expression types. */ -#define EXP_PLUS 0 /* Addition expression. */ -#define EXP_REFERENCE 1 /* Variable reference. */ -#define EXP_ASSIGN 2 /* Assignment. */ -#define EXP_FUNCTION_INVOCATION 3 /* Call function. */ -#define EXP_MINUS 4 /* Subtraction. */ -#define EXP_EQUALS 5 /* Equality test. */ - -/* Parameter list passed to back end. */ -struct parameter_part GTY(()) -{ - struct prod_token_parm_item *next; /* Next entry. */ - unsigned char* variable_name; /* Name. */ - tree * GTY ((length ("1"))) where_to_put_var_tree; /* Where to save decl. */ -}; - -/* A production or a token. */ -struct prod_token_parm_item GTY(()) -{ - enum category_enum category; /* Token or production. */ - unsigned int type; /* Token or production type. */ - union t_or_p - { - struct token_part GTY((tag ("token_category"))) tok; - struct production_part GTY((tag ("production_category"))) pro; - struct parameter_part GTY((tag ("parameter_category"))) par; - } GTY((desc ("((item *)&%1)->category"))) tp; -}; - - -/* For parser. Alternatively you can define it using %union (bison) or - union. */ -#define YYSTYPE void * - -void *my_malloc (size_t size); -int insert_tree_name (struct prod_token_parm_item *prod); -struct prod_token_parm_item *lookup_tree_name (struct prod_token_parm_item *prod); -struct prod_token_parm_item *make_production (int type, struct prod_token_parm_item *main_tok); -void mark_production_used (struct prod_token_parm_item *pp); -void mark_token_used (struct prod_token_parm_item *tt); -void treelang_debug (void); - diff --git a/gcc/treelang/treelang.texi b/gcc/treelang/treelang.texi deleted file mode 100644 index 8f9ea8f6506..00000000000 --- a/gcc/treelang/treelang.texi +++ /dev/null @@ -1,1317 +0,0 @@ -\input texinfo @c -*-texinfo-*- - -@c NOTE THIS IS NOT A GOOD EXAMPLE OF HOW TO DO A MANUAL. FIXME!!! -@c NOTE THIS IS NOT A GOOD EXAMPLE OF HOW TO DO A MANUAL. FIXME!!! -@c NOTE THIS IS NOT A GOOD EXAMPLE OF HOW TO DO A MANUAL. FIXME!!! - - -@c %**start of header -@setfilename treelang.info - -@set last-update 2001-07-30 -@set copyrights-treelang 1995,1996,1997,1998,1999,2000,2001,2002 -@c DEVELOPMENT is set to indicate an in-development version, -@c as compared to a release version. When making a release -@c (e.g. a release branch in the CVS repository for GCC), -@c clear this and set the version information correctly. -@clear DEVELOPMENT -@set version-treelang 1.0 -@set version-GCC 3.0 - -@set email-general gcc@@gcc.gnu.org -@set email-bugs gcc-bugs@@gcc.gnu.org or bug-gcc@@gnu.org -@set email-patches gcc-patches@@gcc.gnu.org -@set path-treelang gcc/gcc/treelang - -@set which-treelang GCC-@value{version-GCC} -@set which-GCC GCC - -@set email-josling tej@@melbpc.org.au -@set www-josling http://www.geocities.com/timjosling - -@c This tells @include'd files that they're part of the overall TREELANG doc -@c set. (They might be part of a higher-level doc set too.) -@set DOC-TREELANG - -@c @setfilename usetreelang.info -@c @setfilename maintaintreelang.info -@c To produce the full manual, use the "treelang.info" setfilename, and -@c make sure the following do NOT begin with '@c' (and the @clear lines DO) -@set INTERNALS -@set USING -@c To produce a user-only manual, use the "usetreelang.info" setfilename, and -@c make sure the following does NOT begin with '@c': -@c @clear INTERNALS -@c To produce a maintainer-only manual, use the "maintaintreelang.info" setfilename, -@c and make sure the following does NOT begin with '@c': -@c @clear USING - -@c 6/27/96 FSF DO wants smallbook fmt for 1st bound edition. (from gcc.texi) -@c @smallbook - -@c i also commented out the finalout command, so if there *are* any -@c overfulls, you'll (hopefully) see the rectangle in the right hand -@c margin. -- burley 1999-03-13 (from mew's comment in GCC.texi). -@c @finalout - -@ifset INTERNALS -@ifset USING -@settitle Using and Maintaining GNU Treelang -@end ifset -@end ifset -@c seems reasonable to assume at least one of INTERNALS or USING is set... -@ifclear INTERNALS -@settitle Using GNU Treelang -@end ifclear -@ifclear USING -@settitle Maintaining GNU Treelang -@end ifclear -@c then again, have some fun -@ifclear INTERNALS -@ifclear USING -@settitle Doing Very Little at all with GNU Treelang -@end ifclear -@end ifclear - -@syncodeindex fn cp -@syncodeindex vr cp -@c %**end of header - -@c Cause even numbered pages to be printed on the left hand side of -@c the page and odd numbered pages to be printed on the right hand -@c side of the page. Using this, you can print on both sides of a -@c sheet of paper and have the text on the same part of the sheet. - -@c The text on right hand pages is pushed towards the right hand -@c margin and the text on left hand pages is pushed toward the left -@c hand margin. -@c (To provide the reverse effect, set bindingoffset to -0.75in.) - -@c @tex -@c \global\bindingoffset=0.75in -@c \global\normaloffset =0.75in -@c @end tex - -@ifinfo -@dircategory Programming -@direntry -* treelang: (treelang). The GNU Treelang compiler. -@end direntry -@ifset INTERNALS -@ifset USING -This file documents the use and the internals of the GNU Treelang -(@code{treelang}) compiler. At the moment this manual is not -incorporated into the main GCC manual as it is too incomplete. It -corresponds to the @value{which-treelang} version of @code{treelang}. -@end ifset -@end ifset -@ifclear USING -This file documents the internals of the GNU Treelang (@code{treelang}) compiler. -It corresponds to the @value{which-treelang} version of @code{treelang}. -@end ifclear -@ifclear INTERNALS -This file documents the use of the GNU Treelang (@code{treelang}) compiler. -It corresponds to the @value{which-treelang} version of @code{treelang}. -@end ifclear - -Published by the Free Software Foundation -59 Temple Place - Suite 330 -Boston, MA 02111-1307 USA - -Copyright (C) @value{copyrights-treelang} Free Software Foundation, Inc. - -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.1 or -any later version published by the Free Software Foundation; with the -Invariant Sections being ``GNU General Public License'', the Front-Cover -texts being (a) (see below), and with the Back-Cover Texts being (b) -(see below). A copy of the license is included in the section entitled -``GNU Free Documentation License''. - -(a) The FSF's Front-Cover Text is: - - A GNU Manual - -(b) The FSF's Back-Cover Text is: - - You have freedom to copy and modify this GNU Manual, like GNU - software. Copies published by the Free Software Foundation raise - funds for GNU development. -@end ifinfo - -treelang was Contributed by Tim Josling (@email{@value{email-josling}}). -Inspired by and based on the 'toy' language, written by Richard Kenner. - -This document was written by Tim Josling, based on the GNU C++ -documentation. - -@setchapternewpage odd -@c @finalout -@titlepage -@ifset INTERNALS -@ifset USING -@center @titlefont{Using and Maintaining GNU Treelang} - -@end ifset -@end ifset -@ifclear INTERNALS -@title Using GNU Treelang -@end ifclear -@ifclear USING -@title Maintaining GNU Treelang -@end ifclear -@sp 2 -@center Tim Josling -@sp 3 -@center Last updated @value{last-update} -@sp 1 -@center for version @value{version-treelang} -@page -@vskip 0pt plus 1filll -Copyright @copyright{} @value{copyrights-treelang} Free Software Foundation, Inc. -@sp 2 -For the @value{which-treelang} Version* -@sp 1 -Published by the Free Software Foundation @* -59 Temple Place - Suite 330@* -Boston, MA 02111-1307, USA@* -@c Last printed ??ber, 19??.@* -@c Printed copies are available for $? each.@* -@c ISBN ??? -@sp 1 -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.1 or -any later version published by the Free Software Foundation; with the -Invariant Sections being ``GNU General Public License'', the Front-Cover -texts being (a) (see below), and with the Back-Cover Texts being (b) -(see below). A copy of the license is included in the section entitled -``GNU Free Documentation License''. - -(a) The FSF's Front-Cover Text is: - - A GNU Manual - -(b) The FSF's Back-Cover Text is: - - You have freedom to copy and modify this GNU Manual, like GNU - software. Copies published by the Free Software Foundation raise - funds for GNU development. -@end titlepage -@page - -@ifinfo - -@node Top, Copying,, (dir) -@top Introduction -@cindex Introduction - -@ifset INTERNALS -@ifset USING -This manual documents how to run, install and maintain @code{treelang}, -as well as its new features and incompatibilities, -and how to report bugs. -It corresponds to the @value{which-treelang} version of @code{treelang}. -@end ifset -@end ifset - -@ifclear INTERNALS -This manual documents how to run and install @code{treelang}, -as well as its new features and incompatibilities, and how to report -bugs. -It corresponds to the @value{which-treelang} version of @code{treelang}. -@end ifclear -@ifclear USING -This manual documents how to maintain @code{treelang}, as well as its -new features and incompatibilities, and how to report bugs. It -corresponds to the @value{which-treelang} version of @code{treelang}. -@end ifclear - -@end ifinfo - -@ifset DEVELOPMENT -@emph{Warning:} This document is still under development, and might not -accurately reflect the @code{treelang} code base of which it is a part. -@end ifset - -@menu -* Copying:: -* Contributors:: -* GNU Free Documentation License:: -* Funding:: -* Getting Started:: -* What is GNU Treelang?:: -* Lexical Syntax:: -* Parsing Syntax:: -* Compiler Overview:: -* TREELANG and GCC:: -* Compiler:: -* Other Languages:: -* treelang internals:: -* Open Questions:: -* Bugs:: -* Service:: -* Projects:: -* Index:: - -@detailmenu - --- The Detailed Node Listing --- - -Other Languages - -* Interoperating with C and C++:: - -treelang internals - -* treelang files:: -* treelang compiler interfaces:: -* Hints and tips:: - -treelang compiler interfaces - -* treelang driver:: -* treelang main compiler:: - -treelang main compiler - -* Interfacing to toplev.c:: -* Interfacing to the garbage collection:: -* Interfacing to the code generation code. :: - -Reporting Bugs - -* Sending Patches:: - -@end detailmenu -@end menu - -@include gpl.texi - -@include fdl.texi - -@node Contributors - -@unnumbered Contributors to GNU Treelang -@cindex contributors -@cindex credits - -Treelang was based on 'toy' by Richard Kenner, and also uses code from -the GCC core code tree. Tim Josling first created the language and -documentation, based on the GCC Fortran compiler's documentation -framework. - -@itemize @bullet -@item -The packaging and compiler portions of GNU Treelang are based largely -on the GCC compiler. -@xref{Contributors,,Contributors to GCC,GCC,Using and Maintaining GCC}, -for more information. - -@item -There is no specific run-time library for treelang, other than the -standard C runtime. - -@item -It would have been difficult to build treelang without access to Joachim -Nadler's guide to writing a front end to GCC (written in German). A -translation of this document into English is available via the -CobolForGCC project or via the documentation links from the GCC home -page @uref{http://GCC.gnu.org}. -@end itemize - -@include funding.texi - -@node Getting Started -@chapter Getting Started -@cindex getting started -@cindex new users -@cindex newbies -@cindex beginners - -Treelang is a sample language, useful only to help people understand how -to implement a new language front end to GCC. It is not a useful -language in itself other than as an example or basis for building a new -language. Therefore only language developers are likely to have an -interest in it. - -This manual assumes familiarity with GCC, which you can obtain by using -it and by reading the manual @samp{Using and Porting GCC}. - -To install treelang, follow the GCC installation instructions, -taking care to ensure you specify treelang in the configure step. - -If you're generally curious about the future of -@code{treelang}, see @ref{Projects}. -If you're curious about its past, -see @ref{Contributors}. - -To see a few of the questions maintainers of @code{treelang} have, -and that you might be able to answer, -see @ref{Open Questions}. - -@ifset USING -@node What is GNU Treelang?, Lexical Syntax, Getting Started, Top -@chapter What is GNU Treelang? -@cindex concepts, basic -@cindex basic concepts - -GNU Treelang, or @code{treelang}, is designed initially as a free -replacement for, or alternative to, the 'toy' language, but which is -amenable to inclusion within the GCC source tree. - -@code{treelang} is largely a cut down version of C, designed to showcase -the features of the GCC code generation back end. Only those features -that are directly supported by the GCC code generation back end are -implemented. Features are implemented in a manner which is easiest and -clearest to implement. Not all or even most code generation back end -features are implemented. The intention is to add features incrementally -until most features of the GCC back end are implemented in treelang. - -The main features missing are structures, arrays and pointers. - -A sample program follows: - -@example -// function prototypes -// function 'add' taking two ints and returning an int -external_definition int add(int arg1, int arg2); -external_definition int subtract(int arg3, int arg4); -external_definition int first_nonzero(int arg5, int arg6); -external_definition int double_plus_one(int arg7); - -// function definition -add -@{ -// return the sum of arg1 and arg2 - return arg1 + arg2; -@} - - -subtract -@{ - return arg3 - arg4; -@} - -double_plus_one -@{ -// aaa is a variable, of type integer and allocated at the start of the function - automatic int aaa; -// set aaa to the value returned from aaa, when passed arg7 and arg7 as the two parameters - aaa=add(arg7, arg7); - aaa=add(aaa, aaa); - aaa=subtract(subtract(aaa, arg7), arg7) + 1; - return aaa; -@} - -first_nonzero -@{ -// C-like if statement - if (arg5) - @{ - return arg5; - @} - else - @{ - @} - return arg6; -@} -@end example - -@node Lexical Syntax, Parsing Syntax, What is GNU Treelang?, Top -@chapter Lexical Syntax -@cindex Lexical Syntax - -Treelang programs consist of whitespace, comments, keywords and names. -@itemize @bullet - -@item -Whitespace consists of the space character and the end of line -character. Tabs are not allowed. Line terminations are as defined by the -standard C library. Whitespace is ignored except within comments, -and where it separates parts of the program. In the example below, A and -B are two separate names separated by whitespace. - -@smallexample -A B -@end smallexample - -@item -Comments consist of @samp{//} followed by any characters up to the end -of the line. C style comments (/* */) are not supported. For example, -the assignment below is followed by a not very helpful comment. - -@smallexample -x=1; // Set X to 1 -@end smallexample - -@item -Keywords consist of any reserved words or symbols as described -later. The list of keywords follows: - -@smallexample -@{ - used to start the statements in a function -@} - used to end the statements in a function -( - start list of function arguments, or to change the precedence of operators in an expression -) - end list or prioritised operators in expression -, - used to separate parameters in a function prototype or in a function call -; - used to end a statement -+ - addition -- - subtraction -= - assignment -== - equality test -if - begin IF statement -else - begin 'else' portion of IF statement -static - indicate variable is permanent, or function has file scope only -automatic - indicate that variable is allocated for the life of the function -external_reference - indicate that variable or function is defined in another file -external_definition - indicate that variable or function is to be accessible from other files -int - variable is an integer (same as C int) -char - variable is a character (same as C char) -unsigned - variable is unsigned. If this is not present, the variable is signed -return - start function return statement -void - used as function type to indicate function returns nothing -@end smallexample - - -@item -Names consist of any letter or "_" followed by any number of letters or -numbers or "_". "$" is not allowed in a name. All names must be globally -unique - the same name may not be used twice in any context - and must -not be a keyword. Names and keywords are case sensitive. For example: - -@smallexample -a A _a a_ IF_X -@end smallexample - -are all different names. - -@end itemize - -@node Parsing Syntax, Compiler Overview, Lexical Syntax, Top -@chapter Parsing Syntax -@cindex Parsing Syntax - -Declarations are built up from the lexical elements described above. A -file may contain one of more declarations. - -@itemize @bullet - -@item -declaration: variable declaration OR function prototype OR function declaration - -@item -Function Prototype: storage type NAME ( parameter_list ) - -@smallexample -static int add (int a, int b) -@end smallexample - -@item -variable_declaration: storage type NAME initial; - -Example: - -@smallexample -int temp1=1; -@end smallexample - -A variable declaration can be outside a function, or at the start of a function. - -@item -storage: automatic OR static OR external_reference OR external_definition - -This defines the scope, duration and visibility of a function or variable - -@enumerate 1 - -@item -automatic: This means a variable is allocated at start of function and -released when the function returns. This can only be used for variables -within functions. It cannot be used for functions. - -@item -static: This means a variable is allocated at start of program and -remains allocated until the program as a whole ends. For a function, it -means that the function is only visible within the current file. - -@item -external_definition: For a variable, which must be defined outside a -function, it means that the variable is visible from other files. For a -function, it means that the function is visible from another file. - -@item -external_reference: For a variable, which must be defined outside a -function, it means that the variable is defined in another file. For a -function, it means that the function is defined in another file. - -@end enumerate - -@item -type: int OR unsigned int OR char OR unsigned char OR void - -This defines the data type of a variable or the return type of a function. - -@enumerate a - -@item -int: The variable is a signed integer. The function returns a signed integer. - -@item -unsigned int: The variable is an unsigned integer. The function returns an unsigned integer. - -@item -char: The variable is a signed character. The function returns a signed character. - -@item -unsigned char: The variable is an unsigned character. The function returns an unsigned character. - -@end enumerate - -@item -parameter_list OR parameter [, parameter]... - -@item -parameter: variable_declaration , - -The variable declarations must not have initialisations. - -@item -initial: = value - -@item -value: integer_constant - -@smallexample -eg 1 +2 -3 -@end smallexample - -@item -function_declaration: name @{variable_declarations statements @} - -A function consists of the function name then the declarations (if any) -and statements (if any) within one pair of braces. - -The details of the function arguments come from the function -prototype. The function prototype must precede the function declaration -in the file. - -@item -statement: if_statement OR expression_statement OR return_statement - -@item -if_statement: if (expression) @{ statements @} else @{ statements @} - -The first lot of statements is executed if the expression is -non-zero. Otherwise the second lot of statements is executed. Either -list of statements may be empty, but both sets of braces and the else must be present. - -@smallexample -if (a==b) -@{ -// nothing -@} -else -@{ -a=b; -@} -@end smallexample - -@item -expression_statement: expression; - -The expression is executed and any side effects, such - -@item -return_statement: return expression_opt; - -Returns from the function. If the function is void, the expression must -be absent, and if the function is not void the expression must be -present. - -@item -expression: variable OR integer_constant OR expression+expression OR expression-expression - OR expression==expression OR (expression) OR variable=expression OR function_call - -An expression can be a constant or a variable reference or a -function_call. Expressions can be combined as a sum of two expressions -or the difference of two expressions, or an equality test of two -expresions. An assignment is also an expression. Expresions and operator -precedence work as in C. - -@item -function_call: function_name (comma_separated_expressions) - -This invokes the function, passing to it the values of the expressions -as actual parameters. - -@end itemize - -@cindex compilers -@node Compiler Overview, TREELANG and GCC, Parsing Syntax, Top -@chapter Compiler Overview -treelang is run as part of the GCC compiler. - -@itemize @bullet -@cindex source code -@cindex file, source -@cindex code, source -@cindex source file -@item -It reads a user's program, stored in a file and containing instructions -written in the appropriate language (Treelang, C, and so on). This file -contains @dfn{source code}. - -@cindex translation of user programs -@cindex machine code -@cindex code, machine -@cindex mistakes -@item -It translates the user's program into instructions a computer can carry -out more quickly than it takes to translate the instructions in the -first place. These instructions are called @dfn{machine code}---code -designed to be efficiently translated and processed by a machine such as -a computer. Humans usually aren't as good writing machine code as they -are at writing Treelang or C, because it is easy to make tiny mistakes -writing machine code. When writing Treelang or C, it is easy to make -big mistakes. But you can only make one mistake, because the compiler -stops after it finds any problem. - -@cindex debugger -@cindex bugs, finding -@cindex @code{gdb}, command -@cindex commands, @code{gdb} -@item -It provides information in the generated machine code -that can make it easier to find bugs in the program -(using a debugging tool, called a @dfn{debugger}, -such as @code{gdb}). - -@cindex libraries -@cindex linking -@cindex @code{ld} command -@cindex commands, @code{ld} -@item -It locates and gathers machine code already generated to perform actions -requested by statements in the user's program. This machine code is -organized into @dfn{libraries} and is located and gathered during the -@dfn{link} phase of the compilation process. (Linking often is thought -of as a separate step, because it can be directly invoked via the -@code{ld} command. However, the @code{gcc} command, as with most -compiler commands, automatically performs the linking step by calling on -@code{ld} directly, unless asked to not do so by the user.) - -@cindex language, incorrect use of -@cindex incorrect use of language -@item -It attempts to diagnose cases where the user's program contains -incorrect usages of the language. The @dfn{diagnostics} produced by the -compiler indicate the problem and the location in the user's source file -where the problem was first noticed. The user can use this information -to locate and fix the problem. - -The compiler stops after the first error. There are no plans to fix -this, ever, as it would vastly complicate the implementation of treelang -to little or no benefit. - -@cindex diagnostics, incorrect -@cindex incorrect diagnostics -@cindex error messages, incorrect -@cindex incorrect error messages -(Sometimes an incorrect usage of the language leads to a situation where -the compiler can not make any sense of what it reads---while a human -might be able to---and thus ends up complaining about an incorrect -``problem'' it encounters that, in fact, reflects a misunderstanding of -the programmer's intention.) - -@cindex warnings -@cindex questionable instructions -@item -There are no warnings in treelang. A program is either correct or in -error. -@end itemize - -@cindex components of treelang -@cindex @code{treelang}, components of -@code{treelang} consists of several components: - -@cindex @code{gcc}, command -@cindex commands, @code{gcc} -@itemize @bullet -@item -A modified version of the @code{gcc} command, which also might be -installed as the system's @code{cc} command. -(In many cases, @code{cc} refers to the -system's ``native'' C compiler, which -might be a non-GNU compiler, or an older version -of @code{GCC} considered more stable or that is -used to build the operating system kernel.) - -@cindex @code{treelang}, command -@cindex commands, @code{treelang} -@item -The @code{treelang} command itself. - -@item -The @code{libc} run-time library. This library contains the machine -code needed to support capabilities of the Treelang language that are -not directly provided by the machine code generated by the -@code{treelang} compilation phase. This is the same library that the -main c compiler uses (libc). - -@cindex @code{tree1}, program -@cindex programs, @code{tree1} -@cindex assembler -@cindex @code{as} command -@cindex commands, @code{as} -@cindex assembly code -@cindex code, assembly -@item -The compiler itself, is internally named @code{tree1}. - -Note that @code{tree1} does not generate machine code directly---it -generates @dfn{assembly code} that is a more readable form -of machine code, leaving the conversion to actual machine code -to an @dfn{assembler}, usually named @code{as}. -@end itemize - -@code{GCC} is often thought of as ``the C compiler'' only, -but it does more than that. -Based on command-line options and the names given for files -on the command line, @code{gcc} determines which actions to perform, including -preprocessing, compiling (in a variety of possible languages), assembling, -and linking. - -@cindex driver, gcc command as -@cindex @code{gcc}, command as driver -@cindex executable file -@cindex files, executable -@cindex cc1 program -@cindex programs, cc1 -@cindex preprocessor -@cindex cpp program -@cindex programs, cpp -For example, the command @samp{gcc foo.c} @dfn{drives} the file -@file{foo.c} through the preprocessor @code{cpp}, then -the C compiler (internally named -@code{cc1}), then the assembler (usually @code{as}), then the linker -(@code{ld}), producing an executable program named @file{a.out} (on -UNIX systems). - -@cindex treelang program -@cindex programs, treelang -As another example, the command @samp{gcc foo.tree} would do much the -same as @samp{gcc foo.c}, but instead of using the C compiler named -@code{cc1}, @code{gcc} would use the treelang compiler (named -@code{tree1}). However there is no preprocessor for treelang. - -@cindex @code{tree1}, program -@cindex programs, @code{tree1} -In a GNU Treelang installation, @code{gcc} recognizes Treelang source -files by name just like it does C and C++ source files. It knows to use -the Treelang compiler named @code{tree1}, instead of @code{cc1} or -@code{cc1plus}, to compile Treelang files. If a file's name ends in -@code{.tree} then GCC knows that the program is written in treelang. You -can also manually override the language. - -@cindex @code{gcc}, not recognizing Treelang source -@cindex unrecognized file format -@cindex file format not recognized -Non-Treelang-related operation of @code{gcc} is generally -unaffected by installing the GNU Treelang version of @code{gcc}. -However, without the installed version of @code{gcc} being the -GNU Treelang version, @code{gcc} will not be able to compile -and link Treelang programs. - -@cindex printing version information -@cindex version information, printing -The command @samp{gcc -v x.tree} where @samp{x.tree} is a file which -must exist but whose contents are ignored, is a quick way to display -version information for the various programs used to compile a typical -Treelang source file. - -The @code{tree1} program represents most of what is unique to GNU -Treelang; @code{tree1} is a combination of two rather large chunks of -code. - -@cindex GCC Back End (GBE) -@cindex GBE -@cindex @code{GCC}, back end -@cindex back end, GCC -@cindex code generator -One chunk is the so-called @dfn{GNU Back End}, or GBE, -which knows how to generate fast code for a wide variety of processors. -The same GBE is used by the C, C++, and Treelang compiler programs @code{cc1}, -@code{cc1plus}, and @code{tree1}, plus others. -Often the GBE is referred to as the ``GCC back end'' or -even just ``GCC''---in this manual, the term GBE is used -whenever the distinction is important. - -@cindex GNU Treelang Front End (TFE) -@cindex tree1 -@cindex @code{treelang}, front end -@cindex front end, @code{treelang} -The other chunk of @code{tree1} is the majority of what is unique about -GNU Treelang---the code that knows how to interpret Treelang programs to -determine what they are intending to do, and then communicate that -knowledge to the GBE for actual compilation of those programs. This -chunk is called the @dfn{Treelang Front End} (TFE). The @code{cc1} and -@code{cc1plus} programs have their own front ends, for the C and C++ -languages, respectively. These fronts ends are responsible for -diagnosing incorrect usage of their respective languages by the programs -the process, and are responsible for most of the warnings about -questionable constructs as well. (The GBE in principle handles -producing some warnings, like those concerning possible references to -undefined variables, but these warnings should not occur in treelang -programs as the front end is meant to pick them up first). - -Because so much is shared among the compilers for various languages, -much of the behavior and many of the user-selectable options for these -compilers are similar. -For example, diagnostics (error messages and -warnings) are similar in appearance; command-line -options like @samp{-Wall} have generally similar effects; and the quality -of generated code (in terms of speed and size) is roughly similar -(since that work is done by the shared GBE). - -@node TREELANG and GCC, Compiler, Compiler Overview, Top -@chapter Compile Treelang, C, or Other Programs -@cindex compiling programs -@cindex programs, compiling - -@cindex @code{gcc}, command -@cindex commands, @code{gcc} -A GNU Treelang installation includes a modified version of the @code{gcc} -command. - -In a non-Treelang installation, @code{gcc} recognizes C, C++, -and Objective-C source files. - -In a GNU Treelang installation, @code{gcc} also recognizes Treelang source -files and accepts Treelang-specific command-line options, plus some -command-line options that are designed to cater to Treelang users -but apply to other languages as well. - -@xref{G++ and GCC,,Compile C; C++; or Objective-C,GCC,Using and Porting GCC}, -for information on the way different languages are handled -by the GCC compiler (@code{gcc}). - -You can use this, combined with the output of the @samp{GCC -v x.tree} -command to get the options applicable to treelang. Treelang programs -must end with the suffix @samp{.tree}. - -@cindex preprocessor - -Treelang programs are not by default run through the C -preprocessor by @code{gcc}. There is no reason why they cannot be run through the -preprocessor manually, but you would need to prevent the preprocessor -from generating #line directives, using the @samp{-P} option, otherwise -tree1 will not accept the input. - -@node Compiler, Other Languages, TREELANG and GCC, Top -@chapter The GNU Treelang Compiler - -The GNU Treelang compiler, @code{treelang}, supports programs written -in the GNU Treelang language. - -@node Other Languages, treelang internals, Compiler, Top -@chapter Other Languages - -@menu -* Interoperating with C and C++:: -@end menu - -@node Interoperating with C and C++, , Other Languages, Other Languages -@section Tools and advice for interoperating with C and C++ - -The output of treelang programs looks like C program code to the linker -and everybody else, so you should be able to freely mix treelang and C -(and C++) code, with one proviso. - -C promotes small integer types to 'int' when used as function parameters and -return values. The treelang compiler does not do this, so if you want to interface -to C, you need to specify the promoted value, not the nominal value. - -@ifset INTERNALS -@node treelang internals, Open Questions, Other Languages, Top -@chapter treelang internals - -@menu -* treelang files:: -* treelang compiler interfaces:: -* Hints and tips:: -@end menu - -@node treelang files, treelang compiler interfaces, treelang internals, treelang internals -@section treelang files - -To create a compiler that integrates into GCC, you need create many -files. Some of the files are integrated into the main GCC makefile, to -build the various parts of the compiler and to run the test -suite. Others are incorporated into various GCC programs such as -GCC.c. Finally you must provide the actual programs comprising your -compiler. - -@cindex files - -The files are: - -@enumerate 1 - -@item -COPYING. This is the copyright file, assuming you are going to use the -GNU General Public Licence. You probably need to use the GPL because if -you use the GCC back end your program and the back end are one program, -and the back end is GPLed. - -This need not be present if the language is incorporated into the main -GCC tree, as the main GCC directory has this file. - -@item -COPYING.LIB. This is the copyright file for those parts of your program -that are not to be covered by the GPL, but are instead to be covered by -the LGPL (Library or Lesser GPL). This licence may be appropriate for -the library routines associated with your compiler. These are the -routines that are linked with the @emph{output} of the compiler. Using -the LGPL for these programs allows programs written using your compiler -to be closed source. For example LIBC is under the LGPL. - -This need not be present if the language is incorporated into the main -GCC tree, as the main GCC directory has this file. - -@item -ChangeLog. Record all the changes to your compiler. Use the same format -as used in treelang as it is supported by an emacs editing mode and is -part of the FSF coding standard. Normally each directory has its own -changelog. The FSF standard allows but does not require a meaningful -comment on why the changes were made, above and beyond @emph{why} they -were made. In the author's opinion it is useful to provide this -information. - -@item -treelang.texi. The manual, written in texinfo. Your manual would have a -different file name. You need not write it in texinfo if you don't want -do, but a lot of GNU software does use texinfo. - -@cindex Make-lang.in -@item -Make-lang.in. This file is part of the make file which in incorporated -with the GCC make file skeleton (Makefile.in in the GCC directory) to -make Makefile, as part of the configuration process. - -Makefile in turn is the main instruction to actually build -everything. The build instructions are held in the main GCC manual and -web site so they are not repeated here. - -There are some comments at the top which will help you understand what -you need to do. - -There are make commands to build things, remove generated files with -various degrees of thoroughness, count the lines of code (so you know -how much progress you are making), build info and html files from the -texinfo source, run the tests etc. - -@item -README. Just a brief informative text file saying what is in this -directory. - -@cindex config-lang.in -@item -config-lang.in. This file is read by the configuration progress and must -be present. You specify the name of your language, the name(s) of the -compiler(s) incouding preprocessors you are going to build, whether any, -usually generated, files should be excluded from diffs (ie when making -diff files to send in patches). Whether the equate 'stagestuff' is used -is unknown (???). - -@cindex lang-options -@item -lang-options. This file is included into GCC.c, the main GCC driver, and -tells it what options your language supports. This is only used to -display help (is this true ???). - -@cindex lang-specs -@item -lang-specs. This file is also included in GCC.c. It tells GCC.c when to -call your programs and what options to send them. The mini-language -'specs' is documented in the source of GCC.c. Do not attempt to write a -specs file from scratch - use an existing one as the base and enhance -it. - -@item -Your texi files. Texinfo can be used to build documentation in HTML, -info, dvi and postscript formats. It is a tagged language, is documented -in its own manual, and has its own emacs mode. - -@item -Your programs. The relationships between all the programs are explained -in the next section. You need to write or use the following programs: - -@itemize @bullet - -@item -lexer. This breaks the input into words and passes these to the -parser. This is lex.l in treelang, which is passed through flex, a lex -variant, to produce C code lex.c. Note there is a school of thought that -says real men hand code their own lexers, however you may prefer to -write far less code and use flex, as was done with treelang. - -@item -parser. This breaks the program into recognizable constructs such as -expressions, statements etc. This is parse.y in treelang, which is -passed through bison, which is a yacc variant, to produce C code parse.c. - -@item -back end interface. This interfaces to the code generation back end. In -treelang, this is tree1.c which mainly interfaces to toplev.c and -treetree.c which mainly interfaces to everything else. Many languages -mix up the back end interface with the parser, as in the C compiler for -example. It is a matter of taste which way to do it, but with treelang -it is separated out to make the back end interface cleaner and easier to -understand. - -@item -header files. For function prototypes and common data items. One point -to note here is that bison can generate a header files with all the -numbers is has assigned to the keywords and symbols, and you can include -the same header in your lexer. This technique is demonstrated in -treelang. - -@item -compiler main file. GCC comes with a program toplev.c which is a -perfectly serviceable main program for your compiler. treelang uses -toplev.c but other languages have been known to replace it with their -own main program. Again this is a matter of taste and how much code you -want to write. - -@end itemize - -@end enumerate - -@node treelang compiler interfaces, Hints and tips, treelang files, treelang internals -@section treelang compiler interfaces - -@cindex driver -@cindex toplev.c - -@menu -* treelang driver:: -* treelang main compiler:: -@end menu - -@node treelang driver, treelang main compiler, treelang compiler interfaces, treelang compiler interfaces -@subsection treelang driver - -The GCC compiler consists of a driver, which then executes the various -compiler phases based on the instructions in the specs files. - -Typically a program's language will be identified from its suffix (eg -.tree) for treelang programs. - -The driver (gcc.c) will then drive (exec) in turn a preprocessor, the main -compiler, the assembler and the link editor. Options to GCC allow you to -override all of this. In the case of treelang programs there is no -preprocessor, and mostly these days the C preprocessor is run within the -main C compiler rather than as a separate process, apparently for reasons of speed. - -You will be using the standard assembler and linkage editor so these are -ignored from now on. - -You have to write your own preprocessor if you want one. This is usually -totally language specific. The main point to be aware of is to ensure -that you find some way to pass file name and line number information -through to the main compiler so that it can tell the back end this -information and so the debugger can find the right source line for each -piece of code. That is all there is to say about the preprocessor except -that the preprocessor will probably not be the slowest part of the -compiler and will probably not use the most memory so don't waste too -much time tuning it until you know you need to do so. - -@node treelang main compiler, , treelang driver, treelang compiler interfaces -@subsection treelang main compiler - -The main compiler for treelang consists of toplev.c from the main GCC -compiler, the parser, lexer and back end interface routines, and the -back end routines themselves, of which there are many. - -toplev.c does a lot of work for you and you should almost certainly use it, - -Writing this code is the hard part of creating a compiler using GCC. The -back end interface documentation is incomplete and the interface is -complex. - -There are three main aspects to interfacing to the other GCC code. - -@menu -* Interfacing to toplev.c:: -* Interfacing to the garbage collection:: -* Interfacing to the code generation code. :: -@end menu - -@node Interfacing to toplev.c, Interfacing to the garbage collection, treelang main compiler, treelang main compiler -@subsubsection Interfacing to toplev.c - -In treelang this is handled mainly in tree1.c -and partly in treetree.c. Peruse toplev.c for details of what you need -to do. - -@node Interfacing to the garbage collection, Interfacing to the code generation code. , Interfacing to toplev.c, treelang main compiler -@subsubsection Interfacing to the garbage collection - -Interfacing to the garbage collection. In treelang this is mainly in -tree1.c. - -Memory allocation in the compiler should be done using the ggc_alloc and -kindred routines in ggc*.*. At the end of every 'function' in your language, toplev.c calls -the garbage collection several times. The garbage collection calls mark -routines which go through the memory which is still used, telling the -garbage collection not to free it. Then all the memory not used is -freed. - -What this means is that you need a way to hook into this marking -process. This is done by calling ggc_add_root. This provides the address -of a callback routine which will be called duing garbage collection and -which can call ggc_mark to save the storage. If storage is only -used within the parsing of a function, you do not need to provide a way -to mark it. - -Note that you can also call ggc_mark_tree to mark any of the back end -internal 'tree' nodes. This routine will follow the branches of the -trees and mark all the subordinate structures. This is useful for -example when you have created a variable declaaration that will be used -across multiple functions, or for a function declaration (from a -prototype) that may be used later on. See the next item for more on the -tree nodes. - -@node Interfacing to the code generation code. , , Interfacing to the garbage collection, treelang main compiler -@subsubsection Interfacing to the code generation code. - -In treelang this is done in treetree.c. A typedef called 'tree' which is -defined in tree.h and tree.def in the GCC directory and largely -implemented in tree.c and stmt.c forms the basic interface to the -compiler back end. - -In general you call various tree routines to generate code, either -directly or through toplev.c. You build up data structures and -expressions in similar ways. - -You can read some documentation on this which can be found via the GCC -main web page. In particular, the documentation produced by Joachim -Nadler and translated by Tim Josling can be quite useful. the C compiler -also has documentation in the main GCC manual (particularly the current -CVS version) which is useful on a lot of the details. - -In time it is hoped to enhance this document to provide a more -comprehensive overview of this topic. The main gap is in explaining how -it all works together. - -@node Hints and tips, , treelang compiler interfaces, treelang internals -@section Hints and tips - -@itemize @bullet - -@item -TAGS: Use the make ETAGS commands to create TAGS files which can be used in -emacs to jump to any symbol quickly. - -@item -GREP: grep is also a useful way to find all uses of a symbol. - -@item -TREE: The main routines to look at are tree.h and tree.def. You will -probably want a hardcopy of these. - -@item -SAMPLE: look at the sample interfacing code in treetree.c. You can use -gdb to trace through the code and learn about how it all works. - -@item -GDB: the GCC back end works well with gdb. It traps abort() and allows -you to trace back what went wrong. - -@item -Error Checking: The compiler back end does some error and consistency -checking. Often the result of an error is just no code being -generated. You will then need to trace through and find out what is -going wrong. The rtl dump files can help here also. - -@item -rtl dump files: The main compiler documents these files which are dumps -of the rtl (intermediate code) which is manipulated doing the code -generation process. This can provide useful clues about what is going -wrong. The rtl 'language' is documented in the main GCC manual. - -@end itemize - -@end ifset - -@node Open Questions, Bugs, treelang internals, Top -@chapter Open Questions - -If you know GCC well, please consider looking at the file treetree.c and -resolving any questions marked "???". - -@node Bugs, Service, Open Questions, Top -@chapter Reporting Bugs -@cindex bugs -@cindex reporting bugs - -You can report bugs to @email{@value{email-bugs}}. Please make -sure bugs are real before reporting them. Follow the guidelines in the -main GCC manual for submitting bug reports. - -@menu -* Sending Patches:: -@end menu - -@node Sending Patches, , Bugs, Bugs -@section Sending Patches for GNU Treelang - -If you would like to write bug fixes or improvements for the GNU -Treelang compiler, that is very helpful. Send suggested fixes to -@email{@value{email-patches}}. - -@node Service, Projects, Bugs, Top -@chapter How To Get Help with GNU Treelang - -If you need help installing, using or changing GNU Treelang, there are two -ways to find it: - -@itemize @bullet - -@item -Look in the service directory for someone who might help you for a fee. -The service directory is found in the file named @file{SERVICE} in the -GCC distribution. - -@item -Send a message to @email{@value{email-general}}. - -@end itemize - -@end ifset -@ifset INTERNALS - -@node Projects, Index, Service, Top -@chapter Projects -@cindex projects - -If you want to contribute to @code{treelang} by doing research, -design, specification, documentation, coding, or testing, -the following information should give you some ideas. - -Send a message to @email{@value{email-general}} if you plan to add a -feature. - -The main requirement for treelang is to add features and to add -documentation. Features are things that the GCC back end can do but -which are not reflected in treelang. Examples include structures, -unions, pointers, arrays. - -@end ifset - -@node Index, , Projects, Top -@unnumbered Index - -@printindex cp -@summarycontents -@contents -@bye diff --git a/gcc/treelang/treetree.c b/gcc/treelang/treetree.c deleted file mode 100644 index 9ee92ba5d25..00000000000 --- a/gcc/treelang/treetree.c +++ /dev/null @@ -1,1299 +0,0 @@ -/* - - TREELANG Compiler back end interface (treetree.c) - Called by the parser. - - If you want a working example of how to write a front end to GCC, - you are in the right place. - - Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002 Free Software Foundation, Inc. - - This code is based on toy.c written by Richard Kenner. - - It was later modified by Jonathan Bartlett whose changes have all - been removed (by Tim Josling). - - Various bits and pieces were cloned from the GCC main tree, as - GCC evolved, for COBOLForGCC, by Tim Josling. - - It was adapted to TREELANG by Tim Josling 2001. - - --------------------------------------------------------------------------- - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! - - --------------------------------------------------------------------------- - - */ - -/* - Assumption: garbage collection is never called implicitly. It will - not be called 'at any time' when short of memory. It will only be - called explicitly at the end of each function. This removes the - need for a *lot* of bother to ensure everything is in the mark trees - at all times. */ - - /* Note it is OK to use GCC extensions such as long long in a compiler front end. - This is because the GCC front ends are built using GCC. */ - -/* Standard/OS headers. */ - -#include -#include -#include "safe-ctype.h" -#include -#include -#include -#include - -#include -#include -#include - -/* GCC headers. */ - -#include "config.h" -#include "ansidecl.h" -#include "system.h" -#include "tree.h" -#include "flags.h" -#include "output.h" -#include "c-tree.h" -#include "rtl.h" -#include "ggc.h" -#include "toplev.h" -#include "varray.h" -#include "langhooks-def.h" -#include "langhooks.h" - -#include "treelang.h" -#include "treetree.h" - -extern int option_main; -extern char **file_names; - -/* The front end language hooks (addresses of code for this front - end). Mostly just use the C routines. */ - -#undef LANG_HOOKS_TRUTHVALUE_CONVERSION -#define LANG_HOOKS_TRUTHVALUE_CONVERSION c_common_truthvalue_conversion -#undef LANG_HOOKS_MARK_ADDRESSABLE -#define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable -#undef LANG_HOOKS_SIGNED_TYPE -#define LANG_HOOKS_SIGNED_TYPE c_common_signed_type -#undef LANG_HOOKS_UNSIGNED_TYPE -#define LANG_HOOKS_UNSIGNED_TYPE c_common_unsigned_type -#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE -#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE c_common_signed_or_unsigned_type -#undef LANG_HOOKS_TYPE_FOR_MODE -#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode -#undef LANG_HOOKS_TYPE_FOR_SIZE -#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size -#undef LANG_HOOKS_PARSE_FILE -#define LANG_HOOKS_PARSE_FILE treelang_parse_file -#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE -#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table -#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE -#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table -#undef LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES -#define LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES c_insert_default_attributes - -/* Hook routines and data unique to treelang. */ - -#undef LANG_HOOKS_INIT -#define LANG_HOOKS_INIT treelang_init -#undef LANG_HOOKS_NAME -#define LANG_HOOKS_NAME "GNU treelang" -#undef LANG_HOOKS_FINISH -#define LANG_HOOKS_FINISH treelang_finish -#undef LANG_HOOKS_DECODE_OPTION -#define LANG_HOOKS_DECODE_OPTION treelang_decode_option -const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; - -/* Tree code type/name/code tables. */ - -#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, - -const char tree_code_type[] = { -#include "tree.def" - 'x' -}; -#undef DEFTREECODE - -#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH, - -const unsigned char tree_code_length[] = { -#include "tree.def" - 0 -}; -#undef DEFTREECODE - -#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME, - -const char *const tree_code_name[] = { -#include "tree.def" - "@@dummy" -}; -#undef DEFTREECODE - -/* Number of bits in int and char - accessed by front end. */ - -unsigned int tree_code_int_size = 0; -unsigned int tree_code_char_size = 0; - -/* Return the tree stuff for this type TYPE_NUM. */ - -tree -tree_code_get_type (int type_num) -{ - switch (type_num) - { - case SIGNED_CHAR: - return signed_char_type_node; - - case UNSIGNED_CHAR: - return unsigned_char_type_node; - - case SIGNED_INT: - return integer_type_node; - - case UNSIGNED_INT: - return unsigned_type_node; - - case VOID_TYPE: - return void_type_node; - - default: - abort (); - } -} - -/* Output the code for the start of an if statement. The test - expression is EXP (true if not zero), and the stmt occurred at line - LINENO in file FILENAME. */ - -void -tree_code_if_start (tree exp, unsigned char* filename, int lineno) -{ - tree cond_exp; - cond_exp = build (NE_EXPR, - TREE_TYPE (exp), - exp, - build1 (CONVERT_EXPR, TREE_TYPE (exp), integer_zero_node)); - emit_line_note ((const char *)filename, lineno); /* Output the line number information. */ - expand_start_cond (cond_exp, /* Exit-able if non zero. */ 0); -} - -/* Output the code for the else of an if statement. The else occurred - at line LINENO in file FILENAME. */ - -void -tree_code_if_else (unsigned char* filename, int lineno) -{ - emit_line_note ((const char *)filename, lineno); /* Output the line number information. */ - expand_start_else (); -} - -/* Output the code for the end_if an if statement. The end_if (final brace) occurred - at line LINENO in file FILENAME. */ - -void -tree_code_if_end (unsigned char* filename, int lineno) -{ - emit_line_note ((const char *)filename, lineno); /* Output the line number information. */ - expand_end_cond (); -} - -/* Create a function. The prototype name is NAME, storage class is - STORAGE_CLASS, type of return variable is RET_TYPE, parameter lists - is PARMS, returns decl for this function. */ - -tree -tree_code_create_function_prototype (unsigned char* chars, - unsigned int storage_class, - unsigned int ret_type, - struct prod_token_parm_item* parms, - unsigned char* filename, - int lineno) -{ - - tree id; - struct prod_token_parm_item* parm; - tree type_list = NULL_TREE; - tree type_node; - tree fn_type; - tree fn_decl; - - /* Build the type. */ - id = get_identifier ((const char*)chars); - for (parm = parms; parm; parm = parm->tp.par.next) - { - type_node = get_type_for_numeric_type (parm->type); - type_list = tree_cons (NULL_TREE, type_node, type_list); - } - /* Last parm if void indicates fixed length list (as opposed to - printf style va_* list). */ - type_list = tree_cons (NULL_TREE, void_type_node, type_list); - /* The back end needs them in reverse order. */ - type_list = nreverse (type_list); - - type_node = get_type_for_numeric_type (ret_type); - fn_type = build_function_type (type_node, type_list); - - id = get_identifier ((const char*)chars); - fn_decl = build_decl (FUNCTION_DECL, id, fn_type); - - DECL_CONTEXT (fn_decl) = NULL_TREE; /* Nested functions not supported here. */ - DECL_SOURCE_FILE (fn_decl) = (const char *)filename; - /* if (lineno > 1000000) - ; */ /* Probably the line # is rubbish because someone forgot to set - the line number - and unfortunately impossible line #s are used as - magic flags at various times. The longest known function for - example is about 550,000 lines (it was written in COBOL). */ - DECL_SOURCE_LINE (fn_decl) = lineno; - - TREE_USED (fn_decl) = 1; - - /* Real name (optional). */ - SET_DECL_ASSEMBLER_NAME (fn_decl, DECL_NAME (fn_decl)); - - TREE_PUBLIC (fn_decl) = 0; - DECL_EXTERNAL (fn_decl) = 0; - TREE_STATIC (fn_decl) = 0; - switch (storage_class) - { - case STATIC_STORAGE: - TREE_PUBLIC (fn_decl) = 0; - break; - - case EXTERNAL_DEFINITION_STORAGE: - TREE_PUBLIC (fn_decl) = 1; - TREE_STATIC (fn_decl) = 0; - DECL_EXTERNAL (fn_decl) = 0; - break; - - case EXTERNAL_REFERENCE_STORAGE: - TREE_PUBLIC (fn_decl) = 0; - DECL_EXTERNAL (fn_decl) = 1; - break; - - - case AUTOMATIC_STORAGE: - default: - abort (); - } - - /* Process declaration of function defined elsewhere. */ - rest_of_decl_compilation (fn_decl, NULL, 1, 0); - - return fn_decl; -} - - -/* Output code for start of function; the decl of the function is in - PREV_SAVED (as created by tree_code_create_function_prototype), - the function is at line number LINENO in file FILENAME. The - parameter details are in the lists PARMS. Returns nothing. */ -void -tree_code_create_function_initial (tree prev_saved, - unsigned char* filename, - int lineno, - struct prod_token_parm_item* parms) -{ - tree fn_decl; - tree param_decl; - tree next_param; - tree first_param; - tree parm_decl; - tree parm_list; - tree resultdecl; - struct prod_token_parm_item* this_parm; - struct prod_token_parm_item* parm; - - fn_decl = prev_saved; - if (!fn_decl) - abort (); - - /* Output message if not -quiet. */ - announce_function (fn_decl); - - /* This has something to do with forcing output also. */ - pushdecl (fn_decl); - - /* Set current function for error msgs etc. */ - current_function_decl = fn_decl; - DECL_INITIAL (fn_decl) = error_mark_node; - - DECL_SOURCE_FILE (fn_decl) = (const char *)filename; - DECL_SOURCE_LINE (fn_decl) = lineno; - - /* Prepare creation of rtl for a new function. */ - - resultdecl = DECL_RESULT (fn_decl) = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (TREE_TYPE (fn_decl))); - DECL_CONTEXT (DECL_RESULT (fn_decl)) = fn_decl; - DECL_SOURCE_FILE (resultdecl) = (const char *)filename; - DECL_SOURCE_LINE (resultdecl) = lineno; - /* Work out the size. ??? is this needed. */ - layout_decl (DECL_RESULT (fn_decl), 0); - - /* Make the argument variable decls. */ - parm_list = NULL_TREE; - for (parm = parms; parm; parm = parm->tp.par.next) - { - parm_decl = build_decl (PARM_DECL, get_identifier - ((const char*) (parm->tp.par.variable_name)), - get_type_for_numeric_type (parm->type)); - - /* Some languages have different nominal and real types. */ - DECL_ARG_TYPE (parm_decl) = TREE_TYPE (parm_decl); - if (!DECL_ARG_TYPE (parm_decl)) - abort (); - if (!fn_decl) - abort (); - DECL_CONTEXT (parm_decl) = fn_decl; - DECL_SOURCE_FILE (parm_decl) = (const char *)filename; - DECL_SOURCE_LINE (parm_decl) = lineno; - parm_list = chainon (parm_decl, parm_list); - } - - /* Back into reverse order as the back end likes them. */ - parm_list = nreverse (parm_list); - - DECL_ARGUMENTS (fn_decl) = parm_list; - - /* Save the decls for use when the args are referred to. */ - for (param_decl = DECL_ARGUMENTS (fn_decl), - this_parm = parms; - param_decl; - param_decl = TREE_CHAIN (param_decl), - this_parm = this_parm->tp.par.next) - { - if (!this_parm) - abort (); /* Too few. */ - *this_parm->tp.par.where_to_put_var_tree = param_decl; - } - if (this_parm) - abort (); /* Too many. */ - - /* Output the decl rtl (not the rtl for the function code). ???. - If the function is not defined in this file, when should you - execute this? */ - make_decl_rtl (fn_decl, NULL); - - /* Use filename/lineno from above. */ - init_function_start (fn_decl, (const char *)filename, lineno); - - /* Create rtl for startup code of function, such as saving registers. */ - - expand_function_start (fn_decl, 0); - - /* Function.c requires a push at the start of the function. that - looks like a bug to me but let's make it happy. */ - - (*lang_hooks.decls.pushlevel) (0); - - /* Create rtl for the start of a new scope. */ - - expand_start_bindings (2); - - /* Put the parameters into the symbol table. */ - - for (first_param = param_decl = nreverse (DECL_ARGUMENTS (fn_decl)); - param_decl; - param_decl = next_param) - { - next_param = TREE_CHAIN (param_decl); - TREE_CHAIN (param_decl) = NULL; - /* layout_decl (param_decl, 0); Already done in build_decl tej 13/4/2002. */ - pushdecl (param_decl); - if (DECL_CONTEXT (param_decl) != current_function_decl) - abort (); - } - - /* Store back the PARM_DECL nodes. They appear in the right order. */ - DECL_ARGUMENTS (fn_decl) = getdecls (); - - /* Force it to be output, else may be solely inlined. */ - TREE_ADDRESSABLE (fn_decl) = 1; - - /* Stop -O3 from deleting it. */ - TREE_USED (fn_decl) = 1; - - /* Add a new level to the debugger symbol table. */ - - (*lang_hooks.decls.pushlevel) (0); - - /* Create rtl for the start of a new scope. */ - - expand_start_bindings (0); - - emit_line_note ((const char *)filename, lineno); /* Output the line number information. */ -} - -/* Wrapup a function contained in file FILENAME, ending at line LINENO. */ -void -tree_code_create_function_wrapup (unsigned char* filename, - int lineno) -{ - tree block; - tree fn_decl; - - fn_decl = current_function_decl; - - emit_line_note ((const char *)filename, lineno); /* Output the line number information. */ - - /* Get completely built level from debugger symbol table. */ - - block = (*lang_hooks.decls.poplevel) (1, 0, 0); - - /* Emit rtl for end of scope. */ - - expand_end_bindings (block, 0, 1); - - /* Emit rtl for end of function. */ - - expand_function_end ((const char *)filename, lineno, 0); - - /* Pop the level. */ - - block = (*lang_hooks.decls.poplevel) (1, 0, 1); - - /* And attach it to the function. */ - - DECL_INITIAL (fn_decl) = block; - - /* Emit rtl for end of scope. */ - - expand_end_bindings (block, 0, 1); - - /* Call optimization and convert optimized rtl to assembly code. */ - - rest_of_compilation (fn_decl); - - /* We are not inside of any scope now. */ - - current_function_decl = NULL_TREE; -} - -/* - Create a variable. - - The storage class is STORAGE_CLASS (eg LOCAL). - The name is CHARS/LENGTH. - The type is EXPRESSION_TYPE (eg UNSIGNED_TYPE). - The init tree is INIT. -*/ - -tree -tree_code_create_variable (unsigned int storage_class, - unsigned char* chars, - unsigned int length, - unsigned int expression_type, - tree init, - unsigned char* filename, - int lineno) -{ - tree var_type; - tree var_id; - tree var_decl; - - /* 1. Build the type. */ - var_type = get_type_for_numeric_type (expression_type); - - /* 2. Build the name. */ - if (chars[length] != 0) - abort (); /* Should be null terminated. */ - - var_id = get_identifier ((const char*)chars); - - /* 3. Build the decl and set up init. */ - var_decl = build_decl (VAR_DECL, var_id, var_type); - - /* 3a. Initialization. */ - if (init) - DECL_INITIAL (var_decl) = build1 (CONVERT_EXPR, var_type, init); - else - DECL_INITIAL (var_decl) = NULL_TREE; - - /* 4. Compute size etc. */ - layout_decl (var_decl, 0); - - if (TYPE_SIZE (var_type) == 0) - abort (); /* Did not calculate size. */ - - DECL_CONTEXT (var_decl) = current_function_decl; - - DECL_SOURCE_FILE (var_decl) = (const char *)filename; - DECL_SOURCE_LINE (var_decl) = lineno; - - /* Set the storage mode and whether only visible in the same file. */ - switch (storage_class) - { - case STATIC_STORAGE: - TREE_STATIC (var_decl) = 1; - TREE_PUBLIC (var_decl) = 0; - break; - - case AUTOMATIC_STORAGE: - TREE_STATIC (var_decl) = 0; - TREE_PUBLIC (var_decl) = 0; - break; - - case EXTERNAL_DEFINITION_STORAGE: - TREE_STATIC (var_decl) = 0; - TREE_PUBLIC (var_decl) = 1; - break; - - case EXTERNAL_REFERENCE_STORAGE: - DECL_EXTERNAL (var_decl) = 1; - TREE_PUBLIC (var_decl) = 0; - break; - - default: - abort (); - } - - /* This should really only be set if the variable is used. */ - TREE_USED (var_decl) = 1; - - /* Expand declaration and initial value if any. */ - - if (TREE_STATIC (var_decl)) - rest_of_decl_compilation (var_decl, 0, 0, 0); - else - { - expand_decl (var_decl); - if (DECL_INITIAL (var_decl)) - expand_decl_init (var_decl); - } - - return pushdecl (copy_node (var_decl)); - -} - - -/* Generate code for return statement. Type is in TYPE, expression - is in EXP if present. */ - -void -tree_code_generate_return (tree type, tree exp) -{ - tree setret; - tree param; - - for (param = DECL_ARGUMENTS (current_function_decl); - param; - param = TREE_CHAIN (param)) - { - if (DECL_CONTEXT (param) != current_function_decl) - abort (); - } - - if (exp) - { - setret = build (MODIFY_EXPR, type, DECL_RESULT (current_function_decl), - build1 (CONVERT_EXPR, type, exp)); - TREE_SIDE_EFFECTS (setret) = 1; - TREE_USED (setret) = 1; - expand_expr_stmt (setret); - } - expand_return (DECL_RESULT (current_function_decl)); -} - -/* Output the code for this expression statement CODE. */ - - -void -tree_code_output_expression_statement (tree code, - unsigned char* filename, int lineno) -{ - /* Output the line number information. */ - emit_line_note ((const char *)filename, lineno); - TREE_USED (code) = 1; - TREE_SIDE_EFFECTS (code) = 1; - expand_expr_stmt (code); -} - -/* Return a tree for a constant integer value in the token TOK. No - size checking is done. */ - -tree -tree_code_get_integer_value (unsigned char* chars, unsigned int length) -{ - long long int val = 0; - unsigned int ix; - unsigned int start = 0; - int negative = 1; - switch (chars[0]) - { - case (unsigned char)'-': - negative = -1; - start = 1; - break; - - case (unsigned char)'+': - start = 1; - break; - - default: - break; - } - for (ix = start; ix < length; ix++) - val = val * 10 + chars[ix] - (unsigned char)'0'; - val = val*negative; - return build_int_2 (val & 0xffffffff, (val >> 32) & 0xffffffff); -} - -/* Return the tree for an expresssion, type EXP_TYPE (see treetree.h) - with tree type TYPE and with operands1 OP1, OP2 (maybe), OP3 (maybe). */ -tree -tree_code_get_expression (unsigned int exp_type, - tree type, tree op1, tree op2, tree op3 ATTRIBUTE_UNUSED) -{ - tree ret1; - int operator; - - switch (exp_type) - { - case EXP_ASSIGN: - if (!op1 || !op2) - abort (); - operator = MODIFY_EXPR; - ret1 = build (operator, type, - op1, - build1 (CONVERT_EXPR, type, op2)); - - break; - - case EXP_PLUS: - operator = PLUS_EXPR; - goto binary_expression; - - case EXP_MINUS: - operator = MINUS_EXPR; - goto binary_expression; - - case EXP_EQUALS: - operator = EQ_EXPR; - goto binary_expression; - - /* Expand a binary expression. Ensure the operands are the right type. */ - binary_expression: - if (!op1 || !op2) - abort (); - ret1 = build (operator, type, - build1 (CONVERT_EXPR, type, op1), - build1 (CONVERT_EXPR, type, op2)); - break; - - /* Reference to a variable. This is dead easy, just return the - decl for the variable. If the TYPE is different than the - variable type, convert it. */ - case EXP_REFERENCE: - if (!op1) - abort (); - if (type == TREE_TYPE (op1)) - ret1 = op1; - else - ret1 = build1 (CONVERT_EXPR, type, op1); - break; - - case EXP_FUNCTION_INVOCATION: - if (!op1 || !op2) - abort (); - { - tree fun_ptr; - fun_ptr = build1 (ADDR_EXPR, build_pointer_type (type), op1); - ret1 = build (CALL_EXPR, type, fun_ptr, nreverse (op2)); - } - break; - - default: - abort (); - } - - return ret1; -} - -/* Init parameter list and return empty list. */ - -tree -tree_code_init_parameters (void) -{ - return NULL_TREE; -} - -/* Add a parameter EXP whose expression type is EXP_PROTO to list - LIST, returning the new list. */ - -tree -tree_code_add_parameter (tree list, tree proto_exp, tree exp) -{ - tree new_exp; - new_exp = tree_cons (NULL_TREE, - build1 (CONVERT_EXPR, TREE_TYPE (proto_exp), exp), - NULL_TREE); - if (!list) - return new_exp; - return chainon (new_exp, list); -} - -/* Get the tree type for this type whose number is NUMERIC_TYPE. */ - -tree -get_type_for_numeric_type (unsigned int numeric_type) -{ - - int size1; - int sign1; - switch (numeric_type) - { - case VOID_TYPE: - return void_type_node; - - case SIGNED_INT: - size1 = tree_code_int_size; - sign1 = 1; - break; - - case UNSIGNED_INT: - size1 = tree_code_int_size; - sign1 = 0; - break; - - case SIGNED_CHAR: - size1 = tree_code_char_size; - sign1 = 1; - break; - - case UNSIGNED_CHAR: - size1 = tree_code_char_size; - sign1 = 0; - break; - - default: - abort (); - } - - return tree_code_get_numeric_type (size1, sign1); - -} - -/* Return tree representing a numeric type of size SIZE1 bits and - signed if SIGN1 != 0. */ -tree -tree_code_get_numeric_type (unsigned int size1, unsigned int sign1) -{ - tree ret1; - if (size1 == tree_code_int_size) - { - if (sign1) - ret1 = integer_type_node; - else - ret1 = unsigned_type_node; - } - else - if (size1 == tree_code_char_size) - { - if (sign1) - ret1 = signed_char_type_node; - else - ret1 = unsigned_char_type_node; - } - else - abort (); - - return ret1; -} - -/* Garbage Collection. */ - -/* Callback to mark storage M as used always. */ - -void -tree_ggc_storage_always_used (void * m) -{ - void **mm; /* Actually M is a pointer to a pointer to the memory. */ - mm = (void**)m; - - if (*mm) - ggc_mark (*mm); -} - -/* Following from c-lang.c. */ - -/* Used by c-typeck.c (build_external_ref), but only for objc. */ - -tree -lookup_objc_ivar (tree id ATTRIBUTE_UNUSED) -{ - return 0; -} - -/* Dummy routines called from c code. Save copying c-decl.c, c-common.c etc. */ - -tree -objc_is_id (tree arg ATTRIBUTE_UNUSED) -{ - return 0; -} - -void -check_function_format (int *status ATTRIBUTE_UNUSED, - tree attrs ATTRIBUTE_UNUSED, - tree params ATTRIBUTE_UNUSED) -{ - return; -} - -/* Tell the c code we are not objective C. */ - -int -objc_comptypes (tree lhs ATTRIBUTE_UNUSED, - tree rhs ATTRIBUTE_UNUSED, - int reflexive ATTRIBUTE_UNUSED) -{ - return 0; -} - -/* Should not be called for treelang. */ - -tree -build_stmt VPARAMS ((enum tree_code code ATTRIBUTE_UNUSED, ...)) -{ - abort (); -} - -/* Should not be called for treelang. */ - -tree -add_stmt (tree t ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -tree -build_return_stmt (tree expr ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* C warning, ignore. */ - -void -pedwarn_c99 VPARAMS ((const char *msgid ATTRIBUTE_UNUSED, ...)) -{ - return; -} - -/* Should not be called for treelang. */ - -tree -build_case_label (tree low_value ATTRIBUTE_UNUSED, - tree high_value ATTRIBUTE_UNUSED, - tree label_decl ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -void -emit_local_var (tree decl ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -void -expand_stmt (tree t ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -cpp_reader * -cpp_create_reader (enum c_lang lang ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -const char * -init_c_lex (const char *filename ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -void init_pragma (void); - -void -init_pragma () -{ - abort (); -} - -/* Should not be called for treelang. */ - -int -cpp_finish (cpp_reader *pfile ATTRIBUTE_UNUSED, FILE *f ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -unsigned int -cpp_errors (cpp_reader *pfile ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Dummy called by C. */ - -tree -handle_format_attribute (tree *node ATTRIBUTE_UNUSED, - tree name ATTRIBUTE_UNUSED, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs ATTRIBUTE_UNUSED) -{ - return NULL_TREE; -} - -/* Should not be called for treelang. */ - -tree -handle_format_arg_attribute (tree *node ATTRIBUTE_UNUSED, - tree name ATTRIBUTE_UNUSED, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -int -cpp_handle_option (cpp_reader *pfile ATTRIBUTE_UNUSED, - int argc ATTRIBUTE_UNUSED, - char **argv ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -void -cpp_assert (cpp_reader * cr ATTRIBUTE_UNUSED, - const char *s ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -void -set_Wformat (int setting ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Used for objective C. */ - -void -objc_check_decl (tree decl ATTRIBUTE_UNUSED); - -void -objc_check_decl (tree decl ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Tell the c code we are not objective C. */ - -tree -objc_message_selector (void); - -tree -objc_message_selector () -{ - return 0; -} - -/* Should not be called for treelang. */ - -void -gen_aux_info_record (tree fndecl ATTRIBUTE_UNUSED, - int is_definition ATTRIBUTE_UNUSED, - int is_implicit ATTRIBUTE_UNUSED, - int is_prototyped ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang, but it is. */ - -void -c_parse_init () -{ - return; -} - -/* Should not be called for treelang. */ - -void maybe_apply_pragma_weak (tree decl); - -void -maybe_apply_pragma_weak (tree decl ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -void -add_decl_stmt (tree decl ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -tree -maybe_apply_renaming_pragma (tree decl, tree asmname); - -/* Should not be called for treelang. */ - -tree -maybe_apply_renaming_pragma (tree decl ATTRIBUTE_UNUSED, tree asmname ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -void -begin_stmt_tree (tree *t ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -void -finish_stmt_tree (tree *t ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -int -defer_fn (tree fn ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -cpp_options -*cpp_get_options (cpp_reader * cr ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -void -cpp_define (cpp_reader * cr ATTRIBUTE_UNUSED, const char * c ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -cpp_callbacks * -cpp_get_callbacks (cpp_reader * cr ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Create the predefined scalar types of C, - and some nodes representing standard constants (0, 1, (void *) 0). - Initialize the global binding level. - Make definitions for built-in primitive functions. */ - - /* `unsigned long' is the standard type for sizeof. - Note that stddef.h uses `unsigned long', - and this must agree, even if long and int are the same size. */ - -/* The reserved keyword table. */ -struct resword -{ - const char *word; - ENUM_BITFIELD(rid) rid : 16; - unsigned int disable : 16; -}; - -static const struct resword reswords[] = -{ - { "_Bool", RID_BOOL, 0 }, - { "_Complex", RID_COMPLEX, 0 }, - { "__FUNCTION__", RID_FUNCTION_NAME, 0 }, - { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, - { "__alignof", RID_ALIGNOF, 0 }, - { "__alignof__", RID_ALIGNOF, 0 }, - { "__asm", RID_ASM, 0 }, - { "__asm__", RID_ASM, 0 }, - { "__attribute", RID_ATTRIBUTE, 0 }, - { "__attribute__", RID_ATTRIBUTE, 0 }, - { "__bounded", RID_BOUNDED, 0 }, - { "__bounded__", RID_BOUNDED, 0 }, - { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 }, - { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 }, - { "__builtin_va_arg", RID_VA_ARG, 0 }, - { "__complex", RID_COMPLEX, 0 }, - { "__complex__", RID_COMPLEX, 0 }, - { "__const", RID_CONST, 0 }, - { "__const__", RID_CONST, 0 }, - { "__extension__", RID_EXTENSION, 0 }, - { "__func__", RID_C99_FUNCTION_NAME, 0 }, - { "__imag", RID_IMAGPART, 0 }, - { "__imag__", RID_IMAGPART, 0 }, - { "__inline", RID_INLINE, 0 }, - { "__inline__", RID_INLINE, 0 }, - { "__label__", RID_LABEL, 0 }, - { "__ptrbase", RID_PTRBASE, 0 }, - { "__ptrbase__", RID_PTRBASE, 0 }, - { "__ptrextent", RID_PTREXTENT, 0 }, - { "__ptrextent__", RID_PTREXTENT, 0 }, - { "__ptrvalue", RID_PTRVALUE, 0 }, - { "__ptrvalue__", RID_PTRVALUE, 0 }, - { "__real", RID_REALPART, 0 }, - { "__real__", RID_REALPART, 0 }, - { "__restrict", RID_RESTRICT, 0 }, - { "__restrict__", RID_RESTRICT, 0 }, - { "__signed", RID_SIGNED, 0 }, - { "__signed__", RID_SIGNED, 0 }, - { "__typeof", RID_TYPEOF, 0 }, - { "__typeof__", RID_TYPEOF, 0 }, - { "__unbounded", RID_UNBOUNDED, 0 }, - { "__unbounded__", RID_UNBOUNDED, 0 }, - { "__volatile", RID_VOLATILE, 0 }, - { "__volatile__", RID_VOLATILE, 0 }, - { "asm", RID_ASM, 0 }, - { "auto", RID_AUTO, 0 }, - { "break", RID_BREAK, 0 }, - { "case", RID_CASE, 0 }, - { "char", RID_CHAR, 0 }, - { "const", RID_CONST, 0 }, - { "continue", RID_CONTINUE, 0 }, - { "default", RID_DEFAULT, 0 }, - { "do", RID_DO, 0 }, - { "double", RID_DOUBLE, 0 }, - { "else", RID_ELSE, 0 }, - { "enum", RID_ENUM, 0 }, - { "extern", RID_EXTERN, 0 }, - { "float", RID_FLOAT, 0 }, - { "for", RID_FOR, 0 }, - { "goto", RID_GOTO, 0 }, - { "if", RID_IF, 0 }, - { "inline", RID_INLINE, 0 }, - { "int", RID_INT, 0 }, - { "long", RID_LONG, 0 }, - { "register", RID_REGISTER, 0 }, - { "restrict", RID_RESTRICT, 0 }, - { "return", RID_RETURN, 0 }, - { "short", RID_SHORT, 0 }, - { "signed", RID_SIGNED, 0 }, - { "sizeof", RID_SIZEOF, 0 }, - { "static", RID_STATIC, 0 }, - { "struct", RID_STRUCT, 0 }, - { "switch", RID_SWITCH, 0 }, - { "typedef", RID_TYPEDEF, 0 }, - { "typeof", RID_TYPEOF, 0 }, - { "union", RID_UNION, 0 }, - { "unsigned", RID_UNSIGNED, 0 }, - { "void", RID_VOID, 0 }, - { "volatile", RID_VOLATILE, 0 }, - { "while", RID_WHILE, 0 }, -}; -#define N_reswords (sizeof reswords / sizeof (struct resword)) - -/* Init enough to allow the C decl code to work, then clean up - afterwards. */ - -void -treelang_init_decl_processing () -{ - unsigned int i; - tree id; - - /* It is not necessary to register ridpointers as a GC root, because - all the trees it points to are permanently interned in the - get_identifier hash anyway. */ - ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree)); - - for (i = 0; i < N_reswords; i++) - { - id = get_identifier (reswords[i].word); - C_RID_CODE (id) = reswords[i].rid; - C_IS_RESERVED_WORD (id) = 1; - ridpointers [(int) reswords[i].rid] = id; - } - - c_init_decl_processing (); - - /* ix86_return_pops_args takes the type of these so need to patch - their own type as themselves. */ - - for (i = 0; i < itk_none; i++) - { - if (integer_types[i]) - TREE_TYPE (integer_types [i]) = integer_types[i]; - } - - /* Probably these ones too. */ - TREE_TYPE (float_type_node) = float_type_node; - TREE_TYPE (double_type_node) = double_type_node; - TREE_TYPE (long_double_type_node) = long_double_type_node; - -} - -/* Save typing debug_tree all the time. Dump a tree T pretty and - concise. */ - -void dt (tree t); - -void -dt (tree t) -{ - debug_tree (t); -} diff --git a/gcc/treelang/treetree.h b/gcc/treelang/treetree.h deleted file mode 100644 index e394ebae8e0..00000000000 --- a/gcc/treelang/treetree.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - - TREELANG Compiler definitions for interfacing to treetree.c - (compiler back end interface). - - Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! - - --------------------------------------------------------------------------- - - Written by Tim Josling 1999, 2000, 2001, based in part on other - parts of the GCC compiler. - - */ - -tree tree_code_init_parameters (void); -tree tree_code_add_parameter (tree list, tree proto_exp, tree exp); -tree tree_code_get_integer_value (unsigned char *chars, unsigned int length); -void tree_code_generate_return (tree type, tree exp); -void tree_ggc_storage_always_used (void *m); -tree tree_code_get_expression (unsigned int exp_type, tree type, tree op1, tree op2, tree op3); -tree tree_code_get_numeric_type (unsigned int size1, unsigned int sign1); -void tree_code_create_function_initial (tree prev_saved, - unsigned char* filename, int lineno, - struct prod_token_parm_item* parms); -void tree_code_create_function_wrapup (unsigned char* filename, int lineno); -tree tree_code_create_function_prototype (unsigned char* chars, - unsigned int storage_class, - unsigned int ret_type, - struct prod_token_parm_item* parms, - unsigned char* filename, - int lineno); -tree tree_code_create_variable (unsigned int storage_class, - unsigned char* chars, - unsigned int length, - unsigned int expression_type, - tree init, - unsigned char* filename, - int lineno); -void tree_code_output_expression_statement (tree code, unsigned char* filename, int lineno); -tree get_type_for_numeric_type (unsigned int numeric_type); -void tree_code_if_start (tree exp, unsigned char* filename, int lineno); -void tree_code_if_else (unsigned char* filename, int lineno); -void tree_code_if_end (unsigned char* filename, int lineno); -tree tree_code_get_type (int type_num); -void treelang_init_decl_processing (void); -void treelang_finish (void); -const char * treelang_init (const char* filename); -int treelang_decode_option (int, char **); -void treelang_parse_file (int debug_flag); -void push_var_level (void); -void pop_var_level (void); - - - -- cgit v1.2.3