diff options
34 files changed, 68 insertions, 16771 deletions
diff --git a/ChangeLog b/ChangeLog index f7381024d3d..3b8b8420d73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2008-01-25 Joseph Myers <joseph@codesourcery.com> + + * MAINTAINERS (c4x port): Remove. + 2008-01-24 David Edelsohn <edelsohn@gnu.org> * libtool.m4: Backport AIX 6 support from ToT Libtool. diff --git a/MAINTAINERS b/MAINTAINERS index d9c4bd05601..0e216ee1446 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -42,7 +42,6 @@ arm port Paul Brook paul@codesourcery.com avr port Denis Chertykov denisc@overta.ru avr port Anatoly Sokolov aesok@post.ru bfin port Bernd Schmidt bernd.schmidt@analog.com -c4x port Michael Hayes m.hayes@elec.canterbury.ac.nz cris port Hans-Peter Nilsson hp@axis.com crx port Paul Woegerer paul.woegerer@nsc.com fr30 port Nick Clifton nickc@redhat.com diff --git a/contrib/ChangeLog b/contrib/ChangeLog index d03acc998f6..1449506e509 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,8 @@ +2008-01-25 Joseph Myers <joseph@codesourcery.com> + + * paranoia.cc (main): Remove handling of c4x_single and + c4x_extended formats. + 2007-12-26 Sebastian Pop <sebastian.pop@amd.com> * compareSumTests3: Changed to GPLv3. diff --git a/contrib/paranoia.cc b/contrib/paranoia.cc index ad9f8c8fda7..ce21d3520ca 100644 --- a/contrib/paranoia.cc +++ b/contrib/paranoia.cc @@ -2643,8 +2643,6 @@ int main(int ac, char **av) F(vax_g), F(i370_single), F(i370_double), - F(c4x_single), - F(c4x_extended), F(real_internal), #undef F }; diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4ad2970ea6e..516d6855784 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2008-01-25 Joseph Myers <joseph@codesourcery.com> + + * config/c4x: Remove directory. + * config.gcc (crx-*, mt-*): Mark obsolete. + (c4x-*, tic4x-*, c4x-*-rtems*, tic4x-*-rtems*, c4x-*, tic4x-*, + h8300-*-rtemscoff*, ns32k-*-netbsdelf*, ns32k-*-netbsd*, + sh-*-rtemscoff*): Remove cases. + * defaults.h (C4X_FLOAT_FORMAT): Remove. + * real.c (encode_c4x_single, decode_c4x_single, + encode_c4x_extended, decode_c4x_extended, c4x_single_format, + c4x_extended_format): Remove. + * real.h (c4x_single_format, c4x_extended_format): Remove. + * doc/extend.texi (interrupt, naked): Remove mention of attributes + on C4x. + (Pragmas): Remove comment about c4x pragmas. + * doc/install.texi (c4x): Remove target-specific instructions. + * doc/invoke.texi (TMS320C3x/C4x Options): Remove. + * doc/md.texi (Machine Constraints): Remove C4x documentation. + * doc/tm.texi (MEMBER_TYPE_FORCES_BLK, c_register_pragma): Do not + refer to C4x source files as examples. + (C4X_FLOAT_FORMAT): Remove documentation. + 2008-01-25 Bernd Schmidt <bernd.schmidt@analog.com> * config/bfin/bfin.c (override_options): Reorder tests so that diff --git a/gcc/config.gcc b/gcc/config.gcc index edb0c8eea16..555e2eb1d2f 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1,6 +1,6 @@ # GCC target-specific configuration file. -# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 -# Free Software Foundation, Inc. +# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +# 2008 Free Software Foundation, Inc. #This file is part of GCC. @@ -195,8 +195,8 @@ md_file= # Obsolete configurations. case ${target} in - c4x-* \ - | tic4x-* \ + crx-* \ + | mt-* \ ) if test "x$enable_obsolete" != xyes; then echo "*** Configuration ${target} is obsolete." >&2 @@ -351,9 +351,6 @@ sh[123456789lbe]*-*-*) cpu_type=sh need_64bit_hwint=yes ;; -tic4x-*-*) - cpu_type=c4x - ;; esac tm_file=${cpu_type}/${cpu_type}.h @@ -830,17 +827,6 @@ bfin*-*) tmake_file=bfin/t-bfin use_collect2=no ;; -c4x-*-rtems* | tic4x-*-rtems*) - tmake_file="c4x/t-c4x t-rtems c4x/t-rtems" - tm_file="c4x/c4x.h c4x/rtems.h rtems.h" - c_target_objs="c4x-c.o" - cxx_target_objs="c4x-c.o" - ;; -c4x-* | tic4x-*) - tmake_file=c4x/t-c4x - c_target_objs="c4x-c.o" - cxx_target_objs="c4x-c.o" - ;; cris-*-aout) tm_file="dbxelf.h ${tm_file} cris/aout.h" gas=yes @@ -895,10 +881,6 @@ frv-*-*linux*) linux.h frv/linux.h frv/frv-abi.h" tmake_file="${tmake_file} frv/t-frv frv/t-linux" ;; -h8300-*-rtemscoff*) - tmake_file="h8300/t-h8300 t-rtems h8300/t-rtems" - tm_file="h8300/h8300.h dbxcoff.h h8300/coff.h h8300/rtems.h rtems.h" - ;; h8300-*-rtems*) tmake_file="h8300/t-h8300 h8300/t-elf t-rtems h8300/t-rtems" tm_file="h8300/h8300.h dbxelf.h elfos.h h8300/elf.h h8300/rtems.h rtems.h" @@ -1828,16 +1810,6 @@ mt-*-elf) tm_file="dbxelf.h elfos.h svr4.h ${tm_file}" tmake_file="${tmake_file} mt/t-mt" ;; -ns32k-*-netbsdelf*) - echo "GCC does not yet support the ${target} target"; exit 1 - ;; -ns32k-*-netbsd*) - tm_file="${tm_file} netbsd.h netbsd-aout.h ns32k/netbsd.h" - # On NetBSD, the headers are already okay, except for math.h. - tmake_file="t-netbsd ns32k/t-ns32k" - extra_parts="" - use_collect2=yes - ;; pdp11-*-bsd) tm_file="${tm_file} pdp11/2bsd.h" use_fixproto=yes @@ -2304,10 +2276,6 @@ sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \ fi use_fixproto=yes ;; -sh-*-rtemscoff*) - tmake_file="sh/t-sh t-rtems sh/t-rtems" - tm_file="${tm_file} dbxcoff.h sh/coff.h sh/rtems.h rtems.h" - ;; sh-*-rtems*) tmake_file="sh/t-sh sh/t-elf t-rtems sh/t-rtems" tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/elf.h sh/embed-elf.h sh/rtemself.h rtems.h" diff --git a/gcc/config/c4x/c4x-c.c b/gcc/config/c4x/c4x-c.c deleted file mode 100644 index 3e132b5d9fd..00000000000 --- a/gcc/config/c4x/c4x-c.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Subroutines for the C front end on the TMS320C[34]x - Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2007 Free Software Foundation, Inc. - - Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) - and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "tree.h" -#include "toplev.h" -#include "cpplib.h" -#include "c-pragma.h" -#include "tm_p.h" - -static int c4x_parse_pragma (const char *, tree *, tree *); - -/* Handle machine specific pragmas for compatibility with existing - compilers for the C3x/C4x. - - pragma attribute - ---------------------------------------------------------- - CODE_SECTION(symbol,"section") section("section") - DATA_SECTION(symbol,"section") section("section") - FUNC_CANNOT_INLINE(function) - FUNC_EXT_CALLED(function) - FUNC_IS_PURE(function) const - FUNC_IS_SYSTEM(function) - FUNC_NEVER_RETURNS(function) noreturn - FUNC_NO_GLOBAL_ASG(function) - FUNC_NO_IND_ASG(function) - INTERRUPT(function) interrupt - - */ - -/* Parse a C4x pragma, of the form ( function [, "section"] ) \n. - FUNC is loaded with the IDENTIFIER_NODE of the function, SECT with - the STRING_CST node of the string. If SECT is null, then this - pragma doesn't take a section string. Returns 0 for a good pragma, - -1 for a malformed pragma. */ -#define BAD(gmsgid, arg) \ - do { warning (OPT_Wpragmas, gmsgid, arg); return -1; } while (0) - -static int -c4x_parse_pragma (const char *name, tree *func, tree *sect) -{ - tree f, s, x; - - if (pragma_lex (&x) != CPP_OPEN_PAREN) - BAD ("missing '(' after '#pragma %s' - ignored", name); - - if (pragma_lex (&f) != CPP_NAME) - BAD ("missing function name in '#pragma %s' - ignored", name); - - if (sect) - { - if (pragma_lex (&x) != CPP_COMMA) - BAD ("malformed '#pragma %s' - ignored", name); - if (pragma_lex (&s) != CPP_STRING) - BAD ("missing section name in '#pragma %s' - ignored", name); - *sect = s; - } - - if (pragma_lex (&x) != CPP_CLOSE_PAREN) - BAD ("missing ')' for '#pragma %s' - ignored", name); - - if (pragma_lex (&x) != CPP_EOF) - warning (OPT_Wpragmas, "junk at end of '#pragma %s'", name); - - *func = f; - return 0; -} - -void -c4x_pr_CODE_SECTION (cpp_reader *pfile ATTRIBUTE_UNUSED) -{ - tree func, sect; - - if (c4x_parse_pragma ("CODE_SECTION", &func, §)) - return; - code_tree = chainon (code_tree, - build_tree_list (func, - build_tree_list (NULL_TREE, sect))); -} - -void -c4x_pr_DATA_SECTION (cpp_reader *pfile ATTRIBUTE_UNUSED) -{ - tree func, sect; - - if (c4x_parse_pragma ("DATA_SECTION", &func, §)) - return; - data_tree = chainon (data_tree, - build_tree_list (func, - build_tree_list (NULL_TREE, sect))); -} - -void -c4x_pr_FUNC_IS_PURE (cpp_reader *pfile ATTRIBUTE_UNUSED) -{ - tree func; - - if (c4x_parse_pragma ("FUNC_IS_PURE", &func, 0)) - return; - pure_tree = chainon (pure_tree, build_tree_list (func, NULL_TREE)); -} - -void -c4x_pr_FUNC_NEVER_RETURNS (cpp_reader *pfile ATTRIBUTE_UNUSED) -{ - tree func; - - if (c4x_parse_pragma ("FUNC_NEVER_RETURNS", &func, 0)) - return; - noreturn_tree = chainon (noreturn_tree, build_tree_list (func, NULL_TREE)); -} - -void -c4x_pr_INTERRUPT (cpp_reader *pfile ATTRIBUTE_UNUSED) -{ - tree func; - - if (c4x_parse_pragma ("INTERRUPT", &func, 0)) - return; - interrupt_tree = chainon (interrupt_tree, build_tree_list (func, NULL_TREE)); -} - -/* Used for FUNC_CANNOT_INLINE, FUNC_EXT_CALLED, FUNC_IS_SYSTEM, - FUNC_NO_GLOBAL_ASG, and FUNC_NO_IND_ASG. */ -void -c4x_pr_ignored (cpp_reader *pfile ATTRIBUTE_UNUSED) -{ -} diff --git a/gcc/config/c4x/c4x-modes.def b/gcc/config/c4x/c4x-modes.def deleted file mode 100644 index 57bfd1267ff..00000000000 --- a/gcc/config/c4x/c4x-modes.def +++ /dev/null @@ -1,108 +0,0 @@ -/* Definitions of target machine for GNU compiler. TMS320C[34]x - Copyright (C) 2002, 2004, 2007 Free Software Foundation, Inc. - - Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) - and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -/* C4x wants 1- and 2-word float modes, in its own peculiar format. - FIXME: Give this port a way to get rid of SFmode, DFmode, and all - the other modes it doesn't use. */ -FLOAT_MODE (QF, 1, c4x_single_format); -FLOAT_MODE (HF, 2, c4x_extended_format); -RESET_FLOAT_FORMAT (SF, 0); /* not used */ -RESET_FLOAT_FORMAT (DF, 0); /* not used */ - -/* Add any extra modes needed to represent the condition code. - - On the C4x, we have a "no-overflow" mode which is used when an ADD, - SUB, NEG, or MPY insn is used to set the condition code. This is - to prevent the combiner from optimizing away a following CMP of the - result with zero when a signed conditional branch or load insn - follows. - - The problem is a subtle one and deals with the manner in which the - negative condition (N) flag is used on the C4x. This flag does not - reflect the status of the actual result but of the ideal result had - no overflow occurred (when considering signed operands). - - For example, 0x7fffffff + 1 => 0x80000000 Z=0 V=1 N=0 C=0. Here - the flags reflect the untruncated result, not the actual result. - While the actual result is less than zero, the N flag is not set - since the ideal result of the addition without truncation would - have been positive. - - Note that the while the N flag is handled differently to most other - architectures, the use of it is self consistent and is not the - cause of the problem. - - Logical operations set the N flag to the MSB of the result so if - the result is negative, N is 1. However, integer and floating - point operations set the N flag to be the MSB of the result - exclusive ored with the overflow (V) flag. Thus if an overflow - occurs and the result does not have the MSB set (i.e., the result - looks like a positive number), the N flag is set. Conversely, if - an overflow occurs and the MSB of the result is set, N is set to 0. - Thus the N flag represents the sign of the result if it could have - been stored without overflow but does not represent the apparent - sign of the result. Note that most architectures set the N flag to - be the MSB of the result. - - The C4x approach to setting the N flag simplifies signed - conditional branches and loads which only have to test the state of - the N flag, whereas most architectures have to look at both the N - and V flags. The disadvantage is that there is no flag giving the - status of the sign bit of the operation. However, there are no - conditional load or branch instructions that make use of this - feature (e.g., BMI---branch minus) instruction. Note that BN and - BLT are identical in the C4x. - - To handle the problem where the N flag is set differently whenever - there is an overflow we use a different CC mode, CC_NOOVmode which - says that the CC reflects the comparison of the result against zero - if no overflow occurred. - - For example, - - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" "")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "") - (minus:QI (match_dup 1) - (match_dup 2)))] - - Note that there is no problem for insns that don't return a result - like CMP, since the CC reflects the effect of operation. - - An example of a potential problem is when GCC - converts (LTU (MINUS (0x80000000) (0x7fffffff) (0x80000000))) - to (LEU (MINUS (0x80000000) (0x7fffffff) (0x7fffffff))) - to (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000))) - - Now (MINUS (0x80000000) (0x7fffffff)) returns 0x00000001 but the - C4x sets the N flag since the result without overflow would have - been 0xffffffff when treating the operands as signed integers. - Thus (GE (MINUS (0x80000000) (0x7fffffff) (0x00000000))) sets the N - flag but (GE (0x00000001)) does not set the N flag. - - The upshot is that we cannot use signed branch and conditional - load instructions after an add, subtract, neg, abs or multiply. - We must emit a compare insn to check the result against 0. */ - -CC_MODE (CC_NOOV); diff --git a/gcc/config/c4x/c4x-protos.h b/gcc/config/c4x/c4x-protos.h deleted file mode 100644 index 78542f9a433..00000000000 --- a/gcc/config/c4x/c4x-protos.h +++ /dev/null @@ -1,246 +0,0 @@ -/* Definitions of target machine for GNU compiler. TMS320C[34]x - Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2004, 2005, - 2007 Free Software Foundation, Inc. - - Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) - and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -#ifndef GCC_C4X_PROTOS_H -#define GCC_C4X_PROTOS_H - -extern void c4x_override_options (void); - -extern void c4x_optimization_options (int, int); - -extern void c4x_output_ascii (FILE *, const char *, int); - -extern int c4x_interrupt_function_p (void); - -extern void c4x_expand_prologue (void); - -extern void c4x_expand_epilogue (void); - -extern int c4x_null_epilogue_p (void); - -extern void c4x_global_label (const char *); - -extern void c4x_external_ref (const char *); - -#ifdef TREE_CODE -extern void c4x_function_arg_advance (CUMULATIVE_ARGS *, - enum machine_mode, tree, int); - -extern struct rtx_def *c4x_function_arg (CUMULATIVE_ARGS *, - enum machine_mode, tree, int); - -#endif /* TREE_CODE */ - - -#if defined(RTX_CODE) && defined(TREE_CODE) -extern void c4x_init_cumulative_args (CUMULATIVE_ARGS *c, tree, rtx); - -extern rtx c4x_expand_builtin (tree, rtx, rtx, enum machine_mode, int); - -extern void c4x_init_builtins (void); - -#endif /* TREE_CODE and RTX_CODE*/ - - -#ifdef RTX_CODE -extern struct rtx_def *c4x_gen_compare_reg (enum rtx_code, rtx, rtx); - -extern int c4x_legitimate_address_p (enum machine_mode, rtx, int); - -extern int c4x_hard_regno_mode_ok (unsigned int, enum machine_mode); - -extern int c4x_hard_regno_rename_ok (unsigned int, unsigned int); - -extern struct rtx_def *c4x_legitimize_address (rtx, enum machine_mode); - -extern void c4x_print_operand (FILE *, rtx, int); - -extern void c4x_print_operand_address (FILE *, rtx); - -extern enum reg_class c4x_preferred_reload_class (rtx, enum reg_class); - -extern struct rtx_def *c4x_operand_subword (rtx, int, int, enum machine_mode); - -extern char *c4x_output_cbranch (const char *, rtx); - -extern int c4x_label_conflict (rtx, rtx, rtx); - -extern int c4x_address_conflict (rtx, rtx, int, int); - -extern void c4x_rptb_insert (rtx insn); - -extern int c4x_rptb_nop_p (rtx); - -extern int c4x_rptb_rpts_p (rtx, rtx); - -extern int c4x_check_laj_p (rtx); - -extern int c4x_autoinc_operand (rtx, enum machine_mode); - -extern int reg_or_const_operand (rtx, enum machine_mode); - -extern int mixed_subreg_operand (rtx, enum machine_mode); - -extern int reg_imm_operand (rtx, enum machine_mode); - -extern int ar0_reg_operand (rtx, enum machine_mode); - -extern int ar0_mem_operand (rtx, enum machine_mode); - -extern int ar1_reg_operand (rtx, enum machine_mode); - -extern int ar1_mem_operand (rtx, enum machine_mode); - -extern int ar2_reg_operand (rtx, enum machine_mode); - -extern int ar2_mem_operand (rtx, enum machine_mode); - -extern int ar3_reg_operand (rtx, enum machine_mode); - -extern int ar3_mem_operand (rtx, enum machine_mode); - -extern int ar4_reg_operand (rtx, enum machine_mode); - -extern int ar4_mem_operand (rtx, enum machine_mode); - -extern int ar5_reg_operand (rtx, enum machine_mode); - -extern int ar5_mem_operand (rtx, enum machine_mode); - -extern int ar6_reg_operand (rtx, enum machine_mode); - -extern int ar6_mem_operand (rtx, enum machine_mode); - -extern int ar7_reg_operand (rtx, enum machine_mode); - -extern int ar7_mem_operand (rtx, enum machine_mode); - -extern int ir0_reg_operand (rtx, enum machine_mode); - -extern int ir0_mem_operand (rtx, enum machine_mode); - -extern int ir1_reg_operand (rtx, enum machine_mode); - -extern int ir1_mem_operand (rtx, enum machine_mode); - -extern int group1_reg_operand (rtx, enum machine_mode); - -extern int group1_mem_operand (rtx, enum machine_mode); - -extern int arx_reg_operand (rtx, enum machine_mode); - -extern int not_rc_reg (rtx, enum machine_mode); - -extern int not_modify_reg (rtx, enum machine_mode); - -extern int c4x_shiftable_constant (rtx); - -extern int c4x_immed_float_p (rtx); - -extern int c4x_a_register (rtx); - -extern int c4x_x_register (rtx); - -extern int c4x_H_constant (rtx); - -extern int c4x_I_constant (rtx); - -extern int c4x_J_constant (rtx); - -extern int c4x_K_constant (rtx); - -extern int c4x_L_constant (rtx); - -extern int c4x_N_constant (rtx); - -extern int c4x_O_constant (rtx); - -extern int c4x_Q_constraint (rtx); - -extern int c4x_R_constraint (rtx); - -extern int c4x_S_indirect (rtx); - -extern int c4x_S_constraint (rtx); - -extern int c4x_T_constraint (rtx); - -extern int c4x_U_constraint (rtx); - -extern void c4x_emit_libcall (rtx, enum rtx_code, enum machine_mode, - enum machine_mode, int, rtx *); - -extern void c4x_emit_libcall3 (rtx, enum rtx_code, enum machine_mode, rtx *); - -extern void c4x_emit_libcall_mulhi (rtx, enum rtx_code, - enum machine_mode, rtx *); - -extern int c4x_emit_move_sequence (rtx *, enum machine_mode); - -extern int legitimize_operands (enum rtx_code, rtx *, enum machine_mode); - -extern int valid_operands (enum rtx_code, rtx *, enum machine_mode); - -extern int valid_parallel_load_store (rtx *, enum machine_mode); - -extern int valid_parallel_operands_4 (rtx *, enum machine_mode); - -extern int valid_parallel_operands_5 (rtx *, enum machine_mode); - -extern int valid_parallel_operands_6 (rtx *, enum machine_mode); - -extern GTY(()) rtx smulhi3_libfunc; -extern GTY(()) rtx umulhi3_libfunc; -extern GTY(()) rtx fix_truncqfhi2_libfunc; -extern GTY(()) rtx fixuns_truncqfhi2_libfunc; -extern GTY(()) rtx fix_trunchfhi2_libfunc; -extern GTY(()) rtx fixuns_trunchfhi2_libfunc; -extern GTY(()) rtx floathiqf2_libfunc; -extern GTY(()) rtx floatunshiqf2_libfunc; -extern GTY(()) rtx floathihf2_libfunc; -extern GTY(()) rtx floatunshihf2_libfunc; - -extern GTY(()) rtx c4x_compare_op0; /* Operand 0 for comparisons. */ -extern GTY(()) rtx c4x_compare_op1; /* Operand 1 for comparisons. */ - -#endif /* RTX_CODE */ - -/* Smallest class containing REGNO. */ -extern enum reg_class c4x_regclass_map[FIRST_PSEUDO_REGISTER]; -extern enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER]; - -extern void c4x_pr_CODE_SECTION (struct cpp_reader *); -extern void c4x_pr_DATA_SECTION (struct cpp_reader *); -extern void c4x_pr_FUNC_IS_PURE (struct cpp_reader *); -extern void c4x_pr_FUNC_NEVER_RETURNS (struct cpp_reader *); -extern void c4x_pr_INTERRUPT (struct cpp_reader *); -extern void c4x_pr_ignored (struct cpp_reader *); -extern void c4x_init_pragma (int (*) (tree *)); - -extern GTY(()) tree code_tree; -extern GTY(()) tree data_tree; -extern GTY(()) tree pure_tree; -extern GTY(()) tree noreturn_tree; -extern GTY(()) tree interrupt_tree; - -#endif /* ! GCC_C4X_PROTOS_H */ diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c deleted file mode 100644 index 3cef36b4b39..00000000000 --- a/gcc/config/c4x/c4x.c +++ /dev/null @@ -1,4618 +0,0 @@ -/* Subroutines for assembler code output on the TMS320C[34]x - Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, - 2004, 2005, 2006, 2007 - Free Software Foundation, Inc. - - Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) - and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -/* Some output-actions in c4x.md need these. */ -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "tree.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "basic-block.h" -#include "real.h" -#include "insn-config.h" -#include "insn-attr.h" -#include "conditions.h" -#include "output.h" -#include "function.h" -#include "expr.h" -#include "optabs.h" -#include "libfuncs.h" -#include "flags.h" -#include "recog.h" -#include "ggc.h" -#include "cpplib.h" -#include "toplev.h" -#include "tm_p.h" -#include "target.h" -#include "target-def.h" -#include "langhooks.h" - -rtx smulhi3_libfunc; -rtx umulhi3_libfunc; -rtx fix_truncqfhi2_libfunc; -rtx fixuns_truncqfhi2_libfunc; -rtx fix_trunchfhi2_libfunc; -rtx fixuns_trunchfhi2_libfunc; -rtx floathiqf2_libfunc; -rtx floatunshiqf2_libfunc; -rtx floathihf2_libfunc; -rtx floatunshihf2_libfunc; - -static int c4x_leaf_function; - -static const char *const float_reg_names[] = FLOAT_REGISTER_NAMES; - -/* Array of the smallest class containing reg number REGNO, indexed by - REGNO. Used by REGNO_REG_CLASS in c4x.h. We assume that all these - registers are available and set the class to NO_REGS for registers - that the target switches say are unavailable. */ - -enum reg_class c4x_regclass_map[FIRST_PSEUDO_REGISTER] = -{ - /* Reg Modes Saved. */ - R0R1_REGS, /* R0 QI, QF, HF No. */ - R0R1_REGS, /* R1 QI, QF, HF No. */ - R2R3_REGS, /* R2 QI, QF, HF No. */ - R2R3_REGS, /* R3 QI, QF, HF No. */ - EXT_LOW_REGS, /* R4 QI, QF, HF QI. */ - EXT_LOW_REGS, /* R5 QI, QF, HF QI. */ - EXT_LOW_REGS, /* R6 QI, QF, HF QF. */ - EXT_LOW_REGS, /* R7 QI, QF, HF QF. */ - ADDR_REGS, /* AR0 QI No. */ - ADDR_REGS, /* AR1 QI No. */ - ADDR_REGS, /* AR2 QI No. */ - ADDR_REGS, /* AR3 QI QI. */ - ADDR_REGS, /* AR4 QI QI. */ - ADDR_REGS, /* AR5 QI QI. */ - ADDR_REGS, /* AR6 QI QI. */ - ADDR_REGS, /* AR7 QI QI. */ - DP_REG, /* DP QI No. */ - INDEX_REGS, /* IR0 QI No. */ - INDEX_REGS, /* IR1 QI No. */ - BK_REG, /* BK QI QI. */ - SP_REG, /* SP QI No. */ - ST_REG, /* ST CC No. */ - NO_REGS, /* DIE/IE No. */ - NO_REGS, /* IIE/IF No. */ - NO_REGS, /* IIF/IOF No. */ - INT_REGS, /* RS QI No. */ - INT_REGS, /* RE QI No. */ - RC_REG, /* RC QI No. */ - EXT_REGS, /* R8 QI, QF, HF QI. */ - EXT_REGS, /* R9 QI, QF, HF No. */ - EXT_REGS, /* R10 QI, QF, HF No. */ - EXT_REGS, /* R11 QI, QF, HF No. */ -}; - -enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER] = -{ - /* Reg Modes Saved. */ - HFmode, /* R0 QI, QF, HF No. */ - HFmode, /* R1 QI, QF, HF No. */ - HFmode, /* R2 QI, QF, HF No. */ - HFmode, /* R3 QI, QF, HF No. */ - QFmode, /* R4 QI, QF, HF QI. */ - QFmode, /* R5 QI, QF, HF QI. */ - QImode, /* R6 QI, QF, HF QF. */ - QImode, /* R7 QI, QF, HF QF. */ - QImode, /* AR0 QI No. */ - QImode, /* AR1 QI No. */ - QImode, /* AR2 QI No. */ - QImode, /* AR3 QI QI. */ - QImode, /* AR4 QI QI. */ - QImode, /* AR5 QI QI. */ - QImode, /* AR6 QI QI. */ - QImode, /* AR7 QI QI. */ - VOIDmode, /* DP QI No. */ - QImode, /* IR0 QI No. */ - QImode, /* IR1 QI No. */ - QImode, /* BK QI QI. */ - VOIDmode, /* SP QI No. */ - VOIDmode, /* ST CC No. */ - VOIDmode, /* DIE/IE No. */ - VOIDmode, /* IIE/IF No. */ - VOIDmode, /* IIF/IOF No. */ - QImode, /* RS QI No. */ - QImode, /* RE QI No. */ - VOIDmode, /* RC QI No. */ - QFmode, /* R8 QI, QF, HF QI. */ - HFmode, /* R9 QI, QF, HF No. */ - HFmode, /* R10 QI, QF, HF No. */ - HFmode, /* R11 QI, QF, HF No. */ -}; - - -/* Test and compare insns in c4x.md store the information needed to - generate branch and scc insns here. */ - -rtx c4x_compare_op0; -rtx c4x_compare_op1; - -int c4x_cpu_version = 40; /* CPU version C30/31/32/33/40/44. */ - -/* Pragma definitions. */ - -tree code_tree = NULL_TREE; -tree data_tree = NULL_TREE; -tree pure_tree = NULL_TREE; -tree noreturn_tree = NULL_TREE; -tree interrupt_tree = NULL_TREE; -tree naked_tree = NULL_TREE; - -/* Forward declarations */ -static bool c4x_handle_option (size_t, const char *, int); -static int c4x_isr_reg_used_p (unsigned int); -static int c4x_leaf_function_p (void); -static int c4x_naked_function_p (void); -static int c4x_immed_int_constant (rtx); -static int c4x_immed_float_constant (rtx); -static int c4x_R_indirect (rtx); -static void c4x_S_address_parse (rtx , int *, int *, int *, int *); -static int c4x_valid_operands (enum rtx_code, rtx *, enum machine_mode, int); -static int c4x_arn_reg_operand (rtx, enum machine_mode, unsigned int); -static int c4x_arn_mem_operand (rtx, enum machine_mode, unsigned int); -static void c4x_file_start (void); -static void c4x_file_end (void); -static void c4x_check_attribute (const char *, tree, tree, tree *); -static int c4x_r11_set_p (rtx); -static int c4x_rptb_valid_p (rtx, rtx); -static void c4x_reorg (void); -static int c4x_label_ref_used_p (rtx, rtx); -static tree c4x_handle_fntype_attribute (tree *, tree, tree, int, bool *); -const struct attribute_spec c4x_attribute_table[]; -static void c4x_insert_attributes (tree, tree *); -static void c4x_asm_named_section (const char *, unsigned int, tree); -static int c4x_adjust_cost (rtx, rtx, rtx, int); -static void c4x_globalize_label (FILE *, const char *); -static bool c4x_rtx_costs (rtx, int, int, int *); -static int c4x_address_cost (rtx); -static void c4x_init_libfuncs (void); -static void c4x_external_libcall (rtx); -static rtx c4x_struct_value_rtx (tree, int); -static tree c4x_gimplify_va_arg_expr (tree, tree, tree *, tree *); - -/* Initialize the GCC target structure. */ -#undef TARGET_ASM_BYTE_OP -#define TARGET_ASM_BYTE_OP "\t.word\t" -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP NULL -#undef TARGET_ASM_ALIGNED_SI_OP -#define TARGET_ASM_ALIGNED_SI_OP NULL -#undef TARGET_ASM_FILE_START -#define TARGET_ASM_FILE_START c4x_file_start -#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE -#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true -#undef TARGET_ASM_FILE_END -#define TARGET_ASM_FILE_END c4x_file_end - -#undef TARGET_ASM_EXTERNAL_LIBCALL -#define TARGET_ASM_EXTERNAL_LIBCALL c4x_external_libcall - -/* Play safe, not the fastest code. */ -#undef TARGET_DEFAULT_TARGET_FLAGS -#define TARGET_DEFAULT_TARGET_FLAGS (MASK_ALIASES | MASK_PARALLEL \ - | MASK_PARALLEL_MPY | MASK_RPTB) -#undef TARGET_HANDLE_OPTION -#define TARGET_HANDLE_OPTION c4x_handle_option - -#undef TARGET_ATTRIBUTE_TABLE -#define TARGET_ATTRIBUTE_TABLE c4x_attribute_table - -#undef TARGET_INSERT_ATTRIBUTES -#define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes - -#undef TARGET_INIT_BUILTINS -#define TARGET_INIT_BUILTINS c4x_init_builtins - -#undef TARGET_EXPAND_BUILTIN -#define TARGET_EXPAND_BUILTIN c4x_expand_builtin - -#undef TARGET_SCHED_ADJUST_COST -#define TARGET_SCHED_ADJUST_COST c4x_adjust_cost - -#undef TARGET_ASM_GLOBALIZE_LABEL -#define TARGET_ASM_GLOBALIZE_LABEL c4x_globalize_label - -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS c4x_rtx_costs -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST c4x_address_cost - -#undef TARGET_MACHINE_DEPENDENT_REORG -#define TARGET_MACHINE_DEPENDENT_REORG c4x_reorg - -#undef TARGET_INIT_LIBFUNCS -#define TARGET_INIT_LIBFUNCS c4x_init_libfuncs - -#undef TARGET_STRUCT_VALUE_RTX -#define TARGET_STRUCT_VALUE_RTX c4x_struct_value_rtx - -#undef TARGET_GIMPLIFY_VA_ARG_EXPR -#define TARGET_GIMPLIFY_VA_ARG_EXPR c4x_gimplify_va_arg_expr - -struct gcc_target targetm = TARGET_INITIALIZER; - -/* Implement TARGET_HANDLE_OPTION. */ - -static bool -c4x_handle_option (size_t code, const char *arg, int value) -{ - switch (code) - { - case OPT_m30: c4x_cpu_version = 30; return true; - case OPT_m31: c4x_cpu_version = 31; return true; - case OPT_m32: c4x_cpu_version = 32; return true; - case OPT_m33: c4x_cpu_version = 33; return true; - case OPT_m40: c4x_cpu_version = 40; return true; - case OPT_m44: c4x_cpu_version = 44; return true; - - case OPT_mcpu_: - if (arg[0] == 'c' || arg[0] == 'C') - arg++; - value = atoi (arg); - switch (value) - { - case 30: case 31: case 32: case 33: case 40: case 44: - c4x_cpu_version = value; - return true; - } - return false; - - default: - return true; - } -} - -/* Override command line options. - Called once after all options have been parsed. - Mostly we process the processor - type and sometimes adjust other TARGET_ options. */ - -void -c4x_override_options (void) -{ - /* Convert foo / 8.0 into foo * 0.125, etc. */ - set_fast_math_flags (1); - - /* We should phase out the following at some stage. - This provides compatibility with the old -mno-aliases option. */ - if (! TARGET_ALIASES && ! flag_argument_noalias) - flag_argument_noalias = 1; - - if (!TARGET_C3X) - target_flags |= MASK_MPYI | MASK_DB; - - if (optimize < 2) - target_flags &= ~(MASK_RPTB | MASK_PARALLEL); - - if (!TARGET_PARALLEL) - target_flags &= ~MASK_PARALLEL_MPY; -} - - -/* This is called before c4x_override_options. */ - -void -c4x_optimization_options (int level ATTRIBUTE_UNUSED, - int size ATTRIBUTE_UNUSED) -{ - /* Scheduling before register allocation can screw up global - register allocation, especially for functions that use MPY||ADD - instructions. The benefit we gain we get by scheduling before - register allocation is probably marginal anyhow. */ - flag_schedule_insns = 0; -} - - -/* Write an ASCII string. */ - -#define C4X_ASCII_LIMIT 40 - -void -c4x_output_ascii (FILE *stream, const char *ptr, int len) -{ - char sbuf[C4X_ASCII_LIMIT + 1]; - int s, l, special, first = 1, onlys; - - if (len) - fprintf (stream, "\t.byte\t"); - - for (s = l = 0; len > 0; --len, ++ptr) - { - onlys = 0; - - /* Escape " and \ with a \". */ - special = *ptr == '\"' || *ptr == '\\'; - - /* If printable - add to buff. */ - if ((! TARGET_TI || ! special) && *ptr >= 0x20 && *ptr < 0x7f) - { - if (special) - sbuf[s++] = '\\'; - sbuf[s++] = *ptr; - if (s < C4X_ASCII_LIMIT - 1) - continue; - onlys = 1; - } - if (s) - { - if (first) - first = 0; - else - { - fputc (',', stream); - l++; - } - - sbuf[s] = 0; - fprintf (stream, "\"%s\"", sbuf); - l += s + 2; - if (TARGET_TI && l >= 80 && len > 1) - { - fprintf (stream, "\n\t.byte\t"); - first = 1; - l = 0; - } - - s = 0; - } - if (onlys) - continue; - - if (first) - first = 0; - else - { - fputc (',', stream); - l++; - } - - fprintf (stream, "%d", *ptr); - l += 3; - if (TARGET_TI && l >= 80 && len > 1) - { - fprintf (stream, "\n\t.byte\t"); - first = 1; - l = 0; - } - } - if (s) - { - if (! first) - fputc (',', stream); - - sbuf[s] = 0; - fprintf (stream, "\"%s\"", sbuf); - s = 0; - } - fputc ('\n', stream); -} - - -int -c4x_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) -{ - switch (mode) - { -#if Pmode != QImode - case Pmode: /* Pointer (24/32 bits). */ -#endif - case QImode: /* Integer (32 bits). */ - return IS_INT_REGNO (regno); - - case QFmode: /* Float, Double (32 bits). */ - case HFmode: /* Long Double (40 bits). */ - return IS_EXT_REGNO (regno); - - case CCmode: /* Condition Codes. */ - case CC_NOOVmode: /* Condition Codes. */ - return IS_ST_REGNO (regno); - - case HImode: /* Long Long (64 bits). */ - /* We need two registers to store long longs. Note that - it is much easier to constrain the first register - to start on an even boundary. */ - return IS_INT_REGNO (regno) - && IS_INT_REGNO (regno + 1) - && (regno & 1) == 0; - - default: - return 0; /* We don't support these modes. */ - } - - return 0; -} - -/* Return nonzero if REGNO1 can be renamed to REGNO2. */ -int -c4x_hard_regno_rename_ok (unsigned int regno1, unsigned int regno2) -{ - /* We cannot copy call saved registers from mode QI into QF or from - mode QF into QI. */ - if (IS_FLOAT_CALL_SAVED_REGNO (regno1) && IS_INT_CALL_SAVED_REGNO (regno2)) - return 0; - if (IS_INT_CALL_SAVED_REGNO (regno1) && IS_FLOAT_CALL_SAVED_REGNO (regno2)) - return 0; - /* We cannot copy from an extended (40 bit) register to a standard - (32 bit) register because we only set the condition codes for - extended registers. */ - if (IS_EXT_REGNO (regno1) && ! IS_EXT_REGNO (regno2)) - return 0; - if (IS_EXT_REGNO (regno2) && ! IS_EXT_REGNO (regno1)) - return 0; - return 1; -} - -/* The TI C3x C compiler register argument runtime model uses 6 registers, - AR2, R2, R3, RC, RS, RE. - - The first two floating point arguments (float, double, long double) - that are found scanning from left to right are assigned to R2 and R3. - - The remaining integer (char, short, int, long) or pointer arguments - are assigned to the remaining registers in the order AR2, R2, R3, - RC, RS, RE when scanning left to right, except for the last named - argument prior to an ellipsis denoting variable number of - arguments. We don't have to worry about the latter condition since - function.c treats the last named argument as anonymous (unnamed). - - All arguments that cannot be passed in registers are pushed onto - the stack in reverse order (right to left). GCC handles that for us. - - c4x_init_cumulative_args() is called at the start, so we can parse - the args to see how many floating point arguments and how many - integer (or pointer) arguments there are. c4x_function_arg() is - then called (sometimes repeatedly) for each argument (parsed left - to right) to obtain the register to pass the argument in, or zero - if the argument is to be passed on the stack. Once the compiler is - happy, c4x_function_arg_advance() is called. - - Don't use R0 to pass arguments in, we use 0 to indicate a stack - argument. */ - -static const int c4x_int_reglist[3][6] = -{ - {AR2_REGNO, R2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO}, - {AR2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0}, - {AR2_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0, 0} -}; - -static const int c4x_fp_reglist[2] = {R2_REGNO, R3_REGNO}; - - -/* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a - function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ - -void -c4x_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname) -{ - tree param, next_param; - - cum->floats = cum->ints = 0; - cum->init = 0; - cum->var = 0; - cum->args = 0; - - if (TARGET_DEBUG) - { - fprintf (stderr, "\nc4x_init_cumulative_args ("); - if (fntype) - { - tree ret_type = TREE_TYPE (fntype); - - fprintf (stderr, "fntype code = %s, ret code = %s", - tree_code_name[(int) TREE_CODE (fntype)], - tree_code_name[(int) TREE_CODE (ret_type)]); - } - else - fprintf (stderr, "no fntype"); - - if (libname) - fprintf (stderr, ", libname = %s", XSTR (libname, 0)); - } - - cum->prototype = (fntype && TYPE_ARG_TYPES (fntype)); - - for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0; - param; param = next_param) - { - tree type; - - next_param = TREE_CHAIN (param); - - type = TREE_VALUE (param); - if (type && type != void_type_node) - { - enum machine_mode mode; - - /* If the last arg doesn't have void type then we have - variable arguments. */ - if (! next_param) - cum->var = 1; - - if ((mode = TYPE_MODE (type))) - { - if (! targetm.calls.must_pass_in_stack (mode, type)) - { - /* Look for float, double, or long double argument. */ - if (mode == QFmode || mode == HFmode) - cum->floats++; - /* Look for integer, enumeral, boolean, char, or pointer - argument. */ - else if (mode == QImode || mode == Pmode) - cum->ints++; - } - } - cum->args++; - } - } - - if (TARGET_DEBUG) - fprintf (stderr, "%s%s, args = %d)\n", - cum->prototype ? ", prototype" : "", - cum->var ? ", variable args" : "", - cum->args); -} - - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - -void -c4x_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, - tree type, int named) -{ - if (TARGET_DEBUG) - fprintf (stderr, "c4x_function_adv(mode=%s, named=%d)\n\n", - GET_MODE_NAME (mode), named); - if (! TARGET_MEMPARM - && named - && type - && ! targetm.calls.must_pass_in_stack (mode, type)) - { - /* Look for float, double, or long double argument. */ - if (mode == QFmode || mode == HFmode) - cum->floats++; - /* Look for integer, enumeral, boolean, char, or pointer argument. */ - else if (mode == QImode || mode == Pmode) - cum->ints++; - } - else if (! TARGET_MEMPARM && ! type) - { - /* Handle libcall arguments. */ - if (mode == QFmode || mode == HFmode) - cum->floats++; - else if (mode == QImode || mode == Pmode) - cum->ints++; - } - return; -} - - -/* Define where to put the arguments to a function. Value is zero to - push the argument on the stack, or a hard register in which to - store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ - -struct rtx_def * -c4x_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, - tree type, int named) -{ - int reg = 0; /* Default to passing argument on stack. */ - - if (! cum->init) - { - /* We can handle at most 2 floats in R2, R3. */ - cum->maxfloats = (cum->floats > 2) ? 2 : cum->floats; - - /* We can handle at most 6 integers minus number of floats passed - in registers. */ - cum->maxints = (cum->ints > 6 - cum->maxfloats) ? - 6 - cum->maxfloats : cum->ints; - - /* If there is no prototype, assume all the arguments are integers. */ - if (! cum->prototype) - cum->maxints = 6; - - cum->ints = cum->floats = 0; - cum->init = 1; - } - - /* This marks the last argument. We don't need to pass this through - to the call insn. */ - if (type == void_type_node) - return 0; - - if (! TARGET_MEMPARM - && named - && type - && ! targetm.calls.must_pass_in_stack (mode, type)) - { - /* Look for float, double, or long double argument. */ - if (mode == QFmode || mode == HFmode) - { - if (cum->floats < cum->maxfloats) - reg = c4x_fp_reglist[cum->floats]; - } - /* Look for integer, enumeral, boolean, char, or pointer argument. */ - else if (mode == QImode || mode == Pmode) - { - if (cum->ints < cum->maxints) - reg = c4x_int_reglist[cum->maxfloats][cum->ints]; - } - } - else if (! TARGET_MEMPARM && ! type) - { - /* We could use a different argument calling model for libcalls, - since we're only calling functions in libgcc. Thus we could - pass arguments for long longs in registers rather than on the - stack. In the meantime, use the odd TI format. We make the - assumption that we won't have more than two floating point - args, six integer args, and that all the arguments are of the - same mode. */ - if (mode == QFmode || mode == HFmode) - reg = c4x_fp_reglist[cum->floats]; - else if (mode == QImode || mode == Pmode) - reg = c4x_int_reglist[0][cum->ints]; - } - - if (TARGET_DEBUG) - { - fprintf (stderr, "c4x_function_arg(mode=%s, named=%d", - GET_MODE_NAME (mode), named); - if (reg) - fprintf (stderr, ", reg=%s", reg_names[reg]); - else - fprintf (stderr, ", stack"); - fprintf (stderr, ")\n"); - } - if (reg) - return gen_rtx_REG (mode, reg); - else - return NULL_RTX; -} - -/* C[34]x arguments grow in weird ways (downwards) that the standard - varargs stuff can't handle.. */ - -static tree -c4x_gimplify_va_arg_expr (tree valist, tree type, - tree *pre_p ATTRIBUTE_UNUSED, - tree *post_p ATTRIBUTE_UNUSED) -{ - tree t; - bool indirect; - - indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false); - if (indirect) - type = build_pointer_type (type); - - t = build2 (PREDECREMENT_EXPR, TREE_TYPE (valist), valist, - build_int_cst (NULL_TREE, int_size_in_bytes (type))); - t = fold_convert (build_pointer_type (type), t); - t = build_va_arg_indirect_ref (t); - - if (indirect) - t = build_va_arg_indirect_ref (t); - - return t; -} - - -static int -c4x_isr_reg_used_p (unsigned int regno) -{ - /* Don't save/restore FP or ST, we handle them separately. */ - if (regno == FRAME_POINTER_REGNUM - || IS_ST_REGNO (regno)) - return 0; - - /* We could be a little smarter abut saving/restoring DP. - We'll only save if for the big memory model or if - we're paranoid. ;-) */ - if (IS_DP_REGNO (regno)) - return ! TARGET_SMALL || TARGET_PARANOID; - - /* Only save/restore regs in leaf function that are used. */ - if (c4x_leaf_function) - return df_regs_ever_live_p (regno) && fixed_regs[regno] == 0; - - /* Only save/restore regs that are used by the ISR and regs - that are likely to be used by functions the ISR calls - if they are not fixed. */ - return IS_EXT_REGNO (regno) - || ((df_regs_ever_live_p (regno) || call_used_regs[regno]) - && fixed_regs[regno] == 0); -} - - -static int -c4x_leaf_function_p (void) -{ - /* A leaf function makes no calls, so we only need - to save/restore the registers we actually use. - For the global variable leaf_function to be set, we need - to define LEAF_REGISTERS and all that it entails. - Let's check ourselves.... */ - - if (lookup_attribute ("leaf_pretend", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) - return 1; - - /* Use the leaf_pretend attribute at your own risk. This is a hack - to speed up ISRs that call a function infrequently where the - overhead of saving and restoring the additional registers is not - warranted. You must save and restore the additional registers - required by the called function. Caveat emptor. Here's enough - rope... */ - - if (leaf_function_p ()) - return 1; - - return 0; -} - - -static int -c4x_naked_function_p (void) -{ - tree type; - - type = TREE_TYPE (current_function_decl); - return lookup_attribute ("naked", TYPE_ATTRIBUTES (type)) != NULL; -} - - -int -c4x_interrupt_function_p (void) -{ - const char *cfun_name; - if (lookup_attribute ("interrupt", - TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) - return 1; - - /* Look for TI style c_intnn. */ - cfun_name = current_function_name (); - return cfun_name[0] == 'c' - && cfun_name[1] == '_' - && cfun_name[2] == 'i' - && cfun_name[3] == 'n' - && cfun_name[4] == 't' - && ISDIGIT (cfun_name[5]) - && ISDIGIT (cfun_name[6]); -} - -void -c4x_expand_prologue (void) -{ - unsigned int regno; - int size = get_frame_size (); - rtx insn; - - /* In functions where ar3 is not used but frame pointers are still - specified, frame pointers are not adjusted (if >= -O2) and this - is used so it won't needlessly push the frame pointer. */ - int dont_push_ar3; - - /* For __naked__ function don't build a prologue. */ - if (c4x_naked_function_p ()) - { - return; - } - - /* For __interrupt__ function build specific prologue. */ - if (c4x_interrupt_function_p ()) - { - c4x_leaf_function = c4x_leaf_function_p (); - - insn = emit_insn (gen_push_st ()); - RTX_FRAME_RELATED_P (insn) = 1; - if (size) - { - insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO))); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO), - gen_rtx_REG (QImode, SP_REGNO))); - RTX_FRAME_RELATED_P (insn) = 1; - /* We require that an ISR uses fewer than 32768 words of - local variables, otherwise we have to go to lots of - effort to save a register, load it with the desired size, - adjust the stack pointer, and then restore the modified - register. Frankly, I think it is a poor ISR that - requires more than 32767 words of local temporary - storage! */ - if (size > 32767) - error ("ISR %s requires %d words of local vars, max is 32767", - current_function_name (), size); - - insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO), - gen_rtx_REG (QImode, SP_REGNO), - GEN_INT (size))); - RTX_FRAME_RELATED_P (insn) = 1; - } - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - if (c4x_isr_reg_used_p (regno)) - { - if (regno == DP_REGNO) - { - insn = emit_insn (gen_push_dp ()); - RTX_FRAME_RELATED_P (insn) = 1; - } - else - { - insn = emit_insn (gen_pushqi (gen_rtx_REG (QImode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - if (IS_EXT_REGNO (regno)) - { - insn = emit_insn (gen_pushqf - (gen_rtx_REG (QFmode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - } - } - } - } - /* We need to clear the repeat mode flag if the ISR is - going to use a RPTB instruction or uses the RC, RS, or RE - registers. */ - if (df_regs_ever_live_p (RC_REGNO) - || df_regs_ever_live_p (RS_REGNO) - || df_regs_ever_live_p (RE_REGNO)) - { - insn = emit_insn (gen_andn_st (GEN_INT(~0x100))); - RTX_FRAME_RELATED_P (insn) = 1; - } - - /* Reload DP reg if we are paranoid about some turkey - violating small memory model rules. */ - if (TARGET_SMALL && TARGET_PARANOID) - { - insn = emit_insn (gen_set_ldp_prologue - (gen_rtx_REG (QImode, DP_REGNO), - gen_rtx_SYMBOL_REF (QImode, "data_sec"))); - RTX_FRAME_RELATED_P (insn) = 1; - } - } - else - { - if (frame_pointer_needed) - { - if ((size != 0) - || (current_function_args_size != 0) - || (optimize < 2)) - { - insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO))); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO), - gen_rtx_REG (QImode, SP_REGNO))); - RTX_FRAME_RELATED_P (insn) = 1; - dont_push_ar3 = 1; - } - else - { - /* Since ar3 is not used, we don't need to push it. */ - dont_push_ar3 = 1; - } - } - else - { - /* If we use ar3, we need to push it. */ - dont_push_ar3 = 0; - if ((size != 0) || (current_function_args_size != 0)) - { - /* If we are omitting the frame pointer, we still have - to make space for it so the offsets are correct - unless we don't use anything on the stack at all. */ - size += 1; - } - } - - if (size > 32767) - { - /* Local vars are too big, it will take multiple operations - to increment SP. */ - if (TARGET_C3X) - { - insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO), - GEN_INT(size >> 16))); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R1_REGNO), - gen_rtx_REG (QImode, R1_REGNO), - GEN_INT(-16))); - RTX_FRAME_RELATED_P (insn) = 1; - } - else - { - insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO), - GEN_INT(size & ~0xffff))); - RTX_FRAME_RELATED_P (insn) = 1; - } - insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R1_REGNO), - gen_rtx_REG (QImode, R1_REGNO), - GEN_INT(size & 0xffff))); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO), - gen_rtx_REG (QImode, SP_REGNO), - gen_rtx_REG (QImode, R1_REGNO))); - RTX_FRAME_RELATED_P (insn) = 1; - } - else if (size != 0) - { - /* Local vars take up less than 32767 words, so we can directly - add the number. */ - insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO), - gen_rtx_REG (QImode, SP_REGNO), - GEN_INT (size))); - RTX_FRAME_RELATED_P (insn) = 1; - } - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) - { - if (IS_FLOAT_CALL_SAVED_REGNO (regno)) - { - if (TARGET_PRESERVE_FLOAT) - { - insn = emit_insn (gen_pushqi - (gen_rtx_REG (QImode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - } - insn = emit_insn (gen_pushqf (gen_rtx_REG (QFmode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - } - else if ((! dont_push_ar3) || (regno != AR3_REGNO)) - { - insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - } - } - } - } -} - - -void -c4x_expand_epilogue(void) -{ - int regno; - int jump = 0; - int dont_pop_ar3; - rtx insn; - int size = get_frame_size (); - - /* For __naked__ function build no epilogue. */ - if (c4x_naked_function_p ()) - { - insn = emit_jump_insn (gen_return_from_epilogue ()); - RTX_FRAME_RELATED_P (insn) = 1; - return; - } - - /* For __interrupt__ function build specific epilogue. */ - if (c4x_interrupt_function_p ()) - { - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno) - { - if (! c4x_isr_reg_used_p (regno)) - continue; - if (regno == DP_REGNO) - { - insn = emit_insn (gen_pop_dp ()); - RTX_FRAME_RELATED_P (insn) = 1; - } - else - { - /* We have to use unspec because the compiler will delete insns - that are not call-saved. */ - if (IS_EXT_REGNO (regno)) - { - insn = emit_insn (gen_popqf_unspec - (gen_rtx_REG (QFmode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - } - insn = emit_insn (gen_popqi_unspec (gen_rtx_REG (QImode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - } - } - if (size) - { - insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO), - gen_rtx_REG (QImode, SP_REGNO), - GEN_INT(size))); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_popqi - (gen_rtx_REG (QImode, AR3_REGNO))); - RTX_FRAME_RELATED_P (insn) = 1; - } - insn = emit_insn (gen_pop_st ()); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_jump_insn (gen_return_from_interrupt_epilogue ()); - RTX_FRAME_RELATED_P (insn) = 1; - } - else - { - if (frame_pointer_needed) - { - if ((size != 0) - || (current_function_args_size != 0) - || (optimize < 2)) - { - insn = emit_insn - (gen_movqi (gen_rtx_REG (QImode, R2_REGNO), - gen_rtx_MEM (QImode, - gen_rtx_PLUS - (QImode, gen_rtx_REG (QImode, - AR3_REGNO), - constm1_rtx)))); - RTX_FRAME_RELATED_P (insn) = 1; - - /* We already have the return value and the fp, - so we need to add those to the stack. */ - size += 2; - jump = 1; - dont_pop_ar3 = 1; - } - else - { - /* Since ar3 is not used for anything, we don't need to - pop it. */ - dont_pop_ar3 = 1; - } - } - else - { - dont_pop_ar3 = 0; /* If we use ar3, we need to pop it. */ - if (size || current_function_args_size) - { - /* If we are omitting the frame pointer, we still have - to make space for it so the offsets are correct - unless we don't use anything on the stack at all. */ - size += 1; - } - } - - /* Now restore the saved registers, putting in the delayed branch - where required. */ - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) - { - if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) - { - if (regno == AR3_REGNO && dont_pop_ar3) - continue; - - if (IS_FLOAT_CALL_SAVED_REGNO (regno)) - { - insn = emit_insn (gen_popqf_unspec - (gen_rtx_REG (QFmode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - if (TARGET_PRESERVE_FLOAT) - { - insn = emit_insn (gen_popqi_unspec - (gen_rtx_REG (QImode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - } - } - else - { - insn = emit_insn (gen_popqi (gen_rtx_REG (QImode, regno))); - RTX_FRAME_RELATED_P (insn) = 1; - } - } - } - - if (frame_pointer_needed) - { - if ((size != 0) - || (current_function_args_size != 0) - || (optimize < 2)) - { - /* Restore the old FP. */ - insn = emit_insn - (gen_movqi - (gen_rtx_REG (QImode, AR3_REGNO), - gen_rtx_MEM (QImode, gen_rtx_REG (QImode, AR3_REGNO)))); - - RTX_FRAME_RELATED_P (insn) = 1; - } - } - - if (size > 32767) - { - /* Local vars are too big, it will take multiple operations - to decrement SP. */ - if (TARGET_C3X) - { - insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO), - GEN_INT(size >> 16))); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R3_REGNO), - gen_rtx_REG (QImode, R3_REGNO), - GEN_INT(-16))); - RTX_FRAME_RELATED_P (insn) = 1; - } - else - { - insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO), - GEN_INT(size & ~0xffff))); - RTX_FRAME_RELATED_P (insn) = 1; - } - insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R3_REGNO), - gen_rtx_REG (QImode, R3_REGNO), - GEN_INT(size & 0xffff))); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO), - gen_rtx_REG (QImode, SP_REGNO), - gen_rtx_REG (QImode, R3_REGNO))); - RTX_FRAME_RELATED_P (insn) = 1; - } - else if (size != 0) - { - /* Local vars take up less than 32768 words, so we can directly - subtract the number. */ - insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO), - gen_rtx_REG (QImode, SP_REGNO), - GEN_INT(size))); - RTX_FRAME_RELATED_P (insn) = 1; - } - - if (jump) - { - insn = emit_jump_insn (gen_return_indirect_internal - (gen_rtx_REG (QImode, R2_REGNO))); - RTX_FRAME_RELATED_P (insn) = 1; - } - else - { - insn = emit_jump_insn (gen_return_from_epilogue ()); - RTX_FRAME_RELATED_P (insn) = 1; - } - } -} - - -int -c4x_null_epilogue_p (void) -{ - int regno; - - if (reload_completed - && ! c4x_naked_function_p () - && ! c4x_interrupt_function_p () - && ! current_function_calls_alloca - && ! current_function_args_size - && ! (optimize < 2) - && ! get_frame_size ()) - { - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) - if (df_regs_ever_live_p (regno) && ! call_used_regs[regno] - && (regno != AR3_REGNO)) - return 1; - return 0; - } - return 1; -} - - -int -c4x_emit_move_sequence (rtx *operands, enum machine_mode mode) -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - - if (! reload_in_progress - && ! REG_P (op0) - && ! REG_P (op1) - && ! (stik_const_operand (op1, mode) && ! push_operand (op0, mode))) - op1 = force_reg (mode, op1); - - if (GET_CODE (op1) == LO_SUM - && GET_MODE (op1) == Pmode - && dp_reg_operand (XEXP (op1, 0), mode)) - { - /* expand_increment will sometimes create a LO_SUM immediate - address. Undo this silliness. */ - op1 = XEXP (op1, 1); - } - - if (symbolic_address_operand (op1, mode)) - { - if (TARGET_LOAD_ADDRESS) - { - /* Alias analysis seems to do a better job if we force - constant addresses to memory after reload. */ - emit_insn (gen_load_immed_address (op0, op1)); - return 1; - } - else - { - /* Stick symbol or label address into the constant pool. */ - op1 = force_const_mem (Pmode, op1); - } - } - else if (mode == HFmode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1)) - { - /* We could be a lot smarter about loading some of these - constants... */ - op1 = force_const_mem (mode, op1); - } - - /* Convert (MEM (SYMREF)) to a (MEM (LO_SUM (REG) (SYMREF))) - and emit associated (HIGH (SYMREF)) if large memory model. - c4x_legitimize_address could be used to do this, - perhaps by calling validize_address. */ - if (TARGET_EXPOSE_LDP - && ! (reload_in_progress || reload_completed) - && GET_CODE (op1) == MEM - && symbolic_address_operand (XEXP (op1, 0), Pmode)) - { - rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); - if (! TARGET_SMALL) - emit_insn (gen_set_ldp (dp_reg, XEXP (op1, 0))); - op1 = change_address (op1, mode, - gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op1, 0))); - } - - if (TARGET_EXPOSE_LDP - && ! (reload_in_progress || reload_completed) - && GET_CODE (op0) == MEM - && symbolic_address_operand (XEXP (op0, 0), Pmode)) - { - rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); - if (! TARGET_SMALL) - emit_insn (gen_set_ldp (dp_reg, XEXP (op0, 0))); - op0 = change_address (op0, mode, - gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op0, 0))); - } - - if (GET_CODE (op0) == SUBREG - && mixed_subreg_operand (op0, mode)) - { - /* We should only generate these mixed mode patterns - during RTL generation. If we need do it later on - then we'll have to emit patterns that won't clobber CC. */ - if (reload_in_progress || reload_completed) - abort (); - if (GET_MODE (SUBREG_REG (op0)) == QImode) - op0 = SUBREG_REG (op0); - else if (GET_MODE (SUBREG_REG (op0)) == HImode) - { - op0 = copy_rtx (op0); - PUT_MODE (op0, QImode); - } - else - abort (); - - if (mode == QFmode) - emit_insn (gen_storeqf_int_clobber (op0, op1)); - else - abort (); - return 1; - } - - if (GET_CODE (op1) == SUBREG - && mixed_subreg_operand (op1, mode)) - { - /* We should only generate these mixed mode patterns - during RTL generation. If we need do it later on - then we'll have to emit patterns that won't clobber CC. */ - if (reload_in_progress || reload_completed) - abort (); - if (GET_MODE (SUBREG_REG (op1)) == QImode) - op1 = SUBREG_REG (op1); - else if (GET_MODE (SUBREG_REG (op1)) == HImode) - { - op1 = copy_rtx (op1); - PUT_MODE (op1, QImode); - } - else - abort (); - - if (mode == QFmode) - emit_insn (gen_loadqf_int_clobber (op0, op1)); - else - abort (); - return 1; - } - - if (mode == QImode - && reg_operand (op0, mode) - && const_int_operand (op1, mode) - && ! IS_INT16_CONST (INTVAL (op1)) - && ! IS_HIGH_CONST (INTVAL (op1))) - { - emit_insn (gen_loadqi_big_constant (op0, op1)); - return 1; - } - - if (mode == HImode - && reg_operand (op0, mode) - && const_int_operand (op1, mode)) - { - emit_insn (gen_loadhi_big_constant (op0, op1)); - return 1; - } - - /* Adjust operands in case we have modified them. */ - operands[0] = op0; - operands[1] = op1; - - /* Emit normal pattern. */ - return 0; -} - - -void -c4x_emit_libcall (rtx libcall, enum rtx_code code, - enum machine_mode dmode, enum machine_mode smode, - int noperands, rtx *operands) -{ - rtx ret; - rtx insns; - rtx equiv; - - start_sequence (); - switch (noperands) - { - case 2: - ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1, - operands[1], smode); - equiv = gen_rtx_fmt_e (code, dmode, operands[1]); - break; - - case 3: - ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 2, - operands[1], smode, operands[2], smode); - equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]); - break; - - default: - abort (); - } - - insns = get_insns (); - end_sequence (); - emit_libcall_block (insns, operands[0], ret, equiv); -} - - -void -c4x_emit_libcall3 (rtx libcall, enum rtx_code code, - enum machine_mode mode, rtx *operands) -{ - c4x_emit_libcall (libcall, code, mode, mode, 3, operands); -} - - -void -c4x_emit_libcall_mulhi (rtx libcall, enum rtx_code code, - enum machine_mode mode, rtx *operands) -{ - rtx ret; - rtx insns; - rtx equiv; - - start_sequence (); - ret = emit_library_call_value (libcall, NULL_RTX, 1, mode, 2, - operands[1], mode, operands[2], mode); - equiv = gen_rtx_TRUNCATE (mode, - gen_rtx_LSHIFTRT (HImode, - gen_rtx_MULT (HImode, - gen_rtx_fmt_e (code, HImode, operands[1]), - gen_rtx_fmt_e (code, HImode, operands[2])), - GEN_INT (32))); - insns = get_insns (); - end_sequence (); - emit_libcall_block (insns, operands[0], ret, equiv); -} - - -int -c4x_legitimate_address_p (enum machine_mode mode, rtx addr, int strict) -{ - rtx base = NULL_RTX; /* Base register (AR0-AR7). */ - rtx indx = NULL_RTX; /* Index register (IR0,IR1). */ - rtx disp = NULL_RTX; /* Displacement. */ - enum rtx_code code; - - code = GET_CODE (addr); - switch (code) - { - /* Register indirect with auto increment/decrement. We don't - allow SP here---push_operand should recognize an operand - being pushed on the stack. */ - - case PRE_DEC: - case PRE_INC: - case POST_DEC: - if (mode != QImode && mode != QFmode) - return 0; - - case POST_INC: - base = XEXP (addr, 0); - if (! REG_P (base)) - return 0; - break; - - case PRE_MODIFY: - case POST_MODIFY: - { - rtx op0 = XEXP (addr, 0); - rtx op1 = XEXP (addr, 1); - - if (mode != QImode && mode != QFmode) - return 0; - - if (! REG_P (op0) - || (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)) - return 0; - base = XEXP (op1, 0); - if (! REG_P (base)) - return 0; - if (REGNO (base) != REGNO (op0)) - return 0; - if (REG_P (XEXP (op1, 1))) - indx = XEXP (op1, 1); - else - disp = XEXP (op1, 1); - } - break; - - /* Register indirect. */ - case REG: - base = addr; - break; - - /* Register indirect with displacement or index. */ - case PLUS: - { - rtx op0 = XEXP (addr, 0); - rtx op1 = XEXP (addr, 1); - enum rtx_code code0 = GET_CODE (op0); - - switch (code0) - { - case REG: - if (REG_P (op1)) - { - base = op0; /* Base + index. */ - indx = op1; - if (IS_INDEX_REG (base) || IS_ADDR_REG (indx)) - { - base = op1; - indx = op0; - } - } - else - { - base = op0; /* Base + displacement. */ - disp = op1; - } - break; - - default: - return 0; - } - } - break; - - /* Direct addressing with DP register. */ - case LO_SUM: - { - rtx op0 = XEXP (addr, 0); - rtx op1 = XEXP (addr, 1); - - /* HImode and HFmode direct memory references aren't truly - offsettable (consider case at end of data page). We - probably get better code by loading a pointer and using an - indirect memory reference. */ - if (mode == HImode || mode == HFmode) - return 0; - - if (!REG_P (op0) || REGNO (op0) != DP_REGNO) - return 0; - - if ((GET_CODE (op1) == SYMBOL_REF || GET_CODE (op1) == LABEL_REF)) - return 1; - - if (GET_CODE (op1) == CONST) - return 1; - return 0; - } - break; - - /* Direct addressing with some work for the assembler... */ - case CONST: - /* Direct addressing. */ - case LABEL_REF: - case SYMBOL_REF: - if (! TARGET_EXPOSE_LDP && ! strict && mode != HFmode && mode != HImode) - return 1; - /* These need to be converted to a LO_SUM (...). - LEGITIMIZE_RELOAD_ADDRESS will do this during reload. */ - return 0; - - /* Do not allow direct memory access to absolute addresses. - This is more pain than it's worth, especially for the - small memory model where we can't guarantee that - this address is within the data page---we don't want - to modify the DP register in the small memory model, - even temporarily, since an interrupt can sneak in.... */ - case CONST_INT: - return 0; - - /* Indirect indirect addressing. */ - case MEM: - return 0; - - case CONST_DOUBLE: - fatal_insn ("using CONST_DOUBLE for address", addr); - - default: - return 0; - } - - /* Validate the base register. */ - if (base) - { - /* Check that the address is offsettable for HImode and HFmode. */ - if (indx && (mode == HImode || mode == HFmode)) - return 0; - - /* Handle DP based stuff. */ - if (REGNO (base) == DP_REGNO) - return 1; - if (strict && ! REGNO_OK_FOR_BASE_P (REGNO (base))) - return 0; - else if (! strict && ! IS_ADDR_OR_PSEUDO_REG (base)) - return 0; - } - - /* Now validate the index register. */ - if (indx) - { - if (GET_CODE (indx) != REG) - return 0; - if (strict && ! REGNO_OK_FOR_INDEX_P (REGNO (indx))) - return 0; - else if (! strict && ! IS_INDEX_OR_PSEUDO_REG (indx)) - return 0; - } - - /* Validate displacement. */ - if (disp) - { - if (GET_CODE (disp) != CONST_INT) - return 0; - if (mode == HImode || mode == HFmode) - { - /* The offset displacement must be legitimate. */ - if (! IS_DISP8_OFF_CONST (INTVAL (disp))) - return 0; - } - else - { - if (! IS_DISP8_CONST (INTVAL (disp))) - return 0; - } - /* Can't add an index with a disp. */ - if (indx) - return 0; - } - return 1; -} - - -rtx -c4x_legitimize_address (rtx orig ATTRIBUTE_UNUSED, - enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (orig) == SYMBOL_REF - || GET_CODE (orig) == LABEL_REF) - { - if (mode == HImode || mode == HFmode) - { - /* We need to force the address into - a register so that it is offsettable. */ - rtx addr_reg = gen_reg_rtx (Pmode); - emit_move_insn (addr_reg, orig); - return addr_reg; - } - else - { - rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); - - if (! TARGET_SMALL) - emit_insn (gen_set_ldp (dp_reg, orig)); - - return gen_rtx_LO_SUM (Pmode, dp_reg, orig); - } - } - - return NULL_RTX; -} - - -/* Provide the costs of an addressing mode that contains ADDR. - If ADDR is not a valid address, its cost is irrelevant. - This is used in cse and loop optimization to determine - if it is worthwhile storing a common address into a register. - Unfortunately, the C4x address cost depends on other operands. */ - -static int -c4x_address_cost (rtx addr) -{ - switch (GET_CODE (addr)) - { - case REG: - return 1; - - case POST_INC: - case POST_DEC: - case PRE_INC: - case PRE_DEC: - return 1; - - /* These shouldn't be directly generated. */ - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return 10; - - case LO_SUM: - { - rtx op1 = XEXP (addr, 1); - - if (GET_CODE (op1) == LABEL_REF || GET_CODE (op1) == SYMBOL_REF) - return TARGET_SMALL ? 3 : 4; - - if (GET_CODE (op1) == CONST) - { - rtx offset = const0_rtx; - - op1 = eliminate_constant_term (op1, &offset); - - /* ??? These costs need rethinking... */ - if (GET_CODE (op1) == LABEL_REF) - return 3; - - if (GET_CODE (op1) != SYMBOL_REF) - return 4; - - if (INTVAL (offset) == 0) - return 3; - - return 4; - } - fatal_insn ("c4x_address_cost: Invalid addressing mode", addr); - } - break; - - case PLUS: - { - register rtx op0 = XEXP (addr, 0); - register rtx op1 = XEXP (addr, 1); - - if (GET_CODE (op0) != REG) - break; - - switch (GET_CODE (op1)) - { - default: - break; - - case REG: - /* This cost for REG+REG must be greater than the cost - for REG if we want autoincrement addressing modes. */ - return 2; - - case CONST_INT: - /* The following tries to improve GIV combination - in strength reduce but appears not to help. */ - if (TARGET_DEVEL && IS_UINT5_CONST (INTVAL (op1))) - return 1; - - if (IS_DISP1_CONST (INTVAL (op1))) - return 1; - - if (! TARGET_C3X && IS_UINT5_CONST (INTVAL (op1))) - return 2; - - return 3; - } - } - default: - break; - } - - return 4; -} - - -rtx -c4x_gen_compare_reg (enum rtx_code code, rtx x, rtx y) -{ - enum machine_mode mode = SELECT_CC_MODE (code, x, y); - rtx cc_reg; - - if (mode == CC_NOOVmode - && (code == LE || code == GE || code == LT || code == GT)) - return NULL_RTX; - - cc_reg = gen_rtx_REG (mode, ST_REGNO); - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, - gen_rtx_COMPARE (mode, x, y))); - return cc_reg; -} - -char * -c4x_output_cbranch (const char *form, rtx seq) -{ - int delayed = 0; - int annultrue = 0; - int annulfalse = 0; - rtx delay; - char *cp; - static char str[100]; - - if (final_sequence) - { - delay = XVECEXP (final_sequence, 0, 1); - delayed = ! INSN_ANNULLED_BRANCH_P (seq); - annultrue = INSN_ANNULLED_BRANCH_P (seq) && ! INSN_FROM_TARGET_P (delay); - annulfalse = INSN_ANNULLED_BRANCH_P (seq) && INSN_FROM_TARGET_P (delay); - } - strcpy (str, form); - cp = &str [strlen (str)]; - if (delayed) - { - *cp++ = '%'; - *cp++ = '#'; - } - if (annultrue) - { - *cp++ = 'a'; - *cp++ = 't'; - } - if (annulfalse) - { - *cp++ = 'a'; - *cp++ = 'f'; - } - *cp++ = '\t'; - *cp++ = '%'; - *cp++ = 'l'; - *cp++ = '1'; - *cp = 0; - return str; -} - -void -c4x_print_operand (FILE *file, rtx op, int letter) -{ - rtx op1; - enum rtx_code code; - - switch (letter) - { - case '#': /* Delayed. */ - if (final_sequence) - fprintf (file, "d"); - return; - } - - code = GET_CODE (op); - switch (letter) - { - case 'A': /* Direct address. */ - if (code == CONST_INT || code == SYMBOL_REF || code == CONST) - fprintf (file, "@"); - break; - - case 'H': /* Sethi. */ - output_addr_const (file, op); - return; - - case 'I': /* Reversed condition. */ - code = reverse_condition (code); - break; - - case 'L': /* Log 2 of constant. */ - if (code != CONST_INT) - fatal_insn ("c4x_print_operand: %%L inconsistency", op); - fprintf (file, "%d", exact_log2 (INTVAL (op))); - return; - - case 'N': /* Ones complement of small constant. */ - if (code != CONST_INT) - fatal_insn ("c4x_print_operand: %%N inconsistency", op); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~INTVAL (op)); - return; - - case 'K': /* Generate ldp(k) if direct address. */ - if (! TARGET_SMALL - && code == MEM - && GET_CODE (XEXP (op, 0)) == LO_SUM - && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG - && REGNO (XEXP (XEXP (op, 0), 0)) == DP_REGNO) - { - op1 = XEXP (XEXP (op, 0), 1); - if (GET_CODE(op1) == CONST_INT || GET_CODE(op1) == SYMBOL_REF) - { - fprintf (file, "\t%s\t@", TARGET_C3X ? "ldp" : "ldpk"); - output_address (XEXP (adjust_address (op, VOIDmode, 1), 0)); - fprintf (file, "\n"); - } - } - return; - - case 'M': /* Generate ldp(k) if direct address. */ - if (! TARGET_SMALL /* Only used in asm statements. */ - && code == MEM - && (GET_CODE (XEXP (op, 0)) == CONST - || GET_CODE (XEXP (op, 0)) == SYMBOL_REF)) - { - fprintf (file, "%s\t@", TARGET_C3X ? "ldp" : "ldpk"); - output_address (XEXP (op, 0)); - fprintf (file, "\n\t"); - } - return; - - case 'O': /* Offset address. */ - if (code == MEM && c4x_autoinc_operand (op, Pmode)) - break; - else if (code == MEM) - output_address (XEXP (adjust_address (op, VOIDmode, 1), 0)); - else if (code == REG) - fprintf (file, "%s", reg_names[REGNO (op) + 1]); - else - fatal_insn ("c4x_print_operand: %%O inconsistency", op); - return; - - case 'C': /* Call. */ - break; - - case 'U': /* Call/callu. */ - if (code != SYMBOL_REF) - fprintf (file, "u"); - return; - - default: - break; - } - - switch (code) - { - case REG: - if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT - && ! TARGET_TI) - fprintf (file, "%s", float_reg_names[REGNO (op)]); - else - fprintf (file, "%s", reg_names[REGNO (op)]); - break; - - case MEM: - output_address (XEXP (op, 0)); - break; - - case CONST_DOUBLE: - { - char str[64]; - - real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (op), - sizeof (str), 0, 1); - fprintf (file, "%s", str); - } - break; - - case CONST_INT: - fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op)); - break; - - case NE: - fprintf (file, "ne"); - break; - - case EQ: - fprintf (file, "eq"); - break; - - case GE: - fprintf (file, "ge"); - break; - - case GT: - fprintf (file, "gt"); - break; - - case LE: - fprintf (file, "le"); - break; - - case LT: - fprintf (file, "lt"); - break; - - case GEU: - fprintf (file, "hs"); - break; - - case GTU: - fprintf (file, "hi"); - break; - - case LEU: - fprintf (file, "ls"); - break; - - case LTU: - fprintf (file, "lo"); - break; - - case SYMBOL_REF: - output_addr_const (file, op); - break; - - case CONST: - output_addr_const (file, XEXP (op, 0)); - break; - - case CODE_LABEL: - break; - - default: - fatal_insn ("c4x_print_operand: Bad operand case", op); - break; - } -} - - -void -c4x_print_operand_address (FILE *file, rtx addr) -{ - switch (GET_CODE (addr)) - { - case REG: - fprintf (file, "*%s", reg_names[REGNO (addr)]); - break; - - case PRE_DEC: - fprintf (file, "*--%s", reg_names[REGNO (XEXP (addr, 0))]); - break; - - case POST_INC: - fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]); - break; - - case POST_MODIFY: - { - rtx op0 = XEXP (XEXP (addr, 1), 0); - rtx op1 = XEXP (XEXP (addr, 1), 1); - - if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1)) - fprintf (file, "*%s++(%s)", reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); - else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0) - fprintf (file, "*%s++(" HOST_WIDE_INT_PRINT_DEC ")", - reg_names[REGNO (op0)], INTVAL (op1)); - else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0) - fprintf (file, "*%s--(" HOST_WIDE_INT_PRINT_DEC ")", - reg_names[REGNO (op0)], -INTVAL (op1)); - else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1)) - fprintf (file, "*%s--(%s)", reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); - else - fatal_insn ("c4x_print_operand_address: Bad post_modify", addr); - } - break; - - case PRE_MODIFY: - { - rtx op0 = XEXP (XEXP (addr, 1), 0); - rtx op1 = XEXP (XEXP (addr, 1), 1); - - if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1)) - fprintf (file, "*++%s(%s)", reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); - else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0) - fprintf (file, "*++%s(" HOST_WIDE_INT_PRINT_DEC ")", - reg_names[REGNO (op0)], INTVAL (op1)); - else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0) - fprintf (file, "*--%s(" HOST_WIDE_INT_PRINT_DEC ")", - reg_names[REGNO (op0)], -INTVAL (op1)); - else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1)) - fprintf (file, "*--%s(%s)", reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); - else - fatal_insn ("c4x_print_operand_address: Bad pre_modify", addr); - } - break; - - case PRE_INC: - fprintf (file, "*++%s", reg_names[REGNO (XEXP (addr, 0))]); - break; - - case POST_DEC: - fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]); - break; - - case PLUS: /* Indirect with displacement. */ - { - rtx op0 = XEXP (addr, 0); - rtx op1 = XEXP (addr, 1); - - if (REG_P (op0)) - { - if (REG_P (op1)) - { - if (IS_INDEX_REG (op0)) - { - fprintf (file, "*+%s(%s)", - reg_names[REGNO (op1)], - reg_names[REGNO (op0)]); /* Index + base. */ - } - else - { - fprintf (file, "*+%s(%s)", - reg_names[REGNO (op0)], - reg_names[REGNO (op1)]); /* Base + index. */ - } - } - else if (INTVAL (op1) < 0) - { - fprintf (file, "*-%s(" HOST_WIDE_INT_PRINT_DEC ")", - reg_names[REGNO (op0)], - -INTVAL (op1)); /* Base - displacement. */ - } - else - { - fprintf (file, "*+%s(" HOST_WIDE_INT_PRINT_DEC ")", - reg_names[REGNO (op0)], - INTVAL (op1)); /* Base + displacement. */ - } - } - else - fatal_insn ("c4x_print_operand_address: Bad operand case", addr); - } - break; - - case LO_SUM: - { - rtx op0 = XEXP (addr, 0); - rtx op1 = XEXP (addr, 1); - - if (REG_P (op0) && REGNO (op0) == DP_REGNO) - c4x_print_operand_address (file, op1); - else - fatal_insn ("c4x_print_operand_address: Bad operand case", addr); - } - break; - - case CONST: - case SYMBOL_REF: - case LABEL_REF: - fprintf (file, "@"); - output_addr_const (file, addr); - break; - - /* We shouldn't access CONST_INT addresses. */ - case CONST_INT: - - default: - fatal_insn ("c4x_print_operand_address: Bad operand case", addr); - break; - } -} - - -/* Return nonzero if the floating point operand will fit - in the immediate field. */ - -int -c4x_immed_float_p (rtx op) -{ - long convval[2]; - int exponent; - REAL_VALUE_TYPE r; - - REAL_VALUE_FROM_CONST_DOUBLE (r, op); - if (GET_MODE (op) == HFmode) - REAL_VALUE_TO_TARGET_DOUBLE (r, convval); - else - { - REAL_VALUE_TO_TARGET_SINGLE (r, convval[0]); - convval[1] = 0; - } - - /* Sign extend exponent. */ - exponent = (((convval[0] >> 24) & 0xff) ^ 0x80) - 0x80; - if (exponent == -128) - return 1; /* 0.0 */ - if ((convval[0] & 0x00000fff) != 0 || convval[1] != 0) - return 0; /* Precision doesn't fit. */ - return (exponent <= 7) /* Positive exp. */ - && (exponent >= -7); /* Negative exp. */ -} - - -/* The last instruction in a repeat block cannot be a Bcond, DBcound, - CALL, CALLCond, TRAPcond, RETIcond, RETScond, IDLE, RPTB or RPTS. - - None of the last four instructions from the bottom of the block can - be a BcondD, BRD, DBcondD, RPTBD, LAJ, LAJcond, LATcond, BcondAF, - BcondAT or RETIcondD. - - This routine scans the four previous insns for a jump insn, and if - one is found, returns 1 so that we bung in a nop instruction. - This simple minded strategy will add a nop, when it may not - be required. Say when there is a JUMP_INSN near the end of the - block that doesn't get converted into a delayed branch. - - Note that we cannot have a call insn, since we don't generate - repeat loops with calls in them (although I suppose we could, but - there's no benefit.) - - !!! FIXME. The rptb_top insn may be sucked into a SEQUENCE. */ - -int -c4x_rptb_nop_p (rtx insn) -{ - rtx start_label; - int i; - - /* Extract the start label from the jump pattern (rptb_end). */ - start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0); - - /* If there is a label at the end of the loop we must insert - a NOP. */ - do { - insn = previous_insn (insn); - } while (GET_CODE (insn) == NOTE - || GET_CODE (insn) == USE - || GET_CODE (insn) == CLOBBER); - if (GET_CODE (insn) == CODE_LABEL) - return 1; - - for (i = 0; i < 4; i++) - { - /* Search back for prev non-note and non-label insn. */ - while (GET_CODE (insn) == NOTE || GET_CODE (insn) == CODE_LABEL - || GET_CODE (insn) == USE || GET_CODE (insn) == CLOBBER) - { - if (insn == start_label) - return i == 0; - - insn = previous_insn (insn); - }; - - /* If we have a jump instruction we should insert a NOP. If we - hit repeat block top we should only insert a NOP if the loop - is empty. */ - if (GET_CODE (insn) == JUMP_INSN) - return 1; - insn = previous_insn (insn); - } - return 0; -} - - -/* The C4x looping instruction needs to be emitted at the top of the - loop. Emitting the true RTL for a looping instruction at the top of - the loop can cause problems with flow analysis. So instead, a dummy - doloop insn is emitted at the end of the loop. This routine checks - for the presence of this doloop insn and then searches back to the - top of the loop, where it inserts the true looping insn (provided - there are no instructions in the loop which would cause problems). - Any additional labels can be emitted at this point. In addition, if - the desired loop count register was not allocated, this routine does - nothing. - - Before we can create a repeat block looping instruction we have to - verify that there are no jumps outside the loop and no jumps outside - the loop go into this loop. This can happen in the basic blocks reorder - pass. The C4x cpu cannot handle this. */ - -static int -c4x_label_ref_used_p (rtx x, rtx code_label) -{ - enum rtx_code code; - int i, j; - const char *fmt; - - if (x == 0) - return 0; - - code = GET_CODE (x); - if (code == LABEL_REF) - return INSN_UID (XEXP (x,0)) == INSN_UID (code_label); - - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - if (c4x_label_ref_used_p (XEXP (x, i), code_label)) - return 1; - } - else if (fmt[i] == 'E') - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if (c4x_label_ref_used_p (XVECEXP (x, i, j), code_label)) - return 1; - } - return 0; -} - - -static int -c4x_rptb_valid_p (rtx insn, rtx start_label) -{ - rtx end = insn; - rtx start; - rtx tmp; - - /* Find the start label. */ - for (; insn; insn = PREV_INSN (insn)) - if (insn == start_label) - break; - - /* Note found then we cannot use a rptb or rpts. The label was - probably moved by the basic block reorder pass. */ - if (! insn) - return 0; - - start = insn; - /* If any jump jumps inside this block then we must fail. */ - for (insn = PREV_INSN (start); insn; insn = PREV_INSN (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp)) - if (GET_CODE (tmp) == JUMP_INSN - && c4x_label_ref_used_p (tmp, insn)) - return 0; - } - } - for (insn = NEXT_INSN (end); insn; insn = NEXT_INSN (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp)) - if (GET_CODE (tmp) == JUMP_INSN - && c4x_label_ref_used_p (tmp, insn)) - return 0; - } - } - /* If any jump jumps outside this block then we must fail. */ - for (insn = NEXT_INSN (start); insn != end; insn = NEXT_INSN (insn)) - { - if (GET_CODE (insn) == CODE_LABEL) - { - for (tmp = NEXT_INSN (end); tmp; tmp = NEXT_INSN(tmp)) - if (GET_CODE (tmp) == JUMP_INSN - && c4x_label_ref_used_p (tmp, insn)) - return 0; - for (tmp = PREV_INSN (start); tmp; tmp = PREV_INSN(tmp)) - if (GET_CODE (tmp) == JUMP_INSN - && c4x_label_ref_used_p (tmp, insn)) - return 0; - } - } - - /* All checks OK. */ - return 1; -} - - -void -c4x_rptb_insert (rtx insn) -{ - rtx end_label; - rtx start_label; - rtx new_start_label; - rtx count_reg; - - /* If the count register has not been allocated to RC, say if - there is a movmem pattern in the loop, then do not insert a - RPTB instruction. Instead we emit a decrement and branch - at the end of the loop. */ - count_reg = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0), 0); - if (REGNO (count_reg) != RC_REGNO) - return; - - /* Extract the start label from the jump pattern (rptb_end). */ - start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0); - - if (! c4x_rptb_valid_p (insn, start_label)) - { - /* We cannot use the rptb insn. Replace it so reorg can use - the delay slots of the jump insn. */ - emit_insn_before (gen_addqi3 (count_reg, count_reg, constm1_rtx), insn); - emit_insn_before (gen_cmpqi (count_reg, const0_rtx), insn); - emit_insn_before (gen_bge (start_label), insn); - LABEL_NUSES (start_label)++; - delete_insn (insn); - return; - } - - end_label = gen_label_rtx (); - LABEL_NUSES (end_label)++; - emit_label_after (end_label, insn); - - new_start_label = gen_label_rtx (); - LABEL_NUSES (new_start_label)++; - - for (; insn; insn = PREV_INSN (insn)) - { - if (insn == start_label) - break; - if (GET_CODE (insn) == JUMP_INSN && - JUMP_LABEL (insn) == start_label) - redirect_jump (insn, new_start_label, 0); - } - if (! insn) - fatal_insn ("c4x_rptb_insert: Cannot find start label", start_label); - - emit_label_after (new_start_label, insn); - - if (TARGET_RPTS && c4x_rptb_rpts_p (PREV_INSN (insn), 0)) - emit_insn_after (gen_rpts_top (new_start_label, end_label), insn); - else - emit_insn_after (gen_rptb_top (new_start_label, end_label), insn); - if (LABEL_NUSES (start_label) == 0) - delete_insn (start_label); -} - - -/* We need to use direct addressing for large constants and addresses - that cannot fit within an instruction. We must check for these - after after the final jump optimization pass, since this may - introduce a local_move insn for a SYMBOL_REF. This pass - must come before delayed branch slot filling since it can generate - additional instructions. - - This function also fixes up RTPB style loops that didn't get RC - allocated as the loop counter. */ - -static void -c4x_reorg (void) -{ - rtx insn; - - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - /* Look for insn. */ - if (INSN_P (insn)) - { - int insn_code_number; - rtx old; - - insn_code_number = recog_memoized (insn); - - if (insn_code_number < 0) - continue; - - /* Insert the RTX for RPTB at the top of the loop - and a label at the end of the loop. */ - if (insn_code_number == CODE_FOR_rptb_end) - c4x_rptb_insert(insn); - - /* We need to split the insn here. Otherwise the calls to - force_const_mem will not work for load_immed_address. */ - old = insn; - - /* Don't split the insn if it has been deleted. */ - if (! INSN_DELETED_P (old)) - insn = try_split (PATTERN(old), old, 1); - - /* When not optimizing, the old insn will be still left around - with only the 'deleted' bit set. Transform it into a note - to avoid confusion of subsequent processing. */ - if (INSN_DELETED_P (old)) - SET_INSN_DELETED (old); - } - } -} - - -int -c4x_a_register (rtx op) -{ - return REG_P (op) && IS_ADDR_OR_PSEUDO_REG (op); -} - - -int -c4x_x_register (rtx op) -{ - return REG_P (op) && IS_INDEX_OR_PSEUDO_REG (op); -} - - -static int -c4x_immed_int_constant (rtx op) -{ - if (GET_CODE (op) != CONST_INT) - return 0; - - return GET_MODE (op) == VOIDmode - || GET_MODE_CLASS (GET_MODE (op)) == MODE_INT - || GET_MODE_CLASS (GET_MODE (op)) == MODE_PARTIAL_INT; -} - - -static int -c4x_immed_float_constant (rtx op) -{ - if (GET_CODE (op) != CONST_DOUBLE) - return 0; - - /* Do not check if the CONST_DOUBLE is in memory. If there is a MEM - present this only means that a MEM rtx has been generated. It does - not mean the rtx is really in memory. */ - - return GET_MODE (op) == QFmode || GET_MODE (op) == HFmode; -} - - -int -c4x_shiftable_constant (rtx op) -{ - int i; - int mask; - int val = INTVAL (op); - - for (i = 0; i < 16; i++) - { - if (val & (1 << i)) - break; - } - mask = ((0xffff >> i) << 16) | 0xffff; - if (IS_INT16_CONST (val & (1 << 31) ? (val >> i) | ~mask - : (val >> i) & mask)) - return i; - return -1; -} - - -int -c4x_H_constant (rtx op) -{ - return c4x_immed_float_constant (op) && c4x_immed_float_p (op); -} - - -int -c4x_I_constant (rtx op) -{ - return c4x_immed_int_constant (op) && IS_INT16_CONST (INTVAL (op)); -} - - -int -c4x_J_constant (rtx op) -{ - if (TARGET_C3X) - return 0; - return c4x_immed_int_constant (op) && IS_INT8_CONST (INTVAL (op)); -} - - -int -c4x_K_constant (rtx op) -{ - if (TARGET_C3X || ! c4x_immed_int_constant (op)) - return 0; - return IS_INT5_CONST (INTVAL (op)); -} - - -int -c4x_L_constant (rtx op) -{ - return c4x_immed_int_constant (op) && IS_UINT16_CONST (INTVAL (op)); -} - - -int -c4x_N_constant (rtx op) -{ - return c4x_immed_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op)); -} - - -int -c4x_O_constant (rtx op) -{ - return c4x_immed_int_constant (op) && IS_HIGH_CONST (INTVAL (op)); -} - - -/* The constraints do not have to check the register class, - except when needed to discriminate between the constraints. - The operand has been checked by the predicates to be valid. */ - -/* ARx + 9-bit signed const or IRn - *ARx, *+ARx(n), *-ARx(n), *+ARx(IRn), *-Arx(IRn) for -256 < n < 256 - We don't include the pre/post inc/dec forms here since - they are handled by the <> constraints. */ - -int -c4x_Q_constraint (rtx op) -{ - enum machine_mode mode = GET_MODE (op); - - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return 1; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (! REG_P (op0)) - return 0; - - if (REG_P (op1)) - return 1; - - if (GET_CODE (op1) != CONST_INT) - return 0; - - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_DISP8_OFF_CONST (INTVAL (op1)); - - return IS_DISP8_CONST (INTVAL (op1)); - } - break; - - default: - break; - } - return 0; -} - - -/* ARx + 5-bit unsigned const - *ARx, *+ARx(n) for n < 32. */ - -int -c4x_R_constraint (rtx op) -{ - enum machine_mode mode = GET_MODE (op); - - if (TARGET_C3X) - return 0; - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return 1; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (! REG_P (op0)) - return 0; - - if (GET_CODE (op1) != CONST_INT) - return 0; - - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_UINT5_CONST (INTVAL (op1) + 1); - - return IS_UINT5_CONST (INTVAL (op1)); - } - break; - - default: - break; - } - return 0; -} - - -static int -c4x_R_indirect (rtx op) -{ - enum machine_mode mode = GET_MODE (op); - - if (TARGET_C3X || GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return IS_ADDR_OR_PSEUDO_REG (op); - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_ADDR_OR_PSEUDO_REG (op0) - && GET_CODE (op1) == CONST_INT - && IS_UINT5_CONST (INTVAL (op1) + 1); - - return REG_P (op0) - && IS_ADDR_OR_PSEUDO_REG (op0) - && GET_CODE (op1) == CONST_INT - && IS_UINT5_CONST (INTVAL (op1)); - } - break; - - default: - break; - } - return 0; -} - - -/* ARx + 1-bit unsigned const or IRn - *ARx, *+ARx(1), *-ARx(1), *+ARx(IRn), *-Arx(IRn) - We don't include the pre/post inc/dec forms here since - they are handled by the <> constraints. */ - -int -c4x_S_constraint (rtx op) -{ - enum machine_mode mode = GET_MODE (op); - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return 1; - - case PRE_MODIFY: - case POST_MODIFY: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS) - || (op0 != XEXP (op1, 0))) - return 0; - - op0 = XEXP (op1, 0); - op1 = XEXP (op1, 1); - return REG_P (op0) && REG_P (op1); - /* Pre or post_modify with a displacement of 0 or 1 - should not be generated. */ - } - break; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (!REG_P (op0)) - return 0; - - if (REG_P (op1)) - return 1; - - if (GET_CODE (op1) != CONST_INT) - return 0; - - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_DISP1_OFF_CONST (INTVAL (op1)); - - return IS_DISP1_CONST (INTVAL (op1)); - } - break; - - default: - break; - } - return 0; -} - - -int -c4x_S_indirect (rtx op) -{ - enum machine_mode mode = GET_MODE (op); - if (GET_CODE (op) != MEM) - return 0; - - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case PRE_DEC: - case POST_DEC: - if (mode != QImode && mode != QFmode) - return 0; - case PRE_INC: - case POST_INC: - op = XEXP (op, 0); - - case REG: - return IS_ADDR_OR_PSEUDO_REG (op); - - case PRE_MODIFY: - case POST_MODIFY: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (mode != QImode && mode != QFmode) - return 0; - - if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS) - || (op0 != XEXP (op1, 0))) - return 0; - - op0 = XEXP (op1, 0); - op1 = XEXP (op1, 1); - return REG_P (op0) && IS_ADDR_OR_PSEUDO_REG (op0) - && REG_P (op1) && IS_INDEX_OR_PSEUDO_REG (op1); - /* Pre or post_modify with a displacement of 0 or 1 - should not be generated. */ - } - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (REG_P (op0)) - { - /* HImode and HFmode must be offsettable. */ - if (mode == HImode || mode == HFmode) - return IS_ADDR_OR_PSEUDO_REG (op0) - && GET_CODE (op1) == CONST_INT - && IS_DISP1_OFF_CONST (INTVAL (op1)); - - if (REG_P (op1)) - return (IS_INDEX_OR_PSEUDO_REG (op1) - && IS_ADDR_OR_PSEUDO_REG (op0)) - || (IS_ADDR_OR_PSEUDO_REG (op1) - && IS_INDEX_OR_PSEUDO_REG (op0)); - - return IS_ADDR_OR_PSEUDO_REG (op0) - && GET_CODE (op1) == CONST_INT - && IS_DISP1_CONST (INTVAL (op1)); - } - } - break; - - default: - break; - } - return 0; -} - - -/* Direct memory operand. */ - -int -c4x_T_constraint (rtx op) -{ - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - - if (GET_CODE (op) != LO_SUM) - { - /* Allow call operands. */ - return GET_CODE (op) == SYMBOL_REF - && GET_MODE (op) == Pmode - && SYMBOL_REF_FUNCTION_P (op); - } - - /* HImode and HFmode are not offsettable. */ - if (GET_MODE (op) == HImode || GET_CODE (op) == HFmode) - return 0; - - if ((GET_CODE (XEXP (op, 0)) == REG) - && (REGNO (XEXP (op, 0)) == DP_REGNO)) - return c4x_U_constraint (XEXP (op, 1)); - - return 0; -} - - -/* Symbolic operand. */ - -int -c4x_U_constraint (rtx op) -{ - /* Don't allow direct addressing to an arbitrary constant. */ - return GET_CODE (op) == CONST - || GET_CODE (op) == SYMBOL_REF - || GET_CODE (op) == LABEL_REF; -} - - -int -c4x_autoinc_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == MEM) - { - enum rtx_code code = GET_CODE (XEXP (op, 0)); - - if (code == PRE_INC - || code == PRE_DEC - || code == POST_INC - || code == POST_DEC - || code == PRE_MODIFY - || code == POST_MODIFY - ) - return 1; - } - return 0; -} - - -int -mixed_subreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - /* Allow (subreg:HF (reg:HI)) that be generated for a union of an - int and a long double. */ - if (GET_CODE (op) == SUBREG - && (GET_MODE (op) == QFmode) - && (GET_MODE (SUBREG_REG (op)) == QImode - || GET_MODE (SUBREG_REG (op)) == HImode)) - return 1; - return 0; -} - - -int -reg_imm_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (REG_P (op) || CONSTANT_P (op)) - return 1; - return 0; -} - - -int -not_modify_reg (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (REG_P (op) || CONSTANT_P (op)) - return 1; - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case REG: - return 1; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (! REG_P (op0)) - return 0; - - if (REG_P (op1) || GET_CODE (op1) == CONST_INT) - return 1; - } - - case LO_SUM: - { - rtx op0 = XEXP (op, 0); - - if (REG_P (op0) && REGNO (op0) == DP_REGNO) - return 1; - } - break; - - case CONST: - case SYMBOL_REF: - case LABEL_REF: - return 1; - - default: - break; - } - return 0; -} - - -int -not_rc_reg (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (REG_P (op) && REGNO (op) == RC_REGNO) - return 0; - return 1; -} - - -static void -c4x_S_address_parse (rtx op, int *base, int *incdec, int *index, int *disp) -{ - *base = 0; - *incdec = 0; - *index = 0; - *disp = 0; - - if (GET_CODE (op) != MEM) - fatal_insn ("invalid indirect memory address", op); - - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case PRE_DEC: - *base = REGNO (XEXP (op, 0)); - *incdec = 1; - *disp = -1; - return; - - case POST_DEC: - *base = REGNO (XEXP (op, 0)); - *incdec = 1; - *disp = 0; - return; - - case PRE_INC: - *base = REGNO (XEXP (op, 0)); - *incdec = 1; - *disp = 1; - return; - - case POST_INC: - *base = REGNO (XEXP (op, 0)); - *incdec = 1; - *disp = 0; - return; - - case POST_MODIFY: - *base = REGNO (XEXP (op, 0)); - if (REG_P (XEXP (XEXP (op, 1), 1))) - { - *index = REGNO (XEXP (XEXP (op, 1), 1)); - *disp = 0; /* ??? */ - } - else - *disp = INTVAL (XEXP (XEXP (op, 1), 1)); - *incdec = 1; - return; - - case PRE_MODIFY: - *base = REGNO (XEXP (op, 0)); - if (REG_P (XEXP (XEXP (op, 1), 1))) - { - *index = REGNO (XEXP (XEXP (op, 1), 1)); - *disp = 1; /* ??? */ - } - else - *disp = INTVAL (XEXP (XEXP (op, 1), 1)); - *incdec = 1; - - return; - - case REG: - *base = REGNO (op); - return; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if (c4x_a_register (op0)) - { - if (c4x_x_register (op1)) - { - *base = REGNO (op0); - *index = REGNO (op1); - return; - } - else if ((GET_CODE (op1) == CONST_INT - && IS_DISP1_CONST (INTVAL (op1)))) - { - *base = REGNO (op0); - *disp = INTVAL (op1); - return; - } - } - else if (c4x_x_register (op0) && c4x_a_register (op1)) - { - *base = REGNO (op1); - *index = REGNO (op0); - return; - } - } - /* Fall through. */ - - default: - fatal_insn ("invalid indirect (S) memory address", op); - } -} - - -int -c4x_address_conflict (rtx op0, rtx op1, int store0, int store1) -{ - int base0; - int base1; - int incdec0; - int incdec1; - int index0; - int index1; - int disp0; - int disp1; - - if (MEM_VOLATILE_P (op0) && MEM_VOLATILE_P (op1)) - return 1; - - c4x_S_address_parse (op0, &base0, &incdec0, &index0, &disp0); - c4x_S_address_parse (op1, &base1, &incdec1, &index1, &disp1); - - if (store0 && store1) - { - /* If we have two stores in parallel to the same address, then - the C4x only executes one of the stores. This is unlikely to - cause problems except when writing to a hardware device such - as a FIFO since the second write will be lost. The user - should flag the hardware location as being volatile so that - we don't do this optimization. While it is unlikely that we - have an aliased address if both locations are not marked - volatile, it is probably safer to flag a potential conflict - if either location is volatile. */ - if (! flag_argument_noalias) - { - if (MEM_VOLATILE_P (op0) || MEM_VOLATILE_P (op1)) - return 1; - } - } - - /* If have a parallel load and a store to the same address, the load - is performed first, so there is no conflict. Similarly, there is - no conflict if have parallel loads from the same address. */ - - /* Cannot use auto increment or auto decrement twice for same - base register. */ - if (base0 == base1 && incdec0 && incdec0) - return 1; - - /* It might be too confusing for GCC if we have use a base register - with a side effect and a memory reference using the same register - in parallel. */ - if (! TARGET_DEVEL && base0 == base1 && (incdec0 || incdec1)) - return 1; - - /* We cannot optimize the case where op1 and op2 refer to the same - address. */ - if (base0 == base1 && disp0 == disp1 && index0 == index1) - return 1; - - /* No conflict. */ - return 0; -} - - -/* Check for while loop inside a decrement and branch loop. */ - -int -c4x_label_conflict (rtx insn, rtx jump, rtx db) -{ - while (insn) - { - if (GET_CODE (insn) == CODE_LABEL) - { - if (CODE_LABEL_NUMBER (jump) == CODE_LABEL_NUMBER (insn)) - return 1; - if (CODE_LABEL_NUMBER (db) == CODE_LABEL_NUMBER (insn)) - return 0; - } - insn = PREV_INSN (insn); - } - return 1; -} - - -/* Validate combination of operands for parallel load/store instructions. */ - -int -valid_parallel_load_store (rtx *operands, - enum machine_mode mode ATTRIBUTE_UNUSED) -{ - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - rtx op3 = operands[3]; - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - if (GET_CODE (op3) == SUBREG) - op3 = SUBREG_REG (op3); - - /* The patterns should only allow ext_low_reg_operand() or - par_ind_operand() operands. Thus of the 4 operands, only 2 - should be REGs and the other 2 should be MEMs. */ - - /* This test prevents the multipack pass from using this pattern if - op0 is used as an index or base register in op2 or op3, since - this combination will require reloading. */ - if (GET_CODE (op0) == REG - && ((GET_CODE (op2) == MEM && reg_mentioned_p (op0, XEXP (op2, 0))) - || (GET_CODE (op3) == MEM && reg_mentioned_p (op0, XEXP (op3, 0))))) - return 0; - - /* LDI||LDI. */ - if (GET_CODE (op0) == REG && GET_CODE (op2) == REG) - return (REGNO (op0) != REGNO (op2)) - && GET_CODE (op1) == MEM && GET_CODE (op3) == MEM - && ! c4x_address_conflict (op1, op3, 0, 0); - - /* STI||STI. */ - if (GET_CODE (op1) == REG && GET_CODE (op3) == REG) - return GET_CODE (op0) == MEM && GET_CODE (op2) == MEM - && ! c4x_address_conflict (op0, op2, 1, 1); - - /* LDI||STI. */ - if (GET_CODE (op0) == REG && GET_CODE (op3) == REG) - return GET_CODE (op1) == MEM && GET_CODE (op2) == MEM - && ! c4x_address_conflict (op1, op2, 0, 1); - - /* STI||LDI. */ - if (GET_CODE (op1) == REG && GET_CODE (op2) == REG) - return GET_CODE (op0) == MEM && GET_CODE (op3) == MEM - && ! c4x_address_conflict (op0, op3, 1, 0); - - return 0; -} - - -int -valid_parallel_operands_4 (rtx *operands, - enum machine_mode mode ATTRIBUTE_UNUSED) -{ - rtx op0 = operands[0]; - rtx op2 = operands[2]; - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - - /* This test prevents the multipack pass from using this pattern if - op0 is used as an index or base register in op2, since this combination - will require reloading. */ - if (GET_CODE (op0) == REG - && GET_CODE (op2) == MEM - && reg_mentioned_p (op0, XEXP (op2, 0))) - return 0; - - return 1; -} - - -int -valid_parallel_operands_5 (rtx *operands, - enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int regs = 0; - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - rtx op3 = operands[3]; - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - - /* The patterns should only allow ext_low_reg_operand() or - par_ind_operand() operands. Operands 1 and 2 may be commutative - but only one of them can be a register. */ - if (GET_CODE (op1) == REG) - regs++; - if (GET_CODE (op2) == REG) - regs++; - - if (regs != 1) - return 0; - - /* This test prevents the multipack pass from using this pattern if - op0 is used as an index or base register in op3, since this combination - will require reloading. */ - if (GET_CODE (op0) == REG - && GET_CODE (op3) == MEM - && reg_mentioned_p (op0, XEXP (op3, 0))) - return 0; - - return 1; -} - - -int -valid_parallel_operands_6 (rtx *operands, - enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int regs = 0; - rtx op0 = operands[0]; - rtx op1 = operands[1]; - rtx op2 = operands[2]; - rtx op4 = operands[4]; - rtx op5 = operands[5]; - - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - if (GET_CODE (op4) == SUBREG) - op4 = SUBREG_REG (op4); - if (GET_CODE (op5) == SUBREG) - op5 = SUBREG_REG (op5); - - /* The patterns should only allow ext_low_reg_operand() or - par_ind_operand() operands. Thus of the 4 input operands, only 2 - should be REGs and the other 2 should be MEMs. */ - - if (GET_CODE (op1) == REG) - regs++; - if (GET_CODE (op2) == REG) - regs++; - if (GET_CODE (op4) == REG) - regs++; - if (GET_CODE (op5) == REG) - regs++; - - /* The new C30/C40 silicon dies allow 3 regs of the 4 input operands. - Perhaps we should count the MEMs as well? */ - if (regs != 2) - return 0; - - /* This test prevents the multipack pass from using this pattern if - op0 is used as an index or base register in op4 or op5, since - this combination will require reloading. */ - if (GET_CODE (op0) == REG - && ((GET_CODE (op4) == MEM && reg_mentioned_p (op0, XEXP (op4, 0))) - || (GET_CODE (op5) == MEM && reg_mentioned_p (op0, XEXP (op5, 0))))) - return 0; - - return 1; -} - - -/* Validate combination of src operands. Note that the operands have - been screened by the src_operand predicate. We just have to check - that the combination of operands is valid. If FORCE is set, ensure - that the destination regno is valid if we have a 2 operand insn. */ - -static int -c4x_valid_operands (enum rtx_code code, rtx *operands, - enum machine_mode mode ATTRIBUTE_UNUSED, - int force) -{ - rtx op0; - rtx op1; - rtx op2; - enum rtx_code code1; - enum rtx_code code2; - - - /* FIXME, why can't we tighten the operands for IF_THEN_ELSE? */ - if (code == IF_THEN_ELSE) - return 1 || (operands[0] == operands[2] || operands[0] == operands[3]); - - if (code == COMPARE) - { - op1 = operands[0]; - op2 = operands[1]; - } - else - { - op1 = operands[1]; - op2 = operands[2]; - } - - op0 = operands[0]; - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - if (GET_CODE (op2) == SUBREG) - op2 = SUBREG_REG (op2); - - code1 = GET_CODE (op1); - code2 = GET_CODE (op2); - - - if (code1 == REG && code2 == REG) - return 1; - - if (code1 == MEM && code2 == MEM) - { - if (c4x_S_indirect (op1) && c4x_S_indirect (op2)) - return 1; - return c4x_R_indirect (op1) && c4x_R_indirect (op2); - } - - /* We cannot handle two MEMs or two CONSTS, etc. */ - if (code1 == code2) - return 0; - - if (code1 == REG) - { - switch (code2) - { - case CONST_INT: - if (c4x_J_constant (op2) && c4x_R_indirect (op1)) - return 1; - break; - - case CONST_DOUBLE: - if (! c4x_H_constant (op2)) - return 0; - break; - - /* Any valid memory operand screened by src_operand is OK. */ - case MEM: - break; - - default: - fatal_insn ("c4x_valid_operands: Internal error", op2); - break; - } - - if (GET_CODE (op0) == SCRATCH) - return 1; - - if (!REG_P (op0)) - return 0; - - /* Check that we have a valid destination register for a two operand - instruction. */ - return ! force || code == COMPARE || REGNO (op1) == REGNO (op0); - } - - - /* Check non-commutative operators. */ - if (code == ASHIFTRT || code == LSHIFTRT - || code == ASHIFT || code == COMPARE) - return code2 == REG - && (c4x_S_indirect (op1) || c4x_R_indirect (op1)); - - - /* Assume MINUS is commutative since the subtract patterns - also support the reverse subtract instructions. Since op1 - is not a register, and op2 is a register, op1 can only - be a restricted memory operand for a shift instruction. */ - if (code2 == REG) - { - switch (code1) - { - case CONST_INT: - break; - - case CONST_DOUBLE: - if (! c4x_H_constant (op1)) - return 0; - break; - - /* Any valid memory operand screened by src_operand is OK. */ - case MEM: - break; - - default: - abort (); - break; - } - - if (GET_CODE (op0) == SCRATCH) - return 1; - - if (!REG_P (op0)) - return 0; - - /* Check that we have a valid destination register for a two operand - instruction. */ - return ! force || REGNO (op1) == REGNO (op0); - } - - if (c4x_J_constant (op1) && c4x_R_indirect (op2)) - return 1; - - return 0; -} - - -int valid_operands (enum rtx_code code, rtx *operands, enum machine_mode mode) -{ - - /* If we are not optimizing then we have to let anything go and let - reload fix things up. instantiate_decl in function.c can produce - invalid insns by changing the offset of a memory operand from a - valid one into an invalid one, when the second operand is also a - memory operand. The alternative is not to allow two memory - operands for an insn when not optimizing. The problem only rarely - occurs, for example with the C-torture program DFcmp.c. */ - - return ! optimize || c4x_valid_operands (code, operands, mode, 0); -} - - -int -legitimize_operands (enum rtx_code code, rtx *operands, enum machine_mode mode) -{ - /* Compare only has 2 operands. */ - if (code == COMPARE) - { - /* During RTL generation, force constants into pseudos so that - they can get hoisted out of loops. This will tie up an extra - register but can save an extra cycle. Only do this if loop - optimization enabled. (We cannot pull this trick for add and - sub instructions since the flow pass won't find - autoincrements etc.) This allows us to generate compare - instructions like CMPI R0, *AR0++ where R0 = 42, say, instead - of LDI *AR0++, R0; CMPI 42, R0. - - Note that expand_binops will try to load an expensive constant - into a register if it is used within a loop. Unfortunately, - the cost mechanism doesn't allow us to look at the other - operand to decide whether the constant is expensive. */ - - if (! reload_in_progress - && TARGET_HOIST - && optimize > 0 - && GET_CODE (operands[1]) == CONST_INT - && rtx_cost (operands[1], code) > 1) - operands[1] = force_reg (mode, operands[1]); - - if (! reload_in_progress - && ! c4x_valid_operands (code, operands, mode, 0)) - operands[0] = force_reg (mode, operands[0]); - return 1; - } - - /* We cannot do this for ADDI/SUBI insns since we will - defeat the flow pass from finding autoincrement addressing - opportunities. */ - if (! reload_in_progress - && ! ((code == PLUS || code == MINUS) && mode == Pmode) - && TARGET_HOIST - && optimize > 1 - && GET_CODE (operands[2]) == CONST_INT - && rtx_cost (operands[2], code) > 1) - operands[2] = force_reg (mode, operands[2]); - - /* We can get better code on a C30 if we force constant shift counts - into a register. This way they can get hoisted out of loops, - tying up a register but saving an instruction. The downside is - that they may get allocated to an address or index register, and - thus we will get a pipeline conflict if there is a nearby - indirect address using an address register. - - Note that expand_binops will not try to load an expensive constant - into a register if it is used within a loop for a shift insn. */ - - if (! reload_in_progress - && ! c4x_valid_operands (code, operands, mode, TARGET_FORCE)) - { - /* If the operand combination is invalid, we force operand1 into a - register, preventing reload from having doing to do this at a - later stage. */ - operands[1] = force_reg (mode, operands[1]); - if (TARGET_FORCE) - { - emit_move_insn (operands[0], operands[1]); - operands[1] = copy_rtx (operands[0]); - } - else - { - /* Just in case... */ - if (! c4x_valid_operands (code, operands, mode, 0)) - operands[2] = force_reg (mode, operands[2]); - } - } - - /* Right shifts require a negative shift count, but GCC expects - a positive count, so we emit a NEG. */ - if ((code == ASHIFTRT || code == LSHIFTRT) - && (GET_CODE (operands[2]) != CONST_INT)) - operands[2] = gen_rtx_NEG (mode, negate_rtx (mode, operands[2])); - - - /* When the shift count is greater than 32 then the result - can be implementation dependent. We truncate the result to - fit in 5 bits so that we do not emit invalid code when - optimizing---such as trying to generate lhu2 with 20021124-1.c. */ - if (((code == ASHIFTRT || code == LSHIFTRT || code == ASHIFT) - && (GET_CODE (operands[2]) == CONST_INT)) - && INTVAL (operands[2]) > (GET_MODE_BITSIZE (mode) - 1)) - operands[2] - = GEN_INT (INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1)); - - return 1; -} - - -/* The following predicates are used for instruction scheduling. */ - -int -group1_reg_operand (rtx op, enum machine_mode mode) -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && (! reload_completed || IS_GROUP1_REG (op)); -} - - -int -group1_mem_operand (rtx op, enum machine_mode mode) -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - - if (GET_CODE (op) == MEM) - { - op = XEXP (op, 0); - if (GET_CODE (op) == PLUS) - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if ((REG_P (op0) && (! reload_completed || IS_GROUP1_REG (op0))) - || (REG_P (op1) && (! reload_completed || IS_GROUP1_REG (op1)))) - return 1; - } - else if ((REG_P (op)) && (! reload_completed || IS_GROUP1_REG (op))) - return 1; - } - - return 0; -} - - -/* Return true if any one of the address registers. */ - -int -arx_reg_operand (rtx op, enum machine_mode mode) -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && (! reload_completed || IS_ADDR_REG (op)); -} - - -static int -c4x_arn_reg_operand (rtx op, enum machine_mode mode, unsigned int regno) -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && (! reload_completed || (REGNO (op) == regno)); -} - - -static int -c4x_arn_mem_operand (rtx op, enum machine_mode mode, unsigned int regno) -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - - if (GET_CODE (op) == MEM) - { - op = XEXP (op, 0); - switch (GET_CODE (op)) - { - case PRE_DEC: - case POST_DEC: - case PRE_INC: - case POST_INC: - op = XEXP (op, 0); - - case REG: - return REG_P (op) && (! reload_completed || (REGNO (op) == regno)); - - case PRE_MODIFY: - case POST_MODIFY: - if (REG_P (XEXP (op, 0)) && (! reload_completed - || (REGNO (XEXP (op, 0)) == regno))) - return 1; - if (REG_P (XEXP (XEXP (op, 1), 1)) - && (! reload_completed - || (REGNO (XEXP (XEXP (op, 1), 1)) == regno))) - return 1; - break; - - case PLUS: - { - rtx op0 = XEXP (op, 0); - rtx op1 = XEXP (op, 1); - - if ((REG_P (op0) && (! reload_completed - || (REGNO (op0) == regno))) - || (REG_P (op1) && (! reload_completed - || (REGNO (op1) == regno)))) - return 1; - } - break; - - default: - break; - } - } - return 0; -} - - -int -ar0_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, AR0_REGNO); -} - - -int -ar0_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, AR0_REGNO); -} - - -int -ar1_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, AR1_REGNO); -} - - -int -ar1_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, AR1_REGNO); -} - - -int -ar2_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, AR2_REGNO); -} - - -int -ar2_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, AR2_REGNO); -} - - -int -ar3_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, AR3_REGNO); -} - - -int -ar3_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, AR3_REGNO); -} - - -int -ar4_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, AR4_REGNO); -} - - -int -ar4_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, AR4_REGNO); -} - - -int -ar5_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, AR5_REGNO); -} - - -int -ar5_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, AR5_REGNO); -} - - -int -ar6_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, AR6_REGNO); -} - - -int -ar6_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, AR6_REGNO); -} - - -int -ar7_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, AR7_REGNO); -} - - -int -ar7_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, AR7_REGNO); -} - - -int -ir0_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, IR0_REGNO); -} - - -int -ir0_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, IR0_REGNO); -} - - -int -ir1_reg_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_reg_operand (op, mode, IR1_REGNO); -} - - -int -ir1_mem_operand (rtx op, enum machine_mode mode) -{ - return c4x_arn_mem_operand (op, mode, IR1_REGNO); -} - - -/* This is similar to operand_subword but allows autoincrement - addressing. */ - -rtx -c4x_operand_subword (rtx op, int i, int validate_address, - enum machine_mode mode) -{ - if (mode != HImode && mode != HFmode) - fatal_insn ("c4x_operand_subword: invalid mode", op); - - if (mode == HFmode && REG_P (op)) - fatal_insn ("c4x_operand_subword: invalid operand", op); - - if (GET_CODE (op) == MEM) - { - enum rtx_code code = GET_CODE (XEXP (op, 0)); - enum machine_mode mode = GET_MODE (XEXP (op, 0)); - enum machine_mode submode; - - submode = mode; - if (mode == HImode) - submode = QImode; - else if (mode == HFmode) - submode = QFmode; - - switch (code) - { - case POST_INC: - case PRE_INC: - return gen_rtx_MEM (submode, XEXP (op, 0)); - - case POST_DEC: - case PRE_DEC: - case PRE_MODIFY: - case POST_MODIFY: - /* We could handle these with some difficulty. - e.g., *p-- => *(p-=2); *(p+1). */ - fatal_insn ("c4x_operand_subword: invalid autoincrement", op); - - case SYMBOL_REF: - case LABEL_REF: - case CONST: - case CONST_INT: - fatal_insn ("c4x_operand_subword: invalid address", op); - - /* Even though offsettable_address_p considers (MEM - (LO_SUM)) to be offsettable, it is not safe if the - address is at the end of the data page since we also have - to fix up the associated high PART. In this case where - we are trying to split a HImode or HFmode memory - reference, we would have to emit another insn to reload a - new HIGH value. It's easier to disable LO_SUM memory references - in HImode or HFmode and we probably get better code. */ - case LO_SUM: - fatal_insn ("c4x_operand_subword: address not offsettable", op); - - default: - break; - } - } - - return operand_subword (op, i, validate_address, mode); -} - -struct name_list -{ - struct name_list *next; - const char *name; -}; - -static struct name_list *global_head; -static struct name_list *extern_head; - - -/* Add NAME to list of global symbols and remove from external list if - present on external list. */ - -void -c4x_global_label (const char *name) -{ - struct name_list *p, *last; - - /* Do not insert duplicate names, so linearly search through list of - existing names. */ - p = global_head; - while (p) - { - if (strcmp (p->name, name) == 0) - return; - p = p->next; - } - p = (struct name_list *) xmalloc (sizeof *p); - p->next = global_head; - p->name = name; - global_head = p; - - /* Remove this name from ref list if present. */ - last = NULL; - p = extern_head; - while (p) - { - if (strcmp (p->name, name) == 0) - { - if (last) - last->next = p->next; - else - extern_head = p->next; - break; - } - last = p; - p = p->next; - } -} - - -/* Add NAME to list of external symbols. */ - -void -c4x_external_ref (const char *name) -{ - struct name_list *p; - - /* Do not insert duplicate names. */ - p = extern_head; - while (p) - { - if (strcmp (p->name, name) == 0) - return; - p = p->next; - } - - /* Do not insert ref if global found. */ - p = global_head; - while (p) - { - if (strcmp (p->name, name) == 0) - return; - p = p->next; - } - p = (struct name_list *) xmalloc (sizeof *p); - p->next = extern_head; - p->name = name; - extern_head = p; -} - -/* We need to have a data section we can identify so that we can set - the DP register back to a data pointer in the small memory model. - This is only required for ISRs if we are paranoid that someone - may have quietly changed this register on the sly. */ -static void -c4x_file_start (void) -{ - default_file_start (); - fprintf (asm_out_file, "\t.version\t%d\n", c4x_cpu_version); - fputs ("\n\t.data\ndata_sec:\n", asm_out_file); -} - - -static void -c4x_file_end (void) -{ - struct name_list *p; - - /* Output all external names that are not global. */ - p = extern_head; - while (p) - { - fprintf (asm_out_file, "\t.ref\t"); - assemble_name (asm_out_file, p->name); - fprintf (asm_out_file, "\n"); - p = p->next; - } - fprintf (asm_out_file, "\t.end\n"); -} - - -static void -c4x_check_attribute (const char *attrib, tree list, tree decl, tree *attributes) -{ - while (list != NULL_TREE - && IDENTIFIER_POINTER (TREE_PURPOSE (list)) - != IDENTIFIER_POINTER (DECL_NAME (decl))) - list = TREE_CHAIN (list); - if (list) - *attributes = tree_cons (get_identifier (attrib), TREE_VALUE (list), - *attributes); -} - - -static void -c4x_insert_attributes (tree decl, tree *attributes) -{ - switch (TREE_CODE (decl)) - { - case FUNCTION_DECL: - c4x_check_attribute ("section", code_tree, decl, attributes); - c4x_check_attribute ("const", pure_tree, decl, attributes); - c4x_check_attribute ("noreturn", noreturn_tree, decl, attributes); - c4x_check_attribute ("interrupt", interrupt_tree, decl, attributes); - c4x_check_attribute ("naked", naked_tree, decl, attributes); - break; - - case VAR_DECL: - c4x_check_attribute ("section", data_tree, decl, attributes); - break; - - default: - break; - } -} - -/* Table of valid machine attributes. */ -const struct attribute_spec c4x_attribute_table[] = -{ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - { "interrupt", 0, 0, false, true, true, c4x_handle_fntype_attribute }, - { "naked", 0, 0, false, true, true, c4x_handle_fntype_attribute }, - { "leaf_pretend", 0, 0, false, true, true, c4x_handle_fntype_attribute }, - { NULL, 0, 0, false, false, false, NULL } -}; - -/* Handle an attribute requiring a FUNCTION_TYPE; - arguments as in struct attribute_spec.handler. */ -static tree -c4x_handle_fntype_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) -{ - if (TREE_CODE (*node) != FUNCTION_TYPE) - { - warning (OPT_Wattributes, "%qs attribute only applies to functions", - IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - - return NULL_TREE; -} - - -/* !!! FIXME to emit RPTS correctly. */ - -int -c4x_rptb_rpts_p (rtx insn, rtx op) -{ - /* The next insn should be our label marking where the - repeat block starts. */ - insn = NEXT_INSN (insn); - if (GET_CODE (insn) != CODE_LABEL) - { - /* Some insns may have been shifted between the RPTB insn - and the top label... They were probably destined to - be moved out of the loop. For now, let's leave them - where they are and print a warning. We should - probably move these insns before the repeat block insn. */ - if (TARGET_DEBUG) - fatal_insn ("c4x_rptb_rpts_p: Repeat block top label moved", - insn); - return 0; - } - - /* Skip any notes. */ - insn = next_nonnote_insn (insn); - - /* This should be our first insn in the loop. */ - if (! INSN_P (insn)) - return 0; - - /* Skip any notes. */ - insn = next_nonnote_insn (insn); - - if (! INSN_P (insn)) - return 0; - - if (recog_memoized (insn) != CODE_FOR_rptb_end) - return 0; - - if (TARGET_RPTS) - return 1; - - return (GET_CODE (op) == CONST_INT) && TARGET_RPTS_CYCLES (INTVAL (op)); -} - - -/* Check if register r11 is used as the destination of an insn. */ - -static int -c4x_r11_set_p(rtx x) -{ - rtx set; - int i, j; - const char *fmt; - - if (x == 0) - return 0; - - if (INSN_P (x) && GET_CODE (PATTERN (x)) == SEQUENCE) - x = XVECEXP (PATTERN (x), 0, XVECLEN (PATTERN (x), 0) - 1); - - if (INSN_P (x) && (set = single_set (x))) - x = SET_DEST (set); - - if (GET_CODE (x) == REG && REGNO (x) == R11_REGNO) - return 1; - - fmt = GET_RTX_FORMAT (GET_CODE (x)); - for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - if (c4x_r11_set_p (XEXP (x, i))) - return 1; - } - else if (fmt[i] == 'E') - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if (c4x_r11_set_p (XVECEXP (x, i, j))) - return 1; - } - return 0; -} - - -/* The c4x sometimes has a problem when the insn before the laj insn - sets the r11 register. Check for this situation. */ - -int -c4x_check_laj_p (rtx insn) -{ - insn = prev_nonnote_insn (insn); - - /* If this is the start of the function no nop is needed. */ - if (insn == 0) - return 0; - - /* If the previous insn is a code label we have to insert a nop. This - could be a jump or table jump. We can find the normal jumps by - scanning the function but this will not find table jumps. */ - if (GET_CODE (insn) == CODE_LABEL) - return 1; - - /* If the previous insn sets register r11 we have to insert a nop. */ - if (c4x_r11_set_p (insn)) - return 1; - - /* No nop needed. */ - return 0; -} - - -/* Adjust the cost of a scheduling dependency. Return the new cost of - a dependency LINK or INSN on DEP_INSN. COST is the current cost. - A set of an address register followed by a use occurs a 2 cycle - stall (reduced to a single cycle on the c40 using LDA), while - a read of an address register followed by a use occurs a single cycle. */ - -#define SET_USE_COST 3 -#define SETLDA_USE_COST 2 -#define READ_USE_COST 2 - -static int -c4x_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost) -{ - /* Don't worry about this until we know what registers have been - assigned. */ - if (flag_schedule_insns == 0 && ! reload_completed) - return 0; - - /* How do we handle dependencies where a read followed by another - read causes a pipeline stall? For example, a read of ar0 followed - by the use of ar0 for a memory reference. It looks like we - need to extend the scheduler to handle this case. */ - - /* Reload sometimes generates a CLOBBER of a stack slot, e.g., - (clobber (mem:QI (plus:QI (reg:QI 11 ar3) (const_int 261)))), - so only deal with insns we know about. */ - if (recog_memoized (dep_insn) < 0) - return 0; - - if (REG_NOTE_KIND (link) == 0) - { - int max = 0; - - /* Data dependency; DEP_INSN writes a register that INSN reads some - cycles later. */ - if (TARGET_C3X) - { - if (get_attr_setgroup1 (dep_insn) && get_attr_usegroup1 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_readarx (dep_insn) && get_attr_usegroup1 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - } - else - { - /* This could be significantly optimized. We should look - to see if dep_insn sets ar0-ar7 or ir0-ir1 and if - insn uses ar0-ar7. We then test if the same register - is used. The tricky bit is that some operands will - use several registers... */ - if (get_attr_setar0 (dep_insn) && get_attr_usear0 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar0 (dep_insn) && get_attr_usear0 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar0 (dep_insn) && get_attr_usear0 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar1 (dep_insn) && get_attr_usear1 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar1 (dep_insn) && get_attr_usear1 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar1 (dep_insn) && get_attr_usear1 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar2 (dep_insn) && get_attr_usear2 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar2 (dep_insn) && get_attr_usear2 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar2 (dep_insn) && get_attr_usear2 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar3 (dep_insn) && get_attr_usear3 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar3 (dep_insn) && get_attr_usear3 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar3 (dep_insn) && get_attr_usear3 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar4 (dep_insn) && get_attr_usear4 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar4 (dep_insn) && get_attr_usear4 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar4 (dep_insn) && get_attr_usear4 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar5 (dep_insn) && get_attr_usear5 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar5 (dep_insn) && get_attr_usear5 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar5 (dep_insn) && get_attr_usear5 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar6 (dep_insn) && get_attr_usear6 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar6 (dep_insn) && get_attr_usear6 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar6 (dep_insn) && get_attr_usear6 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setar7 (dep_insn) && get_attr_usear7 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ar7 (dep_insn) && get_attr_usear7 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - if (get_attr_readar7 (dep_insn) && get_attr_usear7 (insn)) - max = READ_USE_COST > max ? READ_USE_COST : max; - - if (get_attr_setir0 (dep_insn) && get_attr_useir0 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ir0 (dep_insn) && get_attr_useir0 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - - if (get_attr_setir1 (dep_insn) && get_attr_useir1 (insn)) - max = SET_USE_COST > max ? SET_USE_COST : max; - if (get_attr_setlda_ir1 (dep_insn) && get_attr_useir1 (insn)) - max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max; - } - - if (max) - cost = max; - - /* For other data dependencies, the default cost specified in the - md is correct. */ - return cost; - } - else if (REG_NOTE_KIND (link) == REG_DEP_ANTI) - { - /* Anti dependency; DEP_INSN reads a register that INSN writes some - cycles later. */ - - /* For c4x anti dependencies, the cost is 0. */ - return 0; - } - else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT) - { - /* Output dependency; DEP_INSN writes a register that INSN writes some - cycles later. */ - - /* For c4x output dependencies, the cost is 0. */ - return 0; - } - else - abort (); -} - -void -c4x_init_builtins (void) -{ - tree endlink = void_list_node; - - add_builtin_function ("fast_ftoi", - build_function_type - (integer_type_node, - tree_cons (NULL_TREE, double_type_node, - endlink)), - C4X_BUILTIN_FIX, BUILT_IN_MD, NULL, NULL_TREE); - add_builtin_function ("ansi_ftoi", - build_function_type - (integer_type_node, - tree_cons (NULL_TREE, double_type_node, - endlink)), - C4X_BUILTIN_FIX_ANSI, BUILT_IN_MD, NULL, - NULL_TREE); - if (TARGET_C3X) - add_builtin_function ("fast_imult", - build_function_type - (integer_type_node, - tree_cons (NULL_TREE, integer_type_node, - tree_cons (NULL_TREE, - integer_type_node, - endlink))), - C4X_BUILTIN_MPYI, BUILT_IN_MD, NULL, - NULL_TREE); - else - { - add_builtin_function ("toieee", - build_function_type - (double_type_node, - tree_cons (NULL_TREE, double_type_node, - endlink)), - C4X_BUILTIN_TOIEEE, BUILT_IN_MD, NULL, - NULL_TREE); - add_builtin_function ("frieee", - build_function_type - (double_type_node, - tree_cons (NULL_TREE, double_type_node, - endlink)), - C4X_BUILTIN_FRIEEE, BUILT_IN_MD, NULL, - NULL_TREE); - add_builtin_function ("fast_invf", - build_function_type - (double_type_node, - tree_cons (NULL_TREE, double_type_node, - endlink)), - C4X_BUILTIN_RCPF, BUILT_IN_MD, NULL, - NULL_TREE); - } -} - - -rtx -c4x_expand_builtin (tree exp, rtx target, - rtx subtarget ATTRIBUTE_UNUSED, - enum machine_mode mode ATTRIBUTE_UNUSED, - int ignore ATTRIBUTE_UNUSED) -{ - tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); - unsigned int fcode = DECL_FUNCTION_CODE (fndecl); - tree arg0, arg1; - rtx r0, r1; - - switch (fcode) - { - case C4X_BUILTIN_FIX: - arg0 = CALL_EXPR_ARG (exp, 0); - r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); - if (! target || ! register_operand (target, QImode)) - target = gen_reg_rtx (QImode); - emit_insn (gen_fixqfqi_clobber (target, r0)); - return target; - - case C4X_BUILTIN_FIX_ANSI: - arg0 = CALL_EXPR_ARG (exp, 0); - r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); - if (! target || ! register_operand (target, QImode)) - target = gen_reg_rtx (QImode); - emit_insn (gen_fix_truncqfqi2 (target, r0)); - return target; - - case C4X_BUILTIN_MPYI: - if (! TARGET_C3X) - break; - arg0 = CALL_EXPR_ARG (exp, 0); - arg1 = CALL_EXPR_ARG (exp, 1); - r0 = expand_expr (arg0, NULL_RTX, QImode, 0); - r1 = expand_expr (arg1, NULL_RTX, QImode, 0); - if (! target || ! register_operand (target, QImode)) - target = gen_reg_rtx (QImode); - emit_insn (gen_mulqi3_24_clobber (target, r0, r1)); - return target; - - case C4X_BUILTIN_TOIEEE: - if (TARGET_C3X) - break; - arg0 = CALL_EXPR_ARG (exp, 0); - r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); - if (! target || ! register_operand (target, QFmode)) - target = gen_reg_rtx (QFmode); - emit_insn (gen_toieee (target, r0)); - return target; - - case C4X_BUILTIN_FRIEEE: - if (TARGET_C3X) - break; - arg0 = CALL_EXPR_ARG (exp, 0); - r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); - if (register_operand (r0, QFmode)) - { - r1 = assign_stack_local (QFmode, GET_MODE_SIZE (QFmode), 0); - emit_move_insn (r1, r0); - r0 = r1; - } - if (! target || ! register_operand (target, QFmode)) - target = gen_reg_rtx (QFmode); - emit_insn (gen_frieee (target, r0)); - return target; - - case C4X_BUILTIN_RCPF: - if (TARGET_C3X) - break; - arg0 = CALL_EXPR_ARG (exp, 0); - r0 = expand_expr (arg0, NULL_RTX, QFmode, 0); - if (! target || ! register_operand (target, QFmode)) - target = gen_reg_rtx (QFmode); - emit_insn (gen_rcpfqf_clobber (target, r0)); - return target; - } - return NULL_RTX; -} - -static void -c4x_init_libfuncs (void) -{ - set_optab_libfunc (smul_optab, QImode, "__mulqi3"); - set_optab_libfunc (sdiv_optab, QImode, "__divqi3"); - set_optab_libfunc (udiv_optab, QImode, "__udivqi3"); - set_optab_libfunc (smod_optab, QImode, "__modqi3"); - set_optab_libfunc (umod_optab, QImode, "__umodqi3"); - set_optab_libfunc (sdiv_optab, QFmode, "__divqf3"); - set_optab_libfunc (smul_optab, HFmode, "__mulhf3"); - set_optab_libfunc (sdiv_optab, HFmode, "__divhf3"); - set_optab_libfunc (smul_optab, HImode, "__mulhi3"); - set_optab_libfunc (sdiv_optab, HImode, "__divhi3"); - set_optab_libfunc (udiv_optab, HImode, "__udivhi3"); - set_optab_libfunc (smod_optab, HImode, "__modhi3"); - set_optab_libfunc (umod_optab, HImode, "__umodhi3"); - set_optab_libfunc (ffs_optab, QImode, "__ffs"); - smulhi3_libfunc = init_one_libfunc ("__smulhi3_high"); - umulhi3_libfunc = init_one_libfunc ("__umulhi3_high"); - fix_truncqfhi2_libfunc = init_one_libfunc ("__fix_truncqfhi2"); - fixuns_truncqfhi2_libfunc = init_one_libfunc ("__ufix_truncqfhi2"); - fix_trunchfhi2_libfunc = init_one_libfunc ("__fix_trunchfhi2"); - fixuns_trunchfhi2_libfunc = init_one_libfunc ("__ufix_trunchfhi2"); - floathiqf2_libfunc = init_one_libfunc ("__floathiqf2"); - floatunshiqf2_libfunc = init_one_libfunc ("__ufloathiqf2"); - floathihf2_libfunc = init_one_libfunc ("__floathihf2"); - floatunshihf2_libfunc = init_one_libfunc ("__ufloathihf2"); -} - -static void -c4x_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED, - tree decl ATTRIBUTE_UNUSED) -{ - fprintf (asm_out_file, "\t.sect\t\"%s\"\n", name); -} - -static void -c4x_globalize_label (FILE *stream, const char *name) -{ - default_globalize_label (stream, name); - c4x_global_label (name); -} - -#define SHIFT_CODE_P(C) \ - ((C) == ASHIFT || (C) == ASHIFTRT || (C) == LSHIFTRT) -#define LOGICAL_CODE_P(C) \ - ((C) == NOT || (C) == AND || (C) == IOR || (C) == XOR) - -/* Compute a (partial) cost for rtx X. Return true if the complete - cost has been computed, and false if subexpressions should be - scanned. In either case, *TOTAL contains the cost result. */ - -static bool -c4x_rtx_costs (rtx x, int code, int outer_code, int *total) -{ - HOST_WIDE_INT val; - - switch (code) - { - /* Some small integers are effectively free for the C40. We should - also consider if we are using the small memory model. With - the big memory model we require an extra insn for a constant - loaded from memory. */ - - case CONST_INT: - val = INTVAL (x); - if (c4x_J_constant (x)) - *total = 0; - else if (! TARGET_C3X - && outer_code == AND - && (val == 255 || val == 65535)) - *total = 0; - else if (! TARGET_C3X - && (outer_code == ASHIFTRT || outer_code == LSHIFTRT) - && (val == 16 || val == 24)) - *total = 0; - else if (TARGET_C3X && SHIFT_CODE_P (outer_code)) - *total = 3; - else if (LOGICAL_CODE_P (outer_code) - ? c4x_L_constant (x) : c4x_I_constant (x)) - *total = 2; - else - *total = 4; - return true; - - case CONST: - case LABEL_REF: - case SYMBOL_REF: - *total = 4; - return true; - - case CONST_DOUBLE: - if (c4x_H_constant (x)) - *total = 2; - else if (GET_MODE (x) == QFmode) - *total = 4; - else - *total = 8; - return true; - - /* ??? Note that we return true, rather than false so that rtx_cost - doesn't include the constant costs. Otherwise expand_mult will - think that it is cheaper to synthesize a multiply rather than to - use a multiply instruction. I think this is because the algorithm - synth_mult doesn't take into account the loading of the operands, - whereas the calculation of mult_cost does. */ - case PLUS: - case MINUS: - case AND: - case IOR: - case XOR: - case ASHIFT: - case ASHIFTRT: - case LSHIFTRT: - *total = COSTS_N_INSNS (1); - return true; - - case MULT: - *total = COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT - || TARGET_MPYI ? 1 : 14); - return true; - - case DIV: - case UDIV: - case MOD: - case UMOD: - *total = COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT - ? 15 : 50); - return true; - - default: - return false; - } -} - -/* Worker function for TARGET_ASM_EXTERNAL_LIBCALL. */ - -static void -c4x_external_libcall (rtx fun) -{ - /* This is only needed to keep asm30 happy for ___divqf3 etc. */ - c4x_external_ref (XSTR (fun, 0)); -} - -/* Worker function for TARGET_STRUCT_VALUE_RTX. */ - -static rtx -c4x_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, - int incoming ATTRIBUTE_UNUSED) -{ - return gen_rtx_REG (Pmode, AR0_REGNO); -} diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h deleted file mode 100644 index 09a7672b15a..00000000000 --- a/gcc/config/c4x/c4x.h +++ /dev/null @@ -1,1649 +0,0 @@ -/* Definitions of target machine for GNU compiler. TMS320C[34]x - Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. - - Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) - and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -/* RUN-TIME TARGET SPECIFICATION. */ - -#define C4x 1 - -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - extern int flag_inline_trees; \ - if (!TARGET_SMALL) \ - builtin_define ("_BIGMODEL"); \ - if (!TARGET_MEMPARM) \ - builtin_define ("_REGPARM"); \ - if (flag_inline_functions) \ - builtin_define ("_INLINE"); \ - if (TARGET_C3X) \ - { \ - builtin_define ("_TMS320C3x"); \ - builtin_define ("_C3x"); \ - if (TARGET_C30) \ - { \ - builtin_define ("_TMS320C30"); \ - builtin_define ("_C30"); \ - } \ - else if (TARGET_C31) \ - { \ - builtin_define ("_TMS320C31"); \ - builtin_define ("_C31"); \ - } \ - else if (TARGET_C32) \ - { \ - builtin_define ("_TMS320C32"); \ - builtin_define ("_C32"); \ - } \ - else if (TARGET_C33) \ - { \ - builtin_define ("_TMS320C33"); \ - builtin_define ("_C33"); \ - } \ - } \ - else \ - { \ - builtin_define ("_TMS320C4x"); \ - builtin_define ("_C4x"); \ - if (TARGET_C40) \ - { \ - builtin_define ("_TMS320C40"); \ - builtin_define ("_C40"); \ - } \ - else if (TARGET_C44) \ - { \ - builtin_define ("_TMS320C44"); \ - builtin_define ("_C44"); \ - } \ - } \ - } \ - while (0) - -/* Define assembler options. */ - -#define ASM_SPEC "\ -%{!mcpu=30:%{!mcpu=31:%{!mcpu=32:%{!mcpu=33:%{!mcpu=40:%{!mcpu=44:\ -%{!m30:%{!m31:%{!m32:%{!m33:%{!m40:%{!m44:-m40}}}}}}}}}}}} \ -%{mcpu=30} \ -%{mcpu=31} \ -%{mcpu=32} \ -%{mcpu=33} \ -%{mcpu=40} \ -%{mcpu=44} \ -%{m30} \ -%{m31} \ -%{m32} \ -%{m33} \ -%{m40} \ -%{m44} \ -%{mmemparm} %{mregparm} %{!mmemparm:%{!mregparm:-mregparm}} \ -%{mbig} %{msmall} %{!msmall:%{!mbig:-mbig}}" - -/* Define linker options. */ - -#define LINK_SPEC "\ -%{m30:--architecture c3x} \ -%{m31:--architecture c3x} \ -%{m32:--architecture c3x} \ -%{m33:--architecture c3x} \ -%{mcpu=30:--architecture c3x} \ -%{mcpu=31:--architecture c3x} \ -%{mcpu=32:--architecture c3x} \ -%{mcpu=33:--architecture c3x}" - -/* Specify the end file to link with. */ - -#define ENDFILE_SPEC "" - -/* Caveats: - Max iteration count for RPTB/RPTS is 2^31 + 1. - Max iteration count for DB is 2^31 + 1 for C40, but 2^23 + 1 for C30. - RPTS blocks interrupts. */ - - -extern int c4x_cpu_version; /* Cpu version C30/31/32/33/40/44. */ - -#define TARGET_INLINE (! optimize_size) /* Inline MPYI. */ -#define TARGET_SMALL_REG_CLASS 0 - -#define TARGET_C3X (c4x_cpu_version >= 30 \ - && c4x_cpu_version <= 39) - -#define TARGET_C30 (c4x_cpu_version == 30) -#define TARGET_C31 (c4x_cpu_version == 31) -#define TARGET_C32 (c4x_cpu_version == 32) -#define TARGET_C33 (c4x_cpu_version == 33) -#define TARGET_C40 (c4x_cpu_version == 40) -#define TARGET_C44 (c4x_cpu_version == 44) - -/* Nonzero to use load_immed_addr pattern rather than forcing memory - addresses into memory. */ -#define TARGET_LOAD_ADDRESS (1 || (! TARGET_C3X && ! TARGET_SMALL)) - -/* Nonzero to convert direct memory references into HIGH/LO_SUM pairs - during RTL generation. */ -#define TARGET_EXPOSE_LDP 0 - -/* Nonzero to force loading of direct memory references into a register. */ -#define TARGET_LOAD_DIRECT_MEMS 0 - -/* -mrpts allows the use of the RPTS instruction irregardless. - -mrpts=max-cycles will use RPTS if the number of cycles is constant - and less than max-cycles. */ - -#define TARGET_RPTS_CYCLES(CYCLES) (TARGET_RPTS || (CYCLES) < c4x_rpts_cycles) - -/* 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. */ - -#define OVERRIDE_OPTIONS c4x_override_options () - -/* Define this to change the optimizations performed by default. */ - -#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) c4x_optimization_options(LEVEL, SIZE) - -/* Run Time Target Specification. */ - -#define TARGET_VERSION fprintf (stderr, " (TMS320C[34]x, TI syntax)"); - -/* Storage Layout. */ - -#define BITS_BIG_ENDIAN 0 -#define BYTES_BIG_ENDIAN 0 -#define WORDS_BIG_ENDIAN 0 - -/* Technically, we are little endian, but we put the floats out as - whole longs and this makes GCC put them out in the right order. */ - -#define FLOAT_WORDS_BIG_ENDIAN 1 - -/* Note the ANSI C standard requires sizeof(char) = 1. On the C[34]x - all integral and floating point data types are stored in memory as - 32-bits (floating point types can be stored as 40-bits in the - extended precision registers), so sizeof(char) = sizeof(short) = - sizeof(int) = sizeof(long) = sizeof(float) = sizeof(double) = 1. */ - -#define BITS_PER_UNIT 32 -#define UNITS_PER_WORD 1 -#define PARM_BOUNDARY 32 -#define STACK_BOUNDARY 32 -#define FUNCTION_BOUNDARY 32 -#define BIGGEST_ALIGNMENT 32 -#define EMPTY_FIELD_BOUNDARY 32 -#define STRICT_ALIGNMENT 0 -#define TARGET_FLOAT_FORMAT C4X_FLOAT_FORMAT -#define MAX_FIXED_MODE_SIZE 64 /* HImode. */ - -/* If a structure has a floating point field then force structure - to have BLKMODE, unless it is the only field. */ -#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \ - (TREE_CODE (TREE_TYPE (FIELD)) == REAL_TYPE && (MODE) == VOIDmode) - -/* Number of bits in the high and low parts of a two stage - load of an immediate constant. */ -#define BITS_PER_HIGH 16 -#define BITS_PER_LO_SUM 16 - -/* Define register numbers. */ - -/* Extended-precision registers. */ - -#define R0_REGNO 0 -#define R1_REGNO 1 -#define R2_REGNO 2 -#define R3_REGNO 3 -#define R4_REGNO 4 -#define R5_REGNO 5 -#define R6_REGNO 6 -#define R7_REGNO 7 - -/* Auxiliary (address) registers. */ - -#define AR0_REGNO 8 -#define AR1_REGNO 9 -#define AR2_REGNO 10 -#define AR3_REGNO 11 -#define AR4_REGNO 12 -#define AR5_REGNO 13 -#define AR6_REGNO 14 -#define AR7_REGNO 15 - -/* Data page register. */ - -#define DP_REGNO 16 - -/* Index registers. */ - -#define IR0_REGNO 17 -#define IR1_REGNO 18 - -/* Block size register. */ - -#define BK_REGNO 19 - -/* Stack pointer. */ - -#define SP_REGNO 20 - -/* Status register. */ - -#define ST_REGNO 21 - -/* Misc. interrupt registers. */ - -#define DIE_REGNO 22 /* C4x only. */ -#define IE_REGNO 22 /* C3x only. */ -#define IIE_REGNO 23 /* C4x only. */ -#define IF_REGNO 23 /* C3x only. */ -#define IIF_REGNO 24 /* C4x only. */ -#define IOF_REGNO 24 /* C3x only. */ - -/* Repeat block registers. */ - -#define RS_REGNO 25 -#define RE_REGNO 26 -#define RC_REGNO 27 - -/* Additional extended-precision registers. */ - -#define R8_REGNO 28 /* C4x only. */ -#define R9_REGNO 29 /* C4x only. */ -#define R10_REGNO 30 /* C4x only. */ -#define R11_REGNO 31 /* C4x only. */ - -#define FIRST_PSEUDO_REGISTER 32 - -/* Extended precision registers (low set). */ - -#define IS_R0R1_REGNO(r) \ - ((unsigned int)((r) - R0_REGNO) <= (R1_REGNO - R0_REGNO)) -#define IS_R2R3_REGNO(r) \ - ((unsigned int)((r) - R2_REGNO) <= (R3_REGNO - R2_REGNO)) -#define IS_EXT_LOW_REGNO(r) \ - ((unsigned int)((r) - R0_REGNO) <= (R7_REGNO - R0_REGNO)) - -/* Extended precision registers (high set). */ - -#define IS_EXT_HIGH_REGNO(r) \ -(! TARGET_C3X \ - && ((unsigned int) ((r) - R8_REGNO) <= (R11_REGNO - R8_REGNO))) - -/* Address registers. */ - -#define IS_AUX_REGNO(r) \ - ((unsigned int)((r) - AR0_REGNO) <= (AR7_REGNO - AR0_REGNO)) -#define IS_ADDR_REGNO(r) IS_AUX_REGNO(r) -#define IS_DP_REGNO(r) ((r) == DP_REGNO) -#define IS_INDEX_REGNO(r) (((r) == IR0_REGNO) || ((r) == IR1_REGNO)) -#define IS_SP_REGNO(r) ((r) == SP_REGNO) -#define IS_BK_REGNO(r) (TARGET_BK && (r) == BK_REGNO) - -/* Misc registers. */ - -#define IS_ST_REGNO(r) ((r) == ST_REGNO) -#define IS_RC_REGNO(r) ((r) == RC_REGNO) -#define IS_REPEAT_REGNO(r) (((r) >= RS_REGNO) && ((r) <= RC_REGNO)) - -/* Composite register sets. */ - -#define IS_ADDR_OR_INDEX_REGNO(r) (IS_ADDR_REGNO(r) || IS_INDEX_REGNO(r)) -#define IS_EXT_REGNO(r) (IS_EXT_LOW_REGNO(r) || IS_EXT_HIGH_REGNO(r)) -#define IS_STD_REGNO(r) (IS_ADDR_OR_INDEX_REGNO(r) \ - || IS_REPEAT_REGNO(r) \ - || IS_SP_REGNO(r) \ - || IS_BK_REGNO(r)) -#define IS_INT_REGNO(r) (IS_EXT_REGNO(r) || IS_STD_REGNO(r)) -#define IS_GROUP1_REGNO(r) (IS_ADDR_OR_INDEX_REGNO(r) || IS_BK_REGNO(r)) -#define IS_INT_CALL_SAVED_REGNO(r) (((r) == R4_REGNO) || ((r) == R5_REGNO) \ - || ((r) == R8_REGNO)) -#define IS_FLOAT_CALL_SAVED_REGNO(r) (((r) == R6_REGNO) || ((r) == R7_REGNO)) - -#define IS_PSEUDO_REGNO(r) ((r) >= FIRST_PSEUDO_REGISTER) -#define IS_R0R1_OR_PSEUDO_REGNO(r) (IS_R0R1_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_R2R3_OR_PSEUDO_REGNO(r) (IS_R2R3_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_EXT_OR_PSEUDO_REGNO(r) (IS_EXT_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_STD_OR_PSEUDO_REGNO(r) (IS_STD_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_INT_OR_PSEUDO_REGNO(r) (IS_INT_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_ADDR_OR_PSEUDO_REGNO(r) (IS_ADDR_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_INDEX_OR_PSEUDO_REGNO(r) (IS_INDEX_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_EXT_LOW_OR_PSEUDO_REGNO(r) (IS_EXT_LOW_REGNO(r) \ - || IS_PSEUDO_REGNO(r)) -#define IS_DP_OR_PSEUDO_REGNO(r) (IS_DP_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_SP_OR_PSEUDO_REGNO(r) (IS_SP_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_ST_OR_PSEUDO_REGNO(r) (IS_ST_REGNO(r) || IS_PSEUDO_REGNO(r)) -#define IS_RC_OR_PSEUDO_REGNO(r) (IS_RC_REGNO(r) || IS_PSEUDO_REGNO(r)) - -#define IS_PSEUDO_REG(op) (IS_PSEUDO_REGNO(REGNO(op))) -#define IS_ADDR_REG(op) (IS_ADDR_REGNO(REGNO(op))) -#define IS_INDEX_REG(op) (IS_INDEX_REGNO(REGNO(op))) -#define IS_GROUP1_REG(r) (IS_GROUP1_REGNO(REGNO(op))) -#define IS_SP_REG(op) (IS_SP_REGNO(REGNO(op))) -#define IS_STD_REG(op) (IS_STD_REGNO(REGNO(op))) -#define IS_EXT_REG(op) (IS_EXT_REGNO(REGNO(op))) - -#define IS_R0R1_OR_PSEUDO_REG(op) (IS_R0R1_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_R2R3_OR_PSEUDO_REG(op) (IS_R2R3_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_EXT_OR_PSEUDO_REG(op) (IS_EXT_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_STD_OR_PSEUDO_REG(op) (IS_STD_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_EXT_LOW_OR_PSEUDO_REG(op) (IS_EXT_LOW_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_INT_OR_PSEUDO_REG(op) (IS_INT_OR_PSEUDO_REGNO(REGNO(op))) - -#define IS_ADDR_OR_PSEUDO_REG(op) (IS_ADDR_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_INDEX_OR_PSEUDO_REG(op) (IS_INDEX_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_DP_OR_PSEUDO_REG(op) (IS_DP_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_SP_OR_PSEUDO_REG(op) (IS_SP_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_ST_OR_PSEUDO_REG(op) (IS_ST_OR_PSEUDO_REGNO(REGNO(op))) -#define IS_RC_OR_PSEUDO_REG(op) (IS_RC_OR_PSEUDO_REGNO(REGNO(op))) - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. */ - -#define FIXED_REGISTERS \ -{ \ -/* R0 R1 R2 R3 R4 R5 R6 R7 AR0 AR1 AR2 AR3 AR4 AR5 AR6 AR7. */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ -/* DP IR0 IR1 BK SP ST DIE IIE IIF RS RE RC R8 R9 R10 R11. */ \ - 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 \ -} - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. - - Note that the extended precision registers are only saved in some - modes. The macro HARD_REGNO_CALL_CLOBBERED specifies which modes - get clobbered for a given regno. */ - -#define CALL_USED_REGISTERS \ -{ \ -/* R0 R1 R2 R3 R4 R5 R6 R7 AR0 AR1 AR2 AR3 AR4 AR5 AR6 AR7. */ \ - 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, \ -/* DP IR0 IR1 BK SP ST DIE IIE IIF RS RE RC R8 R9 R10 R11. */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1 \ -} - -/* Macro to conditionally modify fixed_regs/call_used_regs. */ - -#define CONDITIONAL_REGISTER_USAGE \ - { \ - if (! TARGET_BK) \ - { \ - fixed_regs[BK_REGNO] = 1; \ - call_used_regs[BK_REGNO] = 1; \ - c4x_regclass_map[BK_REGNO] = NO_REGS; \ - } \ - if (TARGET_C3X) \ - { \ - int i; \ - \ - reg_names[DIE_REGNO] = "ie"; /* Clobber die. */ \ - reg_names[IF_REGNO] = "if"; /* Clobber iie. */ \ - reg_names[IOF_REGNO] = "iof"; /* Clobber iif. */ \ - \ - for (i = R8_REGNO; i <= R11_REGNO; i++) \ - { \ - fixed_regs[i] = call_used_regs[i] = 1; \ - c4x_regclass_map[i] = NO_REGS; \ - } \ - } \ - if (TARGET_PRESERVE_FLOAT) \ - { \ - c4x_caller_save_map[R6_REGNO] = HFmode; \ - c4x_caller_save_map[R7_REGNO] = HFmode; \ - } \ - } - -/* Order of Allocation of Registers. */ - -/* List the order in which to allocate registers. Each register must be - listed once, even those in FIXED_REGISTERS. - - First allocate registers that don't need preservation across calls, - except index and address registers. Then allocate data registers - that require preservation across calls (even though this invokes an - extra overhead of having to save/restore these registers). Next - allocate the address and index registers, since using these - registers for arithmetic can cause pipeline stalls. Finally - allocated the fixed registers which won't be allocated anyhow. */ - -#define REG_ALLOC_ORDER \ -{R0_REGNO, R1_REGNO, R2_REGNO, R3_REGNO, \ - R9_REGNO, R10_REGNO, R11_REGNO, \ - RS_REGNO, RE_REGNO, RC_REGNO, BK_REGNO, \ - R4_REGNO, R5_REGNO, R6_REGNO, R7_REGNO, R8_REGNO, \ - AR0_REGNO, AR1_REGNO, AR2_REGNO, AR3_REGNO, \ - AR4_REGNO, AR5_REGNO, AR6_REGNO, AR7_REGNO, \ - IR0_REGNO, IR1_REGNO, \ - SP_REGNO, DP_REGNO, ST_REGNO, IE_REGNO, IF_REGNO, IOF_REGNO} - -/* A C expression that is nonzero if hard register number REGNO2 can be - considered for use as a rename register for REGNO1 */ - -#define HARD_REGNO_RENAME_OK(REGNO1,REGNO2) \ - c4x_hard_regno_rename_ok((REGNO1), (REGNO2)) - -/* Determine which register classes are very likely used by spill registers. - local-alloc.c won't allocate pseudos that have these classes as their - preferred class unless they are "preferred or nothing". */ - -#define CLASS_LIKELY_SPILLED_P(CLASS) ((CLASS) == INDEX_REGS) - -/* CCmode is wrongly defined in machmode.def. It should have a size - of UNITS_PER_WORD. HFmode is 40-bits and thus fits within a single - extended precision register. Similarly, HCmode fits within two - extended precision registers. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ -(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : \ - ((MODE) == HFmode) ? 1 : \ - ((MODE) == HCmode) ? 2 : \ - ((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) - - -/* A C expression that is nonzero if the hard register REGNO is preserved - across a call in mode MODE. This does not have to include the call used - registers. */ - -#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \ - ((IS_FLOAT_CALL_SAVED_REGNO (REGNO) && ! ((MODE) == QFmode)) \ - || (IS_INT_CALL_SAVED_REGNO (REGNO) \ - && ! ((MODE) == QImode || (MODE) == HImode || (MODE) == Pmode))) - -/* Specify the modes required to caller save a given hard regno. */ - -#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) (c4x_caller_save_map[REGNO]) - -#define HARD_REGNO_MODE_OK(REGNO, MODE) c4x_hard_regno_mode_ok(REGNO, MODE) - -/* A C expression that is nonzero if it is desirable to choose - register allocation so as to avoid move instructions between a - value of mode MODE1 and a value of mode MODE2. - - Value is 1 if it is a good idea to tie two pseudo registers - when one has mode MODE1 and one has mode MODE2. - If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, - for any hard reg, then this must be 0 for correct output. */ - -#define MODES_TIEABLE_P(MODE1, MODE2) 0 - - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -enum reg_class - { - NO_REGS, - R0R1_REGS, /* 't'. */ - R2R3_REGS, /* 'u'. */ - EXT_LOW_REGS, /* 'q'. */ - EXT_REGS, /* 'f'. */ - ADDR_REGS, /* 'a'. */ - INDEX_REGS, /* 'x'. */ - BK_REG, /* 'k'. */ - SP_REG, /* 'b'. */ - RC_REG, /* 'v'. */ - COUNTER_REGS, /* */ - INT_REGS, /* 'c'. */ - GENERAL_REGS, /* 'r'. */ - DP_REG, /* 'z'. */ - ST_REG, /* 'y'. */ - ALL_REGS, - LIM_REG_CLASSES - }; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -#define REG_CLASS_NAMES \ -{ \ - "NO_REGS", \ - "R0R1_REGS", \ - "R2R3_REGS", \ - "EXT_LOW_REGS", \ - "EXT_REGS", \ - "ADDR_REGS", \ - "INDEX_REGS", \ - "BK_REG", \ - "SP_REG", \ - "RC_REG", \ - "COUNTER_REGS", \ - "INT_REGS", \ - "GENERAL_REGS", \ - "DP_REG", \ - "ST_REG", \ - "ALL_REGS" \ -} - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. RC is not included in GENERAL_REGS - since the register allocator will often choose a general register - in preference to RC for the decrement_and_branch_on_count pattern. */ - -#define REG_CLASS_CONTENTS \ -{ \ - {0x00000000}, /* No registers. */ \ - {0x00000003}, /* 't' R0-R1 . */ \ - {0x0000000c}, /* 'u' R2-R3 . */ \ - {0x000000ff}, /* 'q' R0-R7 . */ \ - {0xf00000ff}, /* 'f' R0-R11 */ \ - {0x0000ff00}, /* 'a' AR0-AR7. */ \ - {0x00060000}, /* 'x' IR0-IR1. */ \ - {0x00080000}, /* 'k' BK. */ \ - {0x00100000}, /* 'b' SP. */ \ - {0x08000000}, /* 'v' RC. */ \ - {0x0800ff00}, /* RC,AR0-AR7. */ \ - {0x0e1eff00}, /* 'c' AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC. */ \ - {0xfe1effff}, /* 'r' R0-R11, AR0-AR7, IR0-IR1, BK, SP, RS, RE, RC. */\ - {0x00010000}, /* 'z' DP. */ \ - {0x00200000}, /* 'y' ST. */ \ - {0xffffffff}, /* All registers. */ \ -} - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) (c4x_regclass_map[REGNO]) - -/* When SMALL_REGISTER_CLASSES is defined, the lifetime of registers - explicitly used in the rtl is kept as short as possible. - - We only need to define SMALL_REGISTER_CLASSES if TARGET_PARALLEL_MPY - is defined since the MPY|ADD insns require the classes R0R1_REGS and - R2R3_REGS which are used by the function return registers (R0,R1) and - the register arguments (R2,R3), respectively. I'm reluctant to define - this macro since it stomps on many potential optimizations. Ideally - it should have a register class argument so that not all the register - classes gets penalized for the sake of a naughty few... For long - double arithmetic we need two additional registers that we can use as - spill registers. */ - -#define SMALL_REGISTER_CLASSES (TARGET_SMALL_REG_CLASS && TARGET_PARALLEL_MPY) - -#define BASE_REG_CLASS ADDR_REGS -#define INDEX_REG_CLASS INDEX_REGS - -/* - Register constraints for the C4x - - a - address reg (ar0-ar7) - b - stack reg (sp) - c - other gp int-only reg - d - data/int reg (equiv. to f) - f - data/float reg - h - data/long double reg (equiv. to f) - k - block count (bk) - q - r0-r7 - t - r0-r1 - u - r2-r3 - v - repeat count (rc) - x - index register (ir0-ir1) - y - status register (st) - z - dp reg (dp) - - Memory/constant constraints for the C4x - - G - short float 16-bit - I - signed 16-bit constant (sign extended) - J - signed 8-bit constant (sign extended) (C4x only) - K - signed 5-bit constant (sign extended) (C4x only for stik) - L - unsigned 16-bit constant - M - unsigned 8-bit constant (C4x only) - N - ones complement of unsigned 16-bit constant - Q - indirect arx + 9-bit signed displacement - (a *-arx(n) or *+arx(n) is used to account for the sign bit) - R - indirect arx + 5-bit unsigned displacement (C4x only) - S - indirect arx + 0, 1, or irn displacement - T - direct symbol ref - > - indirect with autoincrement - < - indirect with autodecrement - } - indirect with post-modify - { - indirect with pre-modify - */ - -#define REG_CLASS_FROM_LETTER(CC) \ - ( ((CC) == 'a') ? ADDR_REGS \ - : ((CC) == 'b') ? SP_REG \ - : ((CC) == 'c') ? INT_REGS \ - : ((CC) == 'd') ? EXT_REGS \ - : ((CC) == 'f') ? EXT_REGS \ - : ((CC) == 'h') ? EXT_REGS \ - : ((CC) == 'k') ? BK_REG \ - : ((CC) == 'q') ? EXT_LOW_REGS \ - : ((CC) == 't') ? R0R1_REGS \ - : ((CC) == 'u') ? R2R3_REGS \ - : ((CC) == 'v') ? RC_REG \ - : ((CC) == 'x') ? INDEX_REGS \ - : ((CC) == 'y') ? ST_REG \ - : ((CC) == 'z') ? DP_REG \ - : NO_REGS ) - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_BASE_P(REGNO) \ - (IS_ADDR_REGNO(REGNO) || IS_ADDR_REGNO((unsigned)reg_renumber[REGNO])) - -#define REGNO_OK_FOR_INDEX_P(REGNO) \ - (IS_INDEX_REGNO(REGNO) || IS_INDEX_REGNO((unsigned)reg_renumber[REGNO])) - -/* If we have to generate framepointer + constant prefer an ADDR_REGS - register. This avoids using EXT_REGS in addqi3_noclobber_reload. */ - -#define PREFERRED_RELOAD_CLASS(X, CLASS) \ - (GET_CODE (X) == PLUS \ - && GET_MODE (X) == Pmode \ - && GET_CODE (XEXP ((X), 0)) == REG \ - && GET_MODE (XEXP ((X), 0)) == Pmode \ - && REGNO (XEXP ((X), 0)) == FRAME_POINTER_REGNUM \ - && GET_CODE (XEXP ((X), 1)) == CONST_INT \ - ? ADDR_REGS : (CLASS)) - -#define LIMIT_RELOAD_CLASS(X, CLASS) (CLASS) - -#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) 0 - -#define CLASS_MAX_NREGS(CLASS, MODE) \ -(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : ((MODE) == HFmode) ? 1 : \ -((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) - -#define IS_INT5_CONST(VAL) (((VAL) <= 15) && ((VAL) >= -16)) /* 'K'. */ - -#define IS_UINT5_CONST(VAL) (((VAL) <= 31) && ((VAL) >= 0)) /* 'R'. */ - -#define IS_INT8_CONST(VAL) (((VAL) <= 127) && ((VAL) >= -128)) /* 'J'. */ - -#define IS_UINT8_CONST(VAL) (((VAL) <= 255) && ((VAL) >= 0)) /* 'M'. */ - -#define IS_INT16_CONST(VAL) (((VAL) <= 32767) && ((VAL) >= -32768)) /* 'I'. */ - -#define IS_UINT16_CONST(VAL) (((VAL) <= 65535) && ((VAL) >= 0)) /* 'L'. */ - -#define IS_NOT_UINT16_CONST(VAL) IS_UINT16_CONST(~(VAL)) /* 'N'. */ - -#define IS_HIGH_CONST(VAL) \ -(! TARGET_C3X && (((VAL) & 0xffff) == 0)) /* 'O'. */ - - -#define IS_DISP1_CONST(VAL) (((VAL) <= 1) && ((VAL) >= -1)) /* 'S'. */ - -#define IS_DISP8_CONST(VAL) (((VAL) <= 255) && ((VAL) >= -255)) /* 'Q'. */ - -#define IS_DISP1_OFF_CONST(VAL) (IS_DISP1_CONST (VAL) \ - && IS_DISP1_CONST (VAL + 1)) - -#define IS_DISP8_OFF_CONST(VAL) (IS_DISP8_CONST (VAL) \ - && IS_DISP8_CONST (VAL + 1)) - -#define CONST_OK_FOR_LETTER_P(VAL, C) \ - ( ((C) == 'I') ? (IS_INT16_CONST (VAL)) \ - : ((C) == 'J') ? (! TARGET_C3X && IS_INT8_CONST (VAL)) \ - : ((C) == 'K') ? (! TARGET_C3X && IS_INT5_CONST (VAL)) \ - : ((C) == 'L') ? (IS_UINT16_CONST (VAL)) \ - : ((C) == 'M') ? (! TARGET_C3X && IS_UINT8_CONST (VAL)) \ - : ((C) == 'N') ? (IS_NOT_UINT16_CONST (VAL)) \ - : ((C) == 'O') ? (IS_HIGH_CONST (VAL)) \ - : 0 ) - -#define CONST_DOUBLE_OK_FOR_LETTER_P(OP, C) \ - ( ((C) == 'G') ? (fp_zero_operand (OP, QFmode)) \ - : ((C) == 'H') ? (c4x_H_constant (OP)) \ - : 0 ) - -#define EXTRA_CONSTRAINT(OP, C) \ - ( ((C) == 'Q') ? (c4x_Q_constraint (OP)) \ - : ((C) == 'R') ? (c4x_R_constraint (OP)) \ - : ((C) == 'S') ? (c4x_S_constraint (OP)) \ - : ((C) == 'T') ? (c4x_T_constraint (OP)) \ - : ((C) == 'U') ? (c4x_U_constraint (OP)) \ - : 0 ) - -#define SMALL_CONST(VAL, insn) \ - ( ((insn == NULL_RTX) || (get_attr_data (insn) == DATA_INT16)) \ - ? IS_INT16_CONST (VAL) \ - : ( (get_attr_data (insn) == DATA_NOT_UINT16) \ - ? IS_NOT_UINT16_CONST (VAL) \ - : ( (get_attr_data (insn) == DATA_HIGH_16) \ - ? IS_HIGH_CONST (VAL) \ - : IS_UINT16_CONST (VAL) \ - ) \ - ) \ - ) - -/* - I. Routine calling with arguments in registers - ---------------------------------------------- - - The TI C3x compiler has a rather unusual register passing algorithm. - Data is passed in the following registers (in order): - - AR2, R2, R3, RC, RS, RE - - However, the first and second floating point values are always in R2 - and R3 (and all other floats are on the stack). Structs are always - passed on the stack. If the last argument is an ellipsis, the - previous argument is passed on the stack so that its address can be - taken for the stdargs macros. - - Because of this, we have to pre-scan the list of arguments to figure - out what goes where in the list. - - II. Routine calling with arguments on stack - ------------------------------------------- - - Let the subroutine declared as "foo(arg0, arg1, arg2);" have local - variables loc0, loc1, and loc2. After the function prologue has - been executed, the stack frame will look like: - - [stack grows towards increasing addresses] - I-------------I - 5 I saved reg1 I <= SP points here - I-------------I - 4 I saved reg0 I - I-------------I - 3 I loc2 I - I-------------I - 2 I loc1 I - I-------------I - 1 I loc0 I - I-------------I - 0 I old FP I <= FP (AR3) points here - I-------------I - -1 I return PC I - I-------------I - -2 I arg0 I - I-------------I - -3 I arg1 I - I-------------I - -4 I arg2 I - I-------------I - - All local variables (locn) are accessible by means of +FP(n+1) - addressing, where n is the local variable number. - - All stack arguments (argn) are accessible by means of -FP(n-2). - - The stack pointer (SP) points to the last register saved in the - prologue (regn). - - Note that a push instruction performs a preincrement of the stack - pointer. (STACK_PUSH_CODE == PRE_INC) - - III. Registers used in function calling convention - -------------------------------------------------- - - Preserved across calls: R4...R5 (only by PUSH, i.e. lower 32 bits) - R6...R7 (only by PUSHF, i.e. upper 32 bits) - AR3...AR7 - - (Because of this model, we only assign FP values in R6, R7 and - only assign integer values in R4, R5.) - - These registers are saved at each function entry and restored at - the exit. Also it is expected any of these not affected by any - call to user-defined (not service) functions. - - Not preserved across calls: R0...R3 - R4...R5 (upper 8 bits) - R6...R7 (lower 8 bits) - AR0...AR2, IR0, IR1, BK, ST, RS, RE, RC - - These registers are used arbitrary in a function without being preserved. - It is also expected that any of these can be clobbered by any call. - - Not used by GCC (except for in user "asm" statements): - IE (DIE), IF (IIE), IOF (IIF) - - These registers are never used by GCC for any data, but can be used - with "asm" statements. */ - -#define C4X_ARG0 -2 -#define C4X_LOC0 1 - -/* Basic Stack Layout. */ - -/* The stack grows upward, stack frame grows upward, and args grow - downward. */ - -#define STARTING_FRAME_OFFSET C4X_LOC0 -#define FIRST_PARM_OFFSET(FNDECL) (C4X_ARG0 + 1) -#define ARGS_GROW_DOWNWARD -#define STACK_POINTER_OFFSET 1 - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ - -/* #define STACK_GROWS_DOWNWARD. */ -/* Like the dsp16xx, i370, i960, and we32k ports. */ - -/* Define this to nonzero if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ - -#define FRAME_GROWS_DOWNWARD 0 - - -/* Registers That Address the Stack Frame. */ - -#define STACK_POINTER_REGNUM SP_REGNO /* SP. */ -#define FRAME_POINTER_REGNUM AR3_REGNO /* AR3. */ -#define ARG_POINTER_REGNUM AR3_REGNO /* AR3. */ -#define STATIC_CHAIN_REGNUM AR0_REGNO /* AR0. */ - -/* Eliminating Frame Pointer and Arg Pointer. */ - -#define FRAME_POINTER_REQUIRED 0 - -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ -{ \ - int regno; \ - int offset = 0; \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ - if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) \ - offset += TARGET_PRESERVE_FLOAT \ - && IS_FLOAT_CALL_SAVED_REGNO (regno) ? 2 : 1; \ - (DEPTH) = -(offset + get_frame_size ()); \ -} - -/* This is a hack... We need to specify a register. */ -#define ELIMINABLE_REGS \ - {{ FRAME_POINTER_REGNUM, FRAME_POINTER_REGNUM }} - -#define CAN_ELIMINATE(FROM, TO) \ - (! (((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - || ((FROM) == FRAME_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM))) - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ \ - int regno; \ - int offset = 0; \ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ - if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) \ - offset += TARGET_PRESERVE_FLOAT \ - && IS_FLOAT_CALL_SAVED_REGNO (regno) ? 2 : 1; \ - (OFFSET) = -(offset + get_frame_size ()); \ -} - - -/* Passing Function Arguments on the Stack. */ - -#define PUSH_ARGS 1 -#define PUSH_ROUNDING(BYTES) (BYTES) -#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 - -/* The following structure is used by calls.c, function.c, c4x.c. */ - -typedef struct c4x_args -{ - int floats; - int ints; - int maxfloats; - int maxints; - int init; - int var; - int prototype; - int args; -} -CUMULATIVE_ARGS; - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ - (c4x_init_cumulative_args (&CUM, FNTYPE, LIBNAME)) - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - (c4x_function_arg_advance (&CUM, MODE, TYPE, NAMED)) - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - (c4x_function_arg(&CUM, MODE, TYPE, NAMED)) - -/* Define the profitability of saving registers around calls. - We disable caller save to avoid a bug in flow.c (this also affects - other targets such as m68k). Since we must use stf/sti, - the profitability is marginal anyway. */ - -#define CALLER_SAVE_PROFITABLE(REFS,CALLS) 0 - -/* 1 if N is a possible register number for function argument passing. */ - -#define FUNCTION_ARG_REGNO_P(REGNO) \ - ( ( ((REGNO) == AR2_REGNO) /* AR2. */ \ - || ((REGNO) == R2_REGNO) /* R2. */ \ - || ((REGNO) == R3_REGNO) /* R3. */ \ - || ((REGNO) == RC_REGNO) /* RC. */ \ - || ((REGNO) == RS_REGNO) /* RS. */ \ - || ((REGNO) == RE_REGNO)) /* RE. */ \ - ? 1 \ - : 0) - -/* How Scalar Function Values Are Returned. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx_REG (TYPE_MODE(VALTYPE), R0_REGNO) /* Return in R0. */ - -#define LIBCALL_VALUE(MODE) \ - gen_rtx_REG (MODE, R0_REGNO) /* Return in R0. */ - -#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == R0_REGNO) - -/* How Large Values Are Returned. */ - -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Generating Code for Profiling. */ - -/* Note that the generated assembly uses the ^ operator to load the 16 - MSBs of the address. This is not supported by the TI assembler. - The FUNCTION profiler needs a function mcount which gets passed - a pointer to the LABELNO. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - if (! TARGET_C3X) \ - { \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tldhi\t^LP%d,ar2\n", (LABELNO)); \ - fprintf (FILE, "\tor\t#LP%d,ar2\n", (LABELNO)); \ - fprintf (FILE, "\tcall\tmcount\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tpush\tar2\n"); \ - fprintf (FILE, "\tldiu\t^LP%d,ar2\n", (LABELNO)); \ - fprintf (FILE, "\tlsh\t16,ar2\n"); \ - fprintf (FILE, "\tor\t#LP%d,ar2\n", (LABELNO)); \ - fprintf (FILE, "\tcall\tmcount\n"); \ - fprintf (FILE, "\tpop\tar2\n"); \ - } - -/* CC_NOOVmode should be used when the first operand is a PLUS, MINUS, NEG - or MULT. - CCmode should be used when no special processing is needed. */ -#define SELECT_CC_MODE(OP,X,Y) \ - ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ - || GET_CODE (X) == NEG || GET_CODE (X) == MULT \ - || GET_MODE (X) == ABS \ - || GET_CODE (Y) == PLUS || GET_CODE (Y) == MINUS \ - || GET_CODE (Y) == NEG || GET_CODE (Y) == MULT \ - || GET_MODE (Y) == ABS) \ - ? CC_NOOVmode : CCmode) - -/* Addressing Modes. */ - -#define HAVE_POST_INCREMENT 1 -#define HAVE_PRE_INCREMENT 1 -#define HAVE_POST_DECREMENT 1 -#define HAVE_PRE_DECREMENT 1 -#define HAVE_PRE_MODIFY_REG 1 -#define HAVE_POST_MODIFY_REG 1 -#define HAVE_PRE_MODIFY_DISP 1 -#define HAVE_POST_MODIFY_DISP 1 - -/* The number of insns that can be packed into a single opcode. */ -#define PACK_INSNS 2 - -/* Recognize any constant value that is a valid address. - We could allow arbitrary constant addresses in the large memory - model but for the small memory model we can only accept addresses - within the data page. I suppose we could also allow - CONST PLUS SYMBOL_REF. */ -#define CONSTANT_ADDRESS_P(X) (GET_CODE (X) == SYMBOL_REF) - -/* Maximum number of registers that can appear in a valid memory - address. */ -#define MAX_REGS_PER_ADDRESS 2 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard or pseudo reg that can be used as a base. */ - -#define REG_OK_FOR_BASE_P(X) IS_ADDR_OR_PSEUDO_REG(X) - -/* Nonzero if X is a hard or pseudo reg that can be used as an index. */ - -#define REG_OK_FOR_INDEX_P(X) IS_INDEX_OR_PSEUDO_REG(X) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - if (c4x_legitimate_address_p (MODE, X, 0)) \ - goto ADDR; \ -} - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ - -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) - -/* Nonzero if X is a hard reg that can be used as a base reg. */ - -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - if (c4x_legitimate_address_p (MODE, X, 1)) \ - goto ADDR; \ -} - -#endif - -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -{ \ - rtx new; \ - \ - new = c4x_legitimize_address (X, MODE); \ - if (new != NULL_RTX) \ - { \ - (X) = new; \ - goto WIN; \ - } \ -} - -#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \ -{ \ - if (MODE != HImode \ - && MODE != HFmode \ - && GET_MODE (X) != HImode \ - && GET_MODE (X) != HFmode \ - && (GET_CODE (X) == CONST \ - || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == LABEL_REF)) \ - { \ - if (! TARGET_SMALL) \ - { \ - int i; \ - (X) = gen_rtx_LO_SUM (GET_MODE (X), \ - gen_rtx_HIGH (GET_MODE (X), X), X); \ - i = push_reload (XEXP (X, 0), NULL_RTX, \ - &XEXP (X, 0), NULL, \ - DP_REG, GET_MODE (X), VOIDmode, 0, 0, \ - OPNUM, TYPE); \ - /* The only valid reg is DP. This is a fixed reg and will \ - normally not be used so force it. */ \ - rld[i].reg_rtx = gen_rtx_REG (Pmode, DP_REGNO); \ - rld[i].nocombine = 1; \ - } \ - else \ - { \ - /* make_memloc in reload will substitute invalid memory \ - references. We need to fix them up. */ \ - (X) = gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, DP_REGNO), (X)); \ - } \ - goto WIN; \ - } \ - else if (MODE != HImode \ - && MODE != HFmode \ - && GET_MODE (X) != HImode \ - && GET_MODE (X) != HFmode \ - && GET_CODE (X) == LO_SUM \ - && GET_CODE (XEXP (X,0)) == HIGH \ - && (GET_CODE (XEXP (XEXP (X,0),0)) == CONST \ - || GET_CODE (XEXP (XEXP (X,0),0)) == SYMBOL_REF \ - || GET_CODE (XEXP (XEXP (X,0),0)) == LABEL_REF)) \ - { \ - if (! TARGET_SMALL) \ - { \ - int i = push_reload (XEXP (X, 0), NULL_RTX, \ - &XEXP (X, 0), NULL, \ - DP_REG, GET_MODE (X), VOIDmode, 0, 0, \ - OPNUM, TYPE); \ - /* The only valid reg is DP. This is a fixed reg and will \ - normally not be used so force it. */ \ - rld[i].reg_rtx = gen_rtx_REG (Pmode, DP_REGNO); \ - rld[i].nocombine = 1; \ - } \ - goto WIN; \ - } \ -} - -/* No mode-dependent addresses on the C4x are autoincrements. */ -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ - if (GET_CODE (ADDR) == POST_MODIFY \ - || GET_CODE (ADDR) == PRE_MODIFY) \ - goto LABEL - - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. - - The C4x can only load 16-bit immediate values, so we only allow a - restricted subset of CONST_INT and CONST_DOUBLE. Disallow - LABEL_REF and SYMBOL_REF (except on the C40 with the big memory - model) so that the symbols will be forced into the constant pool. - On second thoughts, let's do this with the move expanders since - the alias analysis has trouble if we force constant addresses - into memory. -*/ - -#define LEGITIMATE_CONSTANT_P(X) \ - ((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X)) \ - || (GET_CODE (X) == CONST_INT) \ - || (GET_CODE (X) == SYMBOL_REF) \ - || (GET_CODE (X) == LABEL_REF) \ - || (GET_CODE (X) == CONST) \ - || (GET_CODE (X) == HIGH && ! TARGET_C3X) \ - || (GET_CODE (X) == LO_SUM && ! TARGET_C3X)) - -#define LEGITIMATE_DISPLACEMENT_P(X) IS_DISP8_CONST (INTVAL (X)) - -/* Describing Relative Cost of Operations. */ - -#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \ -if (REG_P (OP1) && ! REG_P (OP0)) \ -{ \ - rtx tmp = OP0; OP0 = OP1 ; OP1 = tmp; \ - CODE = swap_condition (CODE); \ -} - -#define EXT_CLASS_P(CLASS) (reg_class_subset_p (CLASS, EXT_REGS)) -#define ADDR_CLASS_P(CLASS) (reg_class_subset_p (CLASS, ADDR_REGS)) -#define INDEX_CLASS_P(CLASS) (reg_class_subset_p (CLASS, INDEX_REGS)) -#define EXPENSIVE_CLASS_P(CLASS) (ADDR_CLASS_P(CLASS) \ - || INDEX_CLASS_P(CLASS) || (CLASS) == SP_REG) - -/* Compute extra cost of moving data between one register class - and another. */ - -#define REGISTER_MOVE_COST(MODE, FROM, TO) 2 - -/* Memory move cost is same as fast register move. Maybe this should - be bumped up?. */ - -#define MEMORY_MOVE_COST(M,C,I) 4 - -/* Branches are kind of expensive (even with delayed branching) so - make their cost higher. */ - -#define BRANCH_COST 8 - -#define WORD_REGISTER_OPERATIONS - -/* Dividing the Output into Sections. */ - -#define TEXT_SECTION_ASM_OP "\t.text" - -#define DATA_SECTION_ASM_OP "\t.data" - -#define READONLY_DATA_SECTION_ASM_OP "\t.sect\t\".const\"" - -/* Do not use .init section so __main will be called on startup. This will - call __do_global_ctors and prepare for __do_global_dtors on exit. */ - -#if 0 -#define INIT_SECTION_ASM_OP "\t.sect\t\".init\"" -#endif - -#define FINI_SECTION_ASM_OP "\t.sect\t\".fini\"" - -/* Switch into a generic section. */ -#define TARGET_ASM_NAMED_SECTION c4x_asm_named_section - - -/* Overall Framework of an Assembler File. */ - -#define ASM_COMMENT_START ";" - -#define ASM_APP_ON "" -#define ASM_APP_OFF "" - -#define ASM_OUTPUT_ASCII(FILE, PTR, LEN) c4x_output_ascii (FILE, PTR, LEN) - -/* Output and Generation of Labels. */ - -#define NO_DOT_IN_LABEL /* Only required for TI format. */ - -/* Globalizing directive for a label. */ -#define GLOBAL_ASM_OP "\t.global\t" - -#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ -c4x_external_ref (NAME) - -/* The prefix to add to user-visible assembler symbols. */ - -#define USER_LABEL_PREFIX "_" - -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(BUFFER, PREFIX, NUM) \ - sprintf (BUFFER, "*%s%lu", PREFIX, (unsigned long)(NUM)) - -/* A C statement to output to the stdio stream STREAM assembler code which - defines (equates) the symbol NAME to have the value VALUE. */ - -#define ASM_OUTPUT_DEF(STREAM, NAME, VALUE) \ -do { \ - assemble_name (STREAM, NAME); \ - fprintf (STREAM, "\t.set\t%s\n", VALUE); \ -} while (0) - -/* Output of Dispatch Tables. */ - -/* This is how to output an element of a case-vector that is absolute. */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.long\tL%d\n", VALUE); - -/* This is how to output an element of a case-vector that is relative. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\t.long\tL%d-L%d\n", VALUE, REL); - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "long int" - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 32 - -#define INT_TYPE_SIZE 32 -#define LONG_LONG_TYPE_SIZE 64 -#define FLOAT_TYPE_SIZE 32 -#define DOUBLE_TYPE_SIZE 32 -#define LONG_DOUBLE_TYPE_SIZE 64 /* Actually only 40. */ - -/* Output #ident as a .ident. */ - -#define ASM_OUTPUT_IDENT(FILE, NAME) \ - fprintf (FILE, "\t.ident \"%s\"\n", NAME); - -/* Output of Uninitialized Variables. */ - -/* This says how to output an assembler line to define a local - uninitialized variable. */ - -#undef ASM_OUTPUT_LOCAL -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -( fputs ("\t.bss\t", FILE), \ - assemble_name (FILE, (NAME)), \ - fprintf (FILE, ",%u\n", (int)(ROUNDED))) - -/* This says how to output an assembler line to define a global - uninitialized variable. */ - -#undef ASM_OUTPUT_COMMON -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs ("\t.globl\t", FILE), \ - assemble_name (FILE, (NAME)), \ - fputs ("\n\t.bss\t", FILE), \ - assemble_name (FILE, (NAME)), \ - fprintf (FILE, ",%u\n", (int)(ROUNDED))) - -#undef ASM_OUTPUT_BSS -#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ -( fputs ("\t.globl\t", FILE), \ - assemble_name (FILE, (NAME)), \ - fputs ("\n\t.bss\t", FILE), \ - assemble_name (FILE, (NAME)), \ - fprintf (FILE, ",%u\n", (int)(SIZE))) - -/* Macros Controlling Initialization Routines. */ - -#define OBJECT_FORMAT_COFF -#define REAL_NM_FILE_NAME "c4x-nm" - -/* Output of Assembler Instructions. */ - -/* Register names when used for integer modes. */ - -#define REGISTER_NAMES \ -{ \ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "ar0", "ar1", "ar2", "ar3", "ar4", "ar5", "ar6", "ar7", \ - "dp", "ir0", "ir1", "bk", "sp", "st", "die", "iie", \ - "iif", "rs", "re", "rc", "r8", "r9", "r10", "r11" \ -} - -/* Alternate register names when used for floating point modes. */ - -#define FLOAT_REGISTER_NAMES \ -{ \ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ - "ar0", "ar1", "ar2", "ar3", "ar4", "ar5", "ar6", "ar7", \ - "dp", "ir0", "ir1", "bk", "sp", "st", "die", "iie", \ - "iif", "rs", "re", "rc", "f8", "f9", "f10", "f11" \ -} - -#define PRINT_OPERAND(FILE, X, CODE) c4x_print_operand(FILE, X, CODE) - -/* Determine which codes are valid without a following integer. These must - not be alphabetic. */ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '#') - -#define PRINT_OPERAND_ADDRESS(FILE, X) c4x_print_operand_address(FILE, X) - -/* C4x specific pragmas. */ -#define REGISTER_TARGET_PRAGMAS() do { \ - c_register_pragma (0, "CODE_SECTION", c4x_pr_CODE_SECTION); \ - c_register_pragma (0, "DATA_SECTION", c4x_pr_DATA_SECTION); \ - c_register_pragma (0, "FUNC_CANNOT_INLINE", c4x_pr_ignored); \ - c_register_pragma (0, "FUNC_EXT_CALLED", c4x_pr_ignored); \ - c_register_pragma (0, "FUNC_IS_PURE", c4x_pr_FUNC_IS_PURE); \ - c_register_pragma (0, "FUNC_IS_SYSTEM", c4x_pr_ignored); \ - c_register_pragma (0, "FUNC_NEVER_RETURNS", c4x_pr_FUNC_NEVER_RETURNS); \ - c_register_pragma (0, "FUNC_NO_GLOBAL_ASG", c4x_pr_ignored); \ - c_register_pragma (0, "FUNC_NO_IND_ASG", c4x_pr_ignored); \ - c_register_pragma (0, "INTERRUPT", c4x_pr_INTERRUPT); \ -} while (0) - -/* Assembler Commands for Alignment. */ - -#define ASM_OUTPUT_SKIP(FILE, SIZE) \ -{ int c = SIZE; \ - for (; c > 0; --c) \ - fprintf (FILE,"\t.word\t0\n"); \ -} - -#define ASM_NO_SKIP_IN_TEXT 1 - -/* I'm not sure about this one. FIXME. */ - -#define ASM_OUTPUT_ALIGN(FILE, LOG) \ - if ((LOG) != 0) \ - fprintf (FILE, "\t.align\t%d\n", (1 << (LOG))) - - -/* Macros for SDB and DWARF Output (use .sdef instead of .def - to avoid conflict with TI's use of .def). */ - -#define SDB_DELIM "\n" -#define SDB_DEBUGGING_INFO 1 - -/* Don't use octal since this can confuse gas for the c4x. */ -#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0x%x%s", a, SDB_DELIM) - -#define PUT_SDB_DEF(A) \ -do { fprintf (asm_out_file, "\t.sdef\t"); \ - ASM_OUTPUT_LABELREF (asm_out_file, A); \ - fprintf (asm_out_file, SDB_DELIM); } while (0) - -#define PUT_SDB_PLAIN_DEF(A) \ - fprintf (asm_out_file,"\t.sdef\t.%s%s", A, SDB_DELIM) - -#define PUT_SDB_BLOCK_START(LINE) \ - fprintf (asm_out_file, \ - "\t.sdef\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) - -#define PUT_SDB_BLOCK_END(LINE) \ - fprintf (asm_out_file, \ - "\t.sdef\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) - -#define PUT_SDB_FUNCTION_START(LINE) \ - fprintf (asm_out_file, \ - "\t.sdef\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) - -/* Note we output relative line numbers for .ef which gas converts - to absolute line numbers. The TI compiler outputs absolute line numbers - in the .sym directive which gas does not support. */ -#define PUT_SDB_FUNCTION_END(LINE) \ - fprintf (asm_out_file, \ - "\t.sdef\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM, \ - (LINE), SDB_DELIM) - -#define PUT_SDB_EPILOGUE_END(NAME) \ -do { fprintf (asm_out_file, "\t.sdef\t"); \ - ASM_OUTPUT_LABELREF (asm_out_file, NAME); \ - fprintf (asm_out_file, \ - "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n", \ - SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0) - -/* Define this as 1 if `char' should by default be signed; else as 0. */ - -#define DEFAULT_SIGNED_CHAR 1 - -/* A function address in a call instruction is a byte address (for - indexing purposes) so give the MEM rtx a byte's mode. */ - -#define FUNCTION_MODE QImode - -#define SLOW_BYTE_ACCESS 0 - -/* Specify the machine mode that pointers have. After generation of - RTL, the compiler makes no further distinction between pointers and - any other objects of this machine mode. */ - -#define Pmode QImode - -/* On the C4x we can write the following code. We have to clear the cache - every time we execute it because the data in the stack could change. - - laj $+4 - addi3 4,r11,ar0 - lda *ar0,ar1 - lda *+ar0(1),ar0 - bud ar1 - nop - nop - or 1000h,st - .word FNADDR - .word CXT - - On the c3x this is a bit more difficult. We have to write self - modifying code here. So we have to clear the cache every time - we execute it because the data in the stack could change. - - ldiu TOP_OF_FUNCTION,ar1 - lsh 16,ar1 - or BOTTOM_OF_FUNCTION,ar1 - ldiu TOP_OF_STATIC,ar0 - bud ar1 - lsh 16,ar0 - or BOTTOM_OF_STATIC,ar0 - or 1000h,st - - */ - -#define TRAMPOLINE_SIZE (TARGET_C3X ? 8 : 10) - -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - if (TARGET_C3X) \ - { \ - fprintf (FILE, "\tldiu\t0,ar1\n"); \ - fprintf (FILE, "\tlsh\t16,ar1\n"); \ - fprintf (FILE, "\tor\t0,ar1\n"); \ - fprintf (FILE, "\tldiu\t0,ar0\n"); \ - fprintf (FILE, "\tbud\tar1\n"); \ - fprintf (FILE, "\tlsh\t16,ar0\n"); \ - fprintf (FILE, "\tor\t0,ar0\n"); \ - fprintf (FILE, "\tor\t1000h,st\n"); \ - } \ - else \ - { \ - fprintf (FILE, "\tlaj\t$+4\n"); \ - fprintf (FILE, "\taddi3\t4,r11,ar0\n"); \ - fprintf (FILE, "\tlda\t*ar0,ar1\n"); \ - fprintf (FILE, "\tlda\t*+ar0(1),ar0\n"); \ - fprintf (FILE, "\tbud\tar1\n"); \ - fprintf (FILE, "\tnop\n"); \ - fprintf (FILE, "\tnop\n"); \ - fprintf (FILE, "\tor\t1000h,st\n"); \ - fprintf (FILE, "\t.word\t0\n"); \ - fprintf (FILE, "\t.word\t0\n"); \ - } \ -} - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - if (TARGET_C3X) \ - { \ - rtx tmp1, tmp2; \ - tmp1 = expand_shift (RSHIFT_EXPR, QImode, FNADDR, \ - size_int (16), 0, 1); \ - tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ - GEN_INT (0x5069), size_int (16), 0, 1); \ - emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ - emit_move_insn (gen_rtx_MEM (QImode, \ - plus_constant (TRAMP, 0)), tmp1); \ - tmp1 = expand_and (QImode, FNADDR, GEN_INT (0xffff), 0); \ - tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ - GEN_INT (0x1069), size_int (16), 0, 1); \ - emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ - emit_move_insn (gen_rtx_MEM (QImode, \ - plus_constant (TRAMP, 2)), tmp1); \ - tmp1 = expand_shift (RSHIFT_EXPR, QImode, CXT, \ - size_int (16), 0, 1); \ - tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ - GEN_INT (0x5068), size_int (16), 0, 1); \ - emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ - emit_move_insn (gen_rtx_MEM (QImode, \ - plus_constant (TRAMP, 3)), tmp1); \ - tmp1 = expand_and (QImode, CXT, GEN_INT (0xffff), 0); \ - tmp2 = expand_shift (LSHIFT_EXPR, QImode, \ - GEN_INT (0x1068), size_int (16), 0, 1); \ - emit_insn (gen_iorqi3 (tmp1, tmp1, tmp2)); \ - emit_move_insn (gen_rtx_MEM (QImode, \ - plus_constant (TRAMP, 6)), tmp1); \ - } \ - else \ - { \ - emit_move_insn (gen_rtx_MEM (QImode, \ - plus_constant (TRAMP, 8)), FNADDR); \ - emit_move_insn (gen_rtx_MEM (QImode, \ - plus_constant (TRAMP, 9)), CXT); \ - } \ -} - -/* Specify the machine mode that this machine uses for the index in - the tablejump instruction. */ - -#define CASE_VECTOR_MODE Pmode - -/* Max number of (32-bit) bytes we can move from memory to memory - in one reasonably fast instruction. */ - -#define MOVE_MAX 1 - -/* MOVE_RATIO is the number of move instructions that is better than a - block move. */ - -#define MOVE_RATIO 3 - -#define BSS_SECTION_ASM_OP "\t.bss" - -#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \ - fprintf (FILE, "\tpush\t%s\n", reg_names[REGNO]) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE, REGNO) \ - fprintf (FILE, "\tpop\t%s\n", reg_names[REGNO]) - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ - -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -#define DBR_OUTPUT_SEQEND(FILE) \ -if (final_sequence != NULL_RTX) \ -{ \ - int count; \ - rtx insn = XVECEXP (final_sequence, 0, 0); \ - int laj = GET_CODE (insn) == CALL_INSN \ - || (GET_CODE (insn) == INSN \ - && GET_CODE (PATTERN (insn)) == TRAP_IF);\ - \ - count = dbr_sequence_length(); \ - while (count < (laj ? 2 : 3)) \ - { \ - fputs("\tnop\n", FILE); \ - count++; \ - } \ - if (laj) \ - fputs("\tpush\tr11\n", FILE); \ -} - -#define NO_FUNCTION_CSE - -/* We don't want a leading tab. */ - -#define ASM_OUTPUT_ASM(FILE, STRING) fprintf (FILE, "%s\n", STRING) - -/* Define the intrinsic functions for the c3x/c4x. */ - -enum c4x_builtins -{ - /* intrinsic name */ - C4X_BUILTIN_FIX, /* fast_ftoi */ - C4X_BUILTIN_FIX_ANSI, /* ansi_ftoi */ - C4X_BUILTIN_MPYI, /* fast_imult (only C3x) */ - C4X_BUILTIN_TOIEEE, /* toieee (only C4x) */ - C4X_BUILTIN_FRIEEE, /* frieee (only C4x) */ - C4X_BUILTIN_RCPF /* fast_invf (only C4x) */ -}; - - -/* Hack to overcome use of libgcc2.c using auto-host.h to determine - HAVE_GAS_HIDDEN. */ -#undef HAVE_GAS_HIDDEN diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md deleted file mode 100644 index 364457d9347..00000000000 --- a/gcc/config/c4x/c4x.md +++ /dev/null @@ -1,7306 +0,0 @@ -;; Machine description for the TMS320C[34]x for GCC -;; Copyright (C) 1994, 1995, 1996, 1997, 1998, -;; 1999, 2000, 2002, 2004, 2005, 2007 Free Software Foundation, Inc. - -;; Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) -;; and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl) - -;; This file is part of GCC. - -;; GCC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. - -;; GCC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -; -; TODO : -; Try using PQImode again for addresses since C30 only uses -; 24-bit addresses. Ideally GCC would emit different insns -; for QImode and Pmode, whether Pmode was QImode or PQImode. -; For addresses we wouldn't have to have a clobber of the CC -; associated with each insn and we could use MPYI in address -; calculations without having to synthesize a proper 32-bit multiply. - -; Additional C30/C40 instructions not coded: -; CALLcond, IACK, IDLE, LDE, LDFI, LDII, LDM, NORM, RETIcond -; ROLC, RORC, SIGI, STFI, STII, SUBC, SWI - -; Additional C40 instructions not coded: -; LDEP, LDPE, LWRct, LAJcond, RETIcondD - -; -; C4x MODES -; -; QImode char, short, int, long (32-bits) -; HImode long long (64-bits) -; QFmode float, double (32-bits) -; HFmode long double (40-bits) -; CCmode -; CC_NOOVmode - -; -; C4x PREDICATES: -; -; comparison_operator LT, GT, LE, GE, LTU, GTU, LEU, GEU, EQ, NE -; memory_operand memory [m] -; immediate_operand immediate constant [IKN] -; register_operand register [rf] -; general_operand register, memory, constant [rfmI] - -; addr_reg_operand AR0-AR7, pseudo reg [a] -; sp_reg_operand SP [b] -; std_reg_operand AR0-AR7, IR0-IR1, RC, RS, RE, SP, pseudo [c] -; ext_reg_operand R0-R11, pseudo reg [f] -; ext_low_reg_operand R0-R7, pseudo reg [q] -; index_reg_operand IR0-IR1, pseudo reg [x] -; st_reg_operand ST [y] -; dp_reg_operand DP [z] -; stik_const_operand 5-bit const [K] -; src_operand general operand [rfHmI] -; par_ind_operand indirect S mode (ARx + 0, 1, IRx) [S<>] -; parallel_operand par_ind_operand or ext_low_reg_operand -; symbolic_address_operand -; call_address_operand - -; ADDI src2, src1, dst three operand op -; ADDI src, dst two operand op - -; Note that the predicates are only used when selecting a pattern -; to determine if an operand is valid. - -; The constraints then select which of the possible valid operands -; is present (and guide register selection). The actual assembly -; instruction is then selected on the basis of the constraints. - -; The extra constraint (valid_operands) is used to determine if -; the combination of operands is legitimate for the pattern. - -; -; C4x CONSTRAINTS: -; -; a address reg AR0-AR7 -; b stack pointer SP -; c other int reg AR0-AR7, IR0-IR1, RC, RS, RE -; d fp reg R0-R11 (sets CC when dst) -; e -; f fp reg R0-R11 (sets CC when dst) -; g general reg, memory, constant -; h fp reg (HFmode) R0-R11 (sets CC when dst) -; i immediate int constant -; j -; k block count BK -; l -; m memory -; n immediate int constant with known numeric value -; o offsettable memory -; p memory address -; q low fp reg R0-R7 (sets CC when dst) -; r general reg R0-R11, AR0-AR7, IR0-IR1, RC, RS, RE -; s immediate int constant (value not explicit) -; t R0-R1 -; u R2-R3 -; v repeat count reg RC -; w -; x index reg IR0-IR1 -; y status (CC) reg ST -; z data pointer DP - -; G fp zero -; H fp 16-bit constant -; I signed 16-bit -; J signed 8-bit (C4x only) -; K signed 5-bit (C4x only) -; L unsigned 16-bit -; M unsigned 8-bit (C4x only) -; N ones complement of unsigned 16-bit -; O 16-bit high constant -; Q ARx + 9-bit signed disp -; R ARx + 5-bit unsigned disp (C4x only) -; S ARx + 0, 1, IRx disp -; T direct memory operand -; V non offsettable memory -; X any operand -; < memory operand with autodecrement addressing -; > memory operand with autoincrement addressing -; { memory operand with pre-modify addressing -; } memory operand with post-modify addressing - -; Note that the 'd', 'f', and 'h' constraints are equivalent. -; The m constraint is equivalent to 'QT<>{}' - -; Note we cannot use the 'g' constraint with Pmode (i.e, QImode) -; operations since LEGITIMATE_CONSTANT_P accepts SYMBOL_REF. -; So instead we use 'rIm' for signed operands or 'rLm' for unsigned operands. - -; Note that the constraints are used to select the operands -; for a chosen pattern. The constraint that requires the fewest -; instructions to load an operand is chosen. - -; Note that the 'r' constraint is mostly only used for src integer register -; operands, while 'c' and 'd' constraints are generally only used for dst -; integer register operands (the 'r' constraint is the union of the 'c' and -; 'd' constraints). When a register satisfying the 'd' constraint -; is used as a dst operand, the CC gets clobbered (except for LDIcond)---but -; not for 'c'. - -; The 'f' constraint is only for float register operands---when -; a register satisfying the 'f' constraint is used as a dst operand, -; the CC gets clobbered (except for LDFcond). - -; The ! in front of the 'b' constraint says to GCC to disparage the -; use of this constraint. The 'b' constraint applies only to the SP. - -; Note that we deal with the condition code CC like some of the RISC -; architectures (arm, sh, sparc) where it is stored in a general register, -; in this case the hard register ST (21). Unlike these other architectures -; that do not set the CC with many instructions, the C[34]x architectures -; sets the CC for many instructions when the destination register is -; an extended precision register. While it would have been easier -; to use the generic cc0 register to store the CC, as with most of -; the other ported architectures, this constrains the setting and testing -; of the CC to be consecutive insns. Thus we would reduce the benefit -; of scheduling instructions to avoid pipeline conflicts and filling of -; delayed branch slots. - -; Since the C[34]x has many instructions that set the CC, we pay the -; price of having to explicitly define which insns clobber the CC -; (rather than using the macro NOTICE_UPDATE_CC). - -; Note that many patterns say that the CC is clobbered when in fact -; that it may not be (depending on the destination register). -; We have to cover ourselves if an extended precision register -; is allocated to the destination register. -; Unfortunately, it is not easy to tell GCC that the clobbering of CC -; is register dependent. If we could tolerate the ST register being -; copied about, then we could store the CC in a pseudo register and -; use constructs such as (clobber (match_scratch:CC N "&y,X")) to -; indicate that the 'y' class (ST register) is clobbered for the -; first combination of operands but not with the second. -; I tried this approach for a while but reload got unhappy since I -; didn't allow it to move the CC around. - -; Note that fundamental operations, such as moves, must not clobber the -; CC. Thus movqi chooses a move instruction that doesn't clobber the CC. -; If GCC wants to combine a move with a compare, it is smart enough to -; chose the move instruction that sets the CC. - -; Unfortunately, the C[34]x instruction set does not have arithmetic or -; logical operations that never touch the CC. We thus have to assume -; that the CC may be clobbered at all times. If we define patterns -; such as addqi without the clobber of CC, then GCC will be forced -; to use registers such as the auxiliary registers which can cause -; horrible pipeline conflicts. The tradeoff is that GCC can't now -; sneak in an add instruction between setting and testing of the CC. - -; Most of the C[34]x instructions require operands of the following formats, -; where imm represents an immediate constant, dir a direct memory reference, -; ind an indirect memory reference, and reg a register: - -; src2 (op2) src1 (op1) dst (op0) -; imm dir ind reg | imm dir ind reg | reg Notes -;---------------------+----------------------+------ -; ILH T Q<> r | - - - 0 | r 2 operand -; - - S<> r | - - S<> r | r -; J - R - | - - R r | r C4x - -; Arithmetic operations use the I, J constraints for immediate constants, -; while logical operations use the L, J constraints. Floating point -; operations use the H constraint for immediate constants. - -; With most instructions the src2 and src1 operands are commutative -; (except for SUB, SUBR, ANDN). The assembler considers -; ADDI 10, R0, R1 and ADDI R0, 10, R1 to be equivalent. -; We thus match src2 and src1 with the src_operand predicate and -; use valid_operands as the extra constraint to reject invalid -; operand combinations. For example, ADDI @foo, @bar, R0. - -; Note that we use the ? modifier so that reload doesn't preferentially -; try the alternative where three registers are acceptable as -; operands (whenever an operand requires reloading). Instead it will try -; the 2 operand form which will produce better code since it won't require -; a new spill register. - -; Note that the floating point representation of 0.0 on the C4x -; is 0x80000000 (-2147483648). This value produces a warning -; message on 32-bit machines about the decimal constant being so large -; that it is unsigned. - -; With two operand instructions patterns having two sets, -; the compare set must come first to keep the combiner happy. -; While the combiner seems to cope most of the time with the -; compare set coming second, it's best to have it first. - -; -; C4x CONSTANT attributes -; -(define_attr "cpu" "c4x,c3x" - (const - (cond [(symbol_ref "TARGET_C3X") (const_string "c3x")] - (const_string "c4x")))) - -; -; C4x INSN ATTRIBUTES: -; -; lda load address, non-clobber CC -; store memory store, non-clobber CC -; load_load parallel memory loads, non-clobber CC -; load_store parallel memory load and store, non-clobber CC -; store_load parallel memory store and load, non-clobber CC -; store_store parallel memory stores, non-clobber CC -; unary two operand arithmetic, non-clobber CC -; unarycc two operand arithmetic, clobber CC -; binary three operand arithmetic, non-clobber CC -; binarycc three operand arithmetic, clobber CC -; compare compare, clobber CC -; call function call -; rets return from subroutine -; jump unconditional branch -; jmpc conditional branch -; db decrement and branch (unconditional) -; dbc decrement and branch (conditional) -; ldp load DP -; push stack push -; pop stack pop -; repeat block repeat -; repeat_top block repeat top -; laj link and jump -; multi multiple instruction -; misc nop (default) - -; The only real instructions that affect things are the ones that modify -; address registers and ones that call or jump. Note that the number -; of operands refers to the RTL insn pattern, not the number of explicit -; operands in the machine instruction. -; -(define_attr "type" "lda,store,unary,unarycc,binary,binarycc,compare,call,rets,jump,jmpc,db,dbc,misc,ldp,repeat,repeat_top,laj,load_load,load_store,store_load,store_store,push,pop,multi" - (const_string "misc")) - - -; Some instructions operate on unsigned data constants, some on signed data -; constants, or the ones complement of unsigned constants. -; This differentiates them. Default to signed. This attribute -; is used by the macro SMALL_CONST () (defined in c4x.h) to determine -; whether an immediate integer constant will fit within the instruction, -; or will have to be loaded using direct addressing from memory. -; Note that logical operations assume unsigned integers whereas -; arithmetic operations assume signed integers. Note that the C4x -; small immediate constant (J) used as src2 in three operand instructions -; is always signed. not_uint16 refers to a number that fits into 16-bits -; when one's complemented. -; -(define_attr "data" "int16,uint16,high_16,not_uint16" (const_string "int16")) - -(define_asm_attributes - [(set_attr "type" "multi")]) - -; -; C4x DELAY SLOTS -; -; Define delay slot scheduling for branch and call instructions. -; The C[34]x has three delay slots. Note that none of the three instructions -; that follow a delayed branch can be a Bcond, BcondD, BR, BRD, DBcond, -; DBcondD, CALL, CALLcond, TRAPcond, RETIcond, RETScond, RPTB, RPTS, or IDLE. -; -; Annulled branches are a bit difficult because the next instructions -; are preprocessed. -; The table below shows what phase of the c4x is executed. -; BccA[TF] label -; op1 fetch, decode and read executed -; op2 fetch and decode executed -; op3 fetch executed -; This means that we can allow any instruction in the last delay slot -; and only instructions which modify registers in the first two. -; lda cannot be executed in the first delay slot -; and ldpk cannot be executed in the first two delay slots. - -(define_attr "onlyreg" "false,true" - (cond [(eq_attr "type" "unary,unarycc") - (if_then_else (and (match_operand 0 "reg_imm_operand" "") - (match_operand 1 "reg_imm_operand" "")) - (const_string "true") (const_string "false")) - (eq_attr "type" "binary,binarycc") - (if_then_else (and (match_operand 0 "reg_imm_operand" "") - (and (match_operand 1 "reg_imm_operand" "") - (match_operand 2 "reg_imm_operand" ""))) - (const_string "true") (const_string "false"))] - (const_string "false"))) - -(define_attr "onlyreg_nomod" "false,true" - (cond [(eq_attr "type" "unary,unarycc,compare,lda,store") - (if_then_else (and (match_operand 0 "not_modify_reg" "") - (match_operand 1 "not_modify_reg" "")) - (const_string "true") (const_string "false")) - (eq_attr "type" "binary,binarycc") - (if_then_else (and (match_operand 0 "not_modify_reg" "") - (and (match_operand 1 "not_modify_reg" "") - (match_operand 2 "not_modify_reg" ""))) - (const_string "true") (const_string "false"))] - (const_string "false"))) - -(define_attr "not_repeat_reg" "false,true" - (cond [(eq_attr "type" "unary,unarycc,compare,lda,ldp,store") - (if_then_else (and (match_operand 0 "not_rc_reg" "") - (match_operand 1 "not_rc_reg" "")) - (const_string "true") (const_string "false")) - (eq_attr "type" "binary,binarycc") - (if_then_else (and (match_operand 0 "not_rc_reg" "") - (and (match_operand 1 "not_rc_reg" "") - (match_operand 2 "not_rc_reg" ""))) - (const_string "true") (const_string "false"))] - (const_string "false"))) - -/* Disable compare because the c4x contains a bug. The cmpi insn sets the CC - in the read phase of the pipeline instead of the execution phase when - two registers are compared. */ -(define_attr "in_annul_slot_1" "false,true" - (if_then_else (and (and (eq_attr "cpu" "c4x") - (eq_attr "type" "!jump,call,rets,jmpc,compare,db,dbc,repeat,repeat_top,laj,push,pop,lda,ldp,multi")) - (eq_attr "onlyreg" "true")) - (const_string "true") - (const_string "false"))) - -(define_attr "in_annul_slot_2" "false,true" - (if_then_else (and (and (eq_attr "cpu" "c4x") - (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,ldp,multi")) - (eq_attr "onlyreg_nomod" "true")) - (const_string "true") - (const_string "false"))) - -/* Disable ldp because the c4x contains a bug. The ldp insn modifies - the dp register when the insn is anulled or not. - Also disable autoincrement insns because of a silicon bug. */ -(define_attr "in_annul_slot_3" "false,true" - (if_then_else (and (and (eq_attr "cpu" "c4x") - (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,ldp,multi")) - (eq_attr "onlyreg_nomod" "true")) - (const_string "true") - (const_string "false"))) - -(define_attr "in_delay_slot" "false,true" - (if_then_else (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,multi") - (const_string "true") - (const_string "false"))) - -(define_attr "in_repeat_slot" "false,true" - (if_then_else (and (eq_attr "cpu" "c4x") - (and (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,multi") - (eq_attr "not_repeat_reg" "true"))) - (const_string "true") - (const_string "false"))) - -(define_attr "in_dbc_slot" "false,true" - (if_then_else (eq_attr "type" "!jump,call,rets,jmpc,unarycc,binarycc,compare,db,dbc,repeat,repeat_top,laj,multi") - (const_string "true") - (const_string "false"))) - -(define_delay (eq_attr "type" "jmpc") - [(eq_attr "in_delay_slot" "true") - (eq_attr "in_annul_slot_1" "true") - (eq_attr "in_annul_slot_1" "true") - - (eq_attr "in_delay_slot" "true") - (eq_attr "in_annul_slot_2" "true") - (eq_attr "in_annul_slot_2" "true") - - (eq_attr "in_delay_slot" "true") - (eq_attr "in_annul_slot_3" "true") - (eq_attr "in_annul_slot_3" "true") ]) - - -(define_delay (eq_attr "type" "repeat_top") - [(eq_attr "in_repeat_slot" "true") (nil) (nil) - (eq_attr "in_repeat_slot" "true") (nil) (nil) - (eq_attr "in_repeat_slot" "true") (nil) (nil)]) - -(define_delay (eq_attr "type" "jump,db") - [(eq_attr "in_delay_slot" "true") (nil) (nil) - (eq_attr "in_delay_slot" "true") (nil) (nil) - (eq_attr "in_delay_slot" "true") (nil) (nil)]) - - -; Decrement and branch conditional instructions cannot modify the -; condition codes for the cycles in the delay slots. -; -(define_delay (eq_attr "type" "dbc") - [(eq_attr "in_dbc_slot" "true") (nil) (nil) - (eq_attr "in_dbc_slot" "true") (nil) (nil) - (eq_attr "in_dbc_slot" "true") (nil) (nil)]) - -; The LAJ instruction has three delay slots but the last slot is -; used for pushing the return address. Thus we can only use two slots. -; -(define_delay (eq_attr "type" "laj") - [(eq_attr "in_delay_slot" "true") (nil) (nil) - (eq_attr "in_delay_slot" "true") (nil) (nil)]) - -; -; C4x UNSPEC NUMBERS -; -(define_constants - [ - (UNSPEC_BU 1) - (UNSPEC_RPTS 2) - (UNSPEC_LSH 3) - (UNSPEC_CMPHI 4) - (UNSPEC_RCPF 5) - (UNSPEC_RND 6) - (UNSPEC_RPTB_FILL 7) - (UNSPEC_LOADHF_INT 8) - (UNSPEC_STOREHF_INT 9) - (UNSPEC_RSQRF 10) - (UNSPEC_LOADQF_INT 11) - (UNSPEC_STOREQF_INT 12) - (UNSPEC_LDIV 13) - (UNSPEC_PUSH_ST 14) - (UNSPEC_POP_ST 15) - (UNSPEC_PUSH_DP 16) - (UNSPEC_POP_DP 17) - (UNSPEC_POPQI 18) - (UNSPEC_POPQF 19) - (UNSPEC_ANDN_ST 20) - (UNSPEC_RPTB_INIT 22) - (UNSPEC_TOIEEE 23) - (UNSPEC_FRIEEE 24) - ]) - -; -; C4x PIPELINE MODEL -; -; With the C3x, an external memory write (with no wait states) takes -; two cycles and an external memory read (with no wait states) takes -; one cycle. However, an external read following an external write -; takes two cycles. With internal memory, reads and writes take -; half a cycle. -; When a C4x address register is loaded it will not be available for -; an extra machine cycle. Calculating with a C4x address register -; makes it unavailable for 2 machine cycles. -; -; Just some dummy definitions. The real work is done in c4x_adjust_cost. -; These are needed so the min/max READY_DELAY is known. - -(define_insn_reservation "any_insn" 1 (const_int 1) "nothing") -(define_insn_reservation "slowest_insn" 3 (const_int 0) "nothing") - -; The attribute setar0 is set to 1 for insns where ar0 is a dst operand. -; Note that the attributes unarycc and binarycc do not apply -; if ar0 is a dst operand (only loading an ext. prec. reg. sets CC) -(define_attr "setar0" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar0" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -; The attribute usear0 is set to 1 for insns where ar0 is used -; for addressing, as a src operand, or as a dst operand. -(define_attr "usear0" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -; The attribute readar0 is set to 1 for insns where ar0 is a src operand. -(define_attr "readar0" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar0_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar0_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setar1" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar1" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear1" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar1" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar1_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar1_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setar2" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar2_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar2" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar2_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear2" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar2_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar2_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar2_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar2_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar2" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar2_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar2_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar2_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setar3" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar3_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar3" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar3_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear3" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar3_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar3_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar3_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar3_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar3" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar3_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar3_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar3_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setar4" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar4_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar4" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar4_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear4" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar4_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar4_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar4_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar4_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar4" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar4_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar4_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar4_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setar5" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar5_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar5" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar5_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear5" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar5_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar5_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar5_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar5_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar5" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar5_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar5_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar5_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setar6" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar6_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar6" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar6_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear6" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar6_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar6_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar6_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar6_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar6" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar6_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar6_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar6_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setar7" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ar7_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ar7" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ar7_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usear7" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ar7_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar7_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar7_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "db,dbc") - (if_then_else (match_operand 0 "ar7_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readar7" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "ar7_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ar7_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ar7_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setir0" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ir0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ir0" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ir0_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "useir0" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ir0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ir0_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ir0_mem_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setir1" "" - (cond [(eq_attr "type" "unary,binary") - (if_then_else (match_operand 0 "ir1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "setlda_ir1" "" - (cond [(eq_attr "type" "lda") - (if_then_else (match_operand 0 "ir1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "useir1" "" - (cond [(eq_attr "type" "compare,store") - (if_then_else (match_operand 0 "ir1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "ir1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "ir1_mem_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -; With the C3x, things are simpler but slower, i.e. more pipeline conflicts :( -; There are three functional groups: -; (1) AR0-AR7, IR0-IR1, BK -; (2) DP -; (3) SP -; -; When a register in one of these functional groups is loaded, -; the contents of that or any other register in its group -; will not be available to the next instruction for 2 machine cycles. -; Similarly, when a register in one of the functional groups is read -; excepting (IR0-IR1, BK, DP) the contents of that or any other register -; in its group will not be available to the next instruction for -; 1 machine cycle. -; -; Let's ignore functional groups 2 and 3 for now, since they are not -; so important. - -(define_attr "setgroup1" "" - (cond [(eq_attr "type" "lda,unary,binary") - (if_then_else (match_operand 0 "group1_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "usegroup1" "" - (cond [(eq_attr "type" "compare,store,store_store,store_load") - (if_then_else (match_operand 0 "group1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc,load_load,load_store") - (if_then_else (match_operand 1 "group1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "store_store,load_store") - (if_then_else (match_operand 2 "group1_mem_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "load_load,store_load") - (if_then_else (match_operand 3 "group1_mem_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(define_attr "readarx" "" - (cond [(eq_attr "type" "compare") - (if_then_else (match_operand 0 "arx_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc") - (if_then_else (match_operand 1 "arx_reg_operand" "") - (const_int 1) (const_int 0)) - (eq_attr "type" "binary,binarycc") - (if_then_else (match_operand 2 "arx_reg_operand" "") - (const_int 1) (const_int 0))] - (const_int 0))) - -(include "predicates.md") - -; -; C4x INSN PATTERNS: -; -; Note that the movMM and addP patterns can be called during reload -; so we need to take special care with theses patterns since -; we cannot blindly clobber CC or generate new pseudo registers. - -; -; TWO OPERAND INTEGER INSTRUCTIONS -; - -; -; LDP/LDPK -; -(define_insn "set_ldp" - [(set (match_operand:QI 0 "dp_reg_operand" "=z") - (high:QI (match_operand:QI 1 "" "")))] - "! TARGET_SMALL" - "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";" - [(set_attr "type" "ldp")]) - -(define_insn "set_ldp_prologue" - [(set (match_operand:QI 0 "dp_reg_operand" "=z") - (high:QI (match_operand:QI 1 "" "")))] - "TARGET_SMALL && TARGET_PARANOID" - "* return (TARGET_C3X) ? \"ldp\\t@data_sec\" : \"ldpk\\t@data_sec\";" - [(set_attr "type" "ldp")]) - -(define_insn "set_high" - [(set (match_operand:QI 0 "std_reg_operand" "=c") - (high:QI (match_operand:QI 1 "symbolic_address_operand" "")))] - "! TARGET_C3X && ! TARGET_TI" - "ldhi\\t^%H1,%0" - [(set_attr "type" "unary")]) - -(define_insn "set_lo_sum" - [(set (match_operand:QI 0 "std_reg_operand" "+c") - (lo_sum:QI (match_dup 0) - (match_operand:QI 1 "symbolic_address_operand" "")))] - "! TARGET_TI" - "or\\t#%H1,%0" - [(set_attr "type" "unary")]) - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (match_operand:QI 1 "symbolic_address_operand" ""))] - "reload_completed && ! TARGET_C3X && ! TARGET_TI" - [(set (match_dup 0) (high:QI (match_dup 1))) - (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))] - "") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" "")) - (clobber (reg:QI 16))] - "! TARGET_C3X - && ! IS_INT16_CONST (INTVAL (operands[1])) - && ! IS_HIGH_CONST (INTVAL (operands[1])) - && reload_completed - && std_reg_operand (operands[0], QImode)" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] - " -{ - operands[2] = GEN_INT (INTVAL (operands[1]) & ~0xffff); - operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff); -}") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" ""))] - "! TARGET_C3X - && ! IS_INT16_CONST (INTVAL (operands[1])) - && ! IS_HIGH_CONST (INTVAL (operands[1])) - && reload_completed - && std_reg_operand (operands[0], QImode)" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] - " -{ - operands[2] = GEN_INT (INTVAL (operands[1]) & ~0xffff); - operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff); -}") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" "")) - (clobber (reg:QI 16))] - "TARGET_C3X && ! TARGET_SMALL - && ! IS_INT16_CONST (INTVAL (operands[1])) - && reload_completed - && std_reg_operand (operands[0], QImode) - && c4x_shiftable_constant (operands[1]) < 0" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 4))) - (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] - " -{ - /* Generate two's complement value of 16 MSBs. */ - operands[2] = GEN_INT ((((INTVAL (operands[1]) >> 16) & 0xffff) - - 0x8000) ^ ~0x7fff); - operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff); - operands[4] = GEN_INT (16); -}") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" ""))] - "TARGET_C3X && ! TARGET_SMALL - && ! IS_INT16_CONST (INTVAL (operands[1])) - && reload_completed - && std_reg_operand (operands[0], QImode) - && c4x_shiftable_constant (operands[1]) < 0" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 4))) - (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] - " -{ - /* Generate two's complement value of 16 MSBs. */ - operands[2] = GEN_INT ((((INTVAL (operands[1]) >> 16) & 0xffff) - - 0x8000) ^ ~0x7fff); - operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff); - operands[4] = GEN_INT (16); -}") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" "")) - (clobber (reg:QI 16))] - "TARGET_C3X - && ! IS_INT16_CONST (INTVAL (operands[1])) - && reload_completed - && std_reg_operand (operands[0], QImode) - && c4x_shiftable_constant (operands[1]) >= 0" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 3)))] - " -{ - /* Generate two's complement value of MSBs. */ - int shift = c4x_shiftable_constant (operands[1]); - - operands[2] = GEN_INT ((((INTVAL (operands[1]) >> shift) & 0xffff) - - 0x8000) ^ ~0x7fff); - operands[3] = GEN_INT (shift); -}") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" ""))] - "TARGET_C3X - && ! IS_INT16_CONST (INTVAL (operands[1])) - && reload_completed - && std_reg_operand (operands[0], QImode) - && c4x_shiftable_constant (operands[1]) >= 0" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 3)))] - " -{ - /* Generate two's complement value of MSBs. */ - int shift = c4x_shiftable_constant (operands[1]); - - operands[2] = GEN_INT ((((INTVAL (operands[1]) >> shift) & 0xffff) - - 0x8000) ^ ~0x7fff); - operands[3] = GEN_INT (shift); -}") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" "")) - (clobber (reg:QI 16))] - "! TARGET_SMALL - && ! IS_INT16_CONST (INTVAL (operands[1])) - && ! IS_HIGH_CONST (INTVAL (operands[1])) - && reload_completed - && ! std_reg_operand (operands[0], QImode)" - [(set (match_dup 2) (high:QI (match_dup 3))) - (set (match_dup 0) (match_dup 4)) - (use (match_dup 1))] - " -{ - rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); - operands[2] = dp_reg; - operands[3] = force_const_mem (Pmode, operands[1]); - operands[4] = change_address (operands[3], QImode, - gen_rtx_LO_SUM (Pmode, dp_reg, - XEXP (operands[3], 0))); - operands[3] = XEXP (operands[3], 0); -}") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" ""))] - "! TARGET_SMALL - && ! IS_INT16_CONST (INTVAL (operands[1])) - && ! IS_HIGH_CONST (INTVAL (operands[1])) - && reload_completed - && ! std_reg_operand (operands[0], QImode)" - [(set (match_dup 2) (high:QI (match_dup 3))) - (set (match_dup 0) (match_dup 4)) - (use (match_dup 1))] - " -{ - rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); - operands[2] = dp_reg; - operands[3] = force_const_mem (Pmode, operands[1]); - operands[4] = change_address (operands[3], QImode, - gen_rtx_LO_SUM (Pmode, dp_reg, - XEXP (operands[3], 0))); - operands[3] = XEXP (operands[3], 0); -}") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" "")) - (clobber (reg:QI 16))] - "TARGET_SMALL - && ! IS_INT16_CONST (INTVAL (operands[1])) - && ! IS_HIGH_CONST (INTVAL (operands[1])) - && reload_completed - && ((TARGET_C3X && c4x_shiftable_constant (operands[1]) < 0) - || ! std_reg_operand (operands[0], QImode))" - [(set (match_dup 0) (match_dup 2)) - (use (match_dup 1))] - " -{ - rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); - operands[2] = force_const_mem (Pmode, operands[1]); - operands[2] = change_address (operands[2], QImode, - gen_rtx_LO_SUM (Pmode, dp_reg, - XEXP (operands[2], 0))); -}") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" ""))] - "TARGET_SMALL - && ! IS_INT16_CONST (INTVAL (operands[1])) - && ! IS_HIGH_CONST (INTVAL (operands[1])) - && reload_completed - && ((TARGET_C3X && c4x_shiftable_constant (operands[1]) < 0) - || ! std_reg_operand (operands[0], QImode))" - [(set (match_dup 0) (match_dup 2)) - (use (match_dup 1))] - " -{ - rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); - operands[2] = force_const_mem (Pmode, operands[1]); - operands[2] = change_address (operands[2], QImode, - gen_rtx_LO_SUM (Pmode, dp_reg, - XEXP (operands[2], 0))); -}") - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (match_operand:HI 1 "const_int_operand" "")) - (clobber (reg:QI 16))] - "reload_completed" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - " -{ - operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode); -}") - - -; We need to clobber the DP reg to be safe in case we -; need to load this address from memory -(define_insn "load_immed_address" - [(set (match_operand:QI 0 "reg_operand" "=a?x?c*r") - (match_operand:QI 1 "symbolic_address_operand" "")) - (clobber (reg:QI 16))] - "TARGET_LOAD_ADDRESS" - "#" - [(set_attr "type" "multi")]) - - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (match_operand:QI 1 "symbolic_address_operand" "")) - (clobber (reg:QI 16))] - "reload_completed && ! TARGET_C3X && ! TARGET_TI" - [(set (match_dup 0) (high:QI (match_dup 1))) - (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))] - "") - -; CC has been selected to load a symbolic address. We force the address -; into memory and then generate LDP and LDIU insns. -; This is also required for the C30 if we pretend that we can -; easily load symbolic addresses into a register. -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "symbolic_address_operand" "")) - (clobber (reg:QI 16))] - "reload_completed - && ! TARGET_SMALL - && (TARGET_C3X || TARGET_TI || ! std_reg_operand (operands[0], QImode))" - [(set (match_dup 2) (high:QI (match_dup 3))) - (set (match_dup 0) (match_dup 4)) - (use (match_dup 1))] - " -{ - rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); - operands[2] = dp_reg; - operands[3] = force_const_mem (Pmode, operands[1]); - operands[4] = change_address (operands[3], QImode, - gen_rtx_LO_SUM (Pmode, dp_reg, - XEXP (operands[3], 0))); - operands[3] = XEXP (operands[3], 0); -}") - -; This pattern is similar to the above but does not emit a LDP -; for the small memory model. -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "symbolic_address_operand" "")) - (clobber (reg:QI 16))] - "reload_completed - && TARGET_SMALL - && (TARGET_C3X || TARGET_TI || ! std_reg_operand (operands[0], QImode))" - [(set (match_dup 0) (match_dup 2)) - (use (match_dup 1))] - " -{ - rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); - operands[2] = force_const_mem (Pmode, operands[1]); - operands[2] = change_address (operands[2], QImode, - gen_rtx_LO_SUM (Pmode, dp_reg, - XEXP (operands[2], 0))); -}") - -(define_insn "loadhi_big_constant" - [(set (match_operand:HI 0 "reg_operand" "=c*d") - (match_operand:HI 1 "const_int_operand" "")) - (clobber (reg:QI 16))] - "" - "#" - [(set_attr "type" "multi")]) - -; -; LDIU/LDA/STI/STIK -; -; The following moves will not set the condition codes register. -; - -; This must come before the general case -(define_insn "*movqi_stik" - [(set (match_operand:QI 0 "memory_operand" "=m") - (match_operand:QI 1 "stik_const_operand" "K"))] - "! TARGET_C3X" - "stik\\t%1,%0" - [(set_attr "type" "store")]) - -(define_insn "loadqi_big_constant" - [(set (match_operand:QI 0 "reg_operand" "=c*d") - (match_operand:QI 1 "const_int_operand" "")) - (clobber (reg:QI 16))] - "! IS_INT16_CONST (INTVAL (operands[1])) - && ! IS_HIGH_CONST (INTVAL (operands[1]))" - "#" - [(set_attr "type" "multi")]) - -; We must provide an alternative to store to memory in case we have to -; spill a register. -(define_insn "movqi_noclobber" - [(set (match_operand:QI 0 "dst_operand" "=d,*c,m,r") - (match_operand:QI 1 "src_hi_operand" "rIm,rIm,r,O"))] - "(REG_P (operands[0]) || REG_P (operands[1]) - || GET_CODE (operands[0]) == SUBREG - || GET_CODE (operands[1]) == SUBREG) - && ! symbolic_address_operand (operands[1], QImode)" - "* - if (which_alternative == 2) - return \"sti\\t%1,%0\"; - - if (! TARGET_C3X && which_alternative == 3) - { - operands[1] = GEN_INT ((INTVAL (operands[1]) >> 16) & 0xffff); - return \"ldhi\\t%1,%0\"; - } - - /* The lda instruction cannot use the same register as source - and destination. */ - if (! TARGET_C3X && which_alternative == 1 - && ( IS_ADDR_REG (operands[0]) - || IS_INDEX_REG (operands[0]) - || IS_SP_REG (operands[0])) - && (REGNO (operands[0]) != REGNO (operands[1]))) - return \"lda\\t%1,%0\"; - return \"ldiu\\t%1,%0\"; - " - [(set_attr "type" "unary,lda,store,unary") - (set_attr "data" "int16,int16,int16,high_16")]) - -; -; LDI -; - -; We shouldn't need these peepholes, but the combiner seems to miss them... -(define_peephole - [(set (match_operand:QI 0 "ext_reg_operand" "=d") - (match_operand:QI 1 "src_operand" "rIm")) - (set (reg:CC 21) - (compare:CC (match_dup 0) (const_int 0)))] - "" - "ldi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -(define_insn "*movqi_set" - [(set (reg:CC 21) - (compare:CC (match_operand:QI 1 "src_operand" "rIm") - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (match_dup 1))] - "" - "ldi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -; This pattern probably gets in the way and requires a scratch register -; when a simple compare with zero will suffice. -;(define_insn "*movqi_test" -; [(set (reg:CC 21) -; (compare:CC (match_operand:QI 1 "src_operand" "rIm") -; (const_int 0))) -; (clobber (match_scratch:QI 0 "=d"))] -; "" -; "@ -; ldi\\t%1,%0" -; [(set_attr "type" "unarycc") -; (set_attr "data" "int16")]) - -; If one of the operands is not a register, then we should -; emit two insns, using a scratch register. This will produce -; better code in loops if the source operand is invariant, since -; the source reload can be optimized out. During reload we cannot -; use change_address or force_reg which will allocate new pseudo regs. - -; Unlike most other insns, the move insns can't be split with -; different predicates, because register spilling and other parts of -; the compiler, have memoized the insn number already. - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (c4x_emit_move_sequence (operands, QImode)) - DONE; -}") - - -; As far as GCC is concerned, the moves are performed in parallel -; thus it must be convinced that there is no aliasing. -; It also assumes that the input operands are simultaneously loaded -; and then the output operands are simultaneously stored. -; With the C4x, if there are parallel stores to the same address -; both stores are executed. -; If there is a parallel load and store to the same address, -; the load is performed first. -; The problem with this pattern is that reload can spoil -; the show when it eliminates a reference to the frame pointer. -; This can invalidate the memory addressing mode, i.e., when -; the displacement is greater than 1. -(define_insn "movqi_parallel" - [(set (match_operand:QI 0 "parallel_operand" "=q,S<>!V,q,S<>!V") - (match_operand:QI 1 "parallel_operand" "S<>!V,q,S<>!V,q")) - (set (match_operand:QI 2 "parallel_operand" "=q,S<>!V,S<>!V,q") - (match_operand:QI 3 "parallel_operand" "S<>!V,q,q,S<>!V"))] - "TARGET_PARALLEL && valid_parallel_load_store (operands, QImode)" - "@ - ldi1\\t%1,%0\\n||\\tldi2\\t%3,%2 - sti1\\t%1,%0\\n||\\tsti2\\t%3,%2 - ldi\\t%1,%0\\n||\\tsti\\t%3,%2 - ldi\\t%3,%2\\n||\\tsti\\t%1,%0" - [(set_attr "type" "load_load,store_store,load_store,store_load")]) - -; -; PUSH/POP -; -(define_insn "pushqi" - [(set (mem:QI (pre_inc:QI (reg:QI 20))) - (match_operand:QI 0 "reg_operand" "r"))] - "" - "push\\t%0" - [(set_attr "type" "push")]) - -(define_insn "push_st" - [(set (mem:QI (pre_inc:QI (reg:QI 20))) - (unspec:QI [(reg:QI 21)] UNSPEC_PUSH_ST)) - (use (reg:QI 21))] - "" - "push\\tst" - [(set_attr "type" "push")]) - -(define_insn "push_dp" - [(set (mem:QI (pre_inc:QI (reg:QI 20))) - (unspec:QI [(reg:QI 16)] UNSPEC_PUSH_DP)) - (use (reg:QI 16))] - "" - "push\\tdp" - [(set_attr "type" "push")]) - -(define_insn "popqi" - [(set (match_operand:QI 0 "reg_operand" "=r") - (mem:QI (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))] - "" - "pop\\t%0" - [(set_attr "type" "pop")]) - -(define_insn "pop_st" - [(set (unspec:QI [(reg:QI 21)] UNSPEC_POP_ST) - (mem:QI (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))] - "" - "pop\\tst" - [(set_attr "type" "pop")]) - -(define_insn "pop_dp" - [(set (unspec:QI [(reg:QI 16)] UNSPEC_POP_DP) - (mem:QI (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 16))] - "" - "pop\\tdp" - [(set_attr "type" "pop")]) - -(define_insn "popqi_unspec" - [(set (unspec:QI [(match_operand:QI 0 "reg_operand" "=r")] UNSPEC_POPQI) - (mem:QI (post_dec:QI (reg:QI 20)))) - (clobber (match_dup 0)) - (clobber (reg:CC 21))] - "" - "pop\\t%0" - [(set_attr "type" "pop")]) - -; -; ABSI -; -(define_expand "absqi2" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (abs:QI (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "") - -(define_insn "*absqi2_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (abs:QI (match_operand:QI 1 "src_operand" "rIm,rIm"))) - (clobber (reg:CC_NOOV 21))] - "" - "absi\\t%1,%0" - [(set_attr "type" "unarycc,unary") - (set_attr "data" "int16,int16")]) - -(define_insn "*absqi2_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c") - (abs:QI (match_operand:QI 1 "src_operand" "rIm")))] - "" - "absi\\t%1,%0" - [(set_attr "type" "unary") - (set_attr "data" "int16")]) - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (abs:QI (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(set (match_dup 0) - (abs:QI (match_dup 1)))] - "") - -(define_insn "*absqi2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "rIm")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "" - "absi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -(define_insn "*absqi2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "rIm")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (abs:QI (match_dup 1)))] - "" - "absi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -; -; NEGI -; -(define_expand "negqi2" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (neg:QI (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] -"" -"") - -(define_insn "*negqi2_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (neg:QI (match_operand:QI 1 "src_operand" "rIm,rIm"))) - (clobber (reg:CC_NOOV 21))] - "" - "negi\\t%1,%0" - [(set_attr "type" "unarycc,unary") - (set_attr "data" "int16,int16")]) - -(define_insn "*negqi2_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c") - (neg:QI (match_operand:QI 1 "src_operand" "rIm")))] - "" - "negi\\t%1,%0" - [(set_attr "type" "unary") - (set_attr "data" "int16")]) - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (neg:QI (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(set (match_dup 0) - (neg:QI (match_dup 1)))] - "") - -(define_insn "*negqi2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "rIm")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "" - "negi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -(define_insn "*negqi2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "rIm")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (neg:QI (match_dup 1)))] - "" - "negi\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -(define_insn "*negbqi2_clobber" - [(set (match_operand:QI 0 "ext_reg_operand" "=d") - (neg:QI (match_operand:QI 1 "src_operand" "rIm"))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))] - "" - "negb\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "int16")]) - -; -; NOT -; -(define_expand "one_cmplqi2" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (not:QI (match_operand:QI 1 "lsrc_operand" ""))) - (clobber (reg:CC 21))])] - "" - "") - -(define_insn "*one_cmplqi2_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (not:QI (match_operand:QI 1 "lsrc_operand" "rLm,rLm"))) - (clobber (reg:CC 21))] - "" - "not\\t%1,%0" - [(set_attr "type" "unarycc,unary") - (set_attr "data" "uint16,uint16")]) - -(define_insn "*one_cmplqi2_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c") - (not:QI (match_operand:QI 1 "lsrc_operand" "rLm")))] - "" - "not\\t%1,%0" - [(set_attr "type" "unary") - (set_attr "data" "uint16")]) - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (not:QI (match_operand:QI 1 "lsrc_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(set (match_dup 0) - (not:QI (match_dup 1)))] - "") - -(define_insn "*one_cmplqi2_test" - [(set (reg:CC 21) - (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "rLm")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "" - "not\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "uint16")]) - -(define_insn "*one_cmplqi2_set" - [(set (reg:CC 21) - (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "rLm")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (not:QI (match_dup 1)))] - "" - "not\\t%1,%0" - [(set_attr "type" "unarycc") - (set_attr "data" "uint16")]) - -(define_insn "*one_cmplqi2_const_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (match_operand:QI 1 "not_const_operand" "N,N")) - (clobber (reg:CC 21))] - "" - "@ - not\\t%N1,%0 - not\\t%N1,%0" - [(set_attr "type" "unarycc,unary") - (set_attr "data" "not_uint16,not_uint16")]) - -; movqi can use this for loading an integer that can't normally -; fit into a 16-bit signed integer. The drawback is that it cannot -; go into R0-R11 since that will clobber the CC and movqi shouldn't -; do that. This can cause additional reloading but in most cases -; this will cause only an additional register move. With the large -; memory model we require an extra instruction to load DP anyway, -; if we're loading the constant from memory. The big advantage of -; allowing constants that satisfy not_const_operand in movqi, is that -; it allows andn to be generated more often. -; However, there is a problem if GCC has decided that it wants -; to use R0-R11, since we won't have a matching pattern... -; In interim, we prevent immed_const allowing `N' constants. -(define_insn "*one_cmplqi2_const_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c") - (match_operand:QI 1 "not_const_operand" "N"))] - "" - "not\\t%N1,%0" - [(set_attr "type" "unary") - (set_attr "data" "not_uint16")]) - -; -; ROL -; -(define_expand "rotlqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (rotate:QI (match_operand:QI 1 "reg_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (INTVAL (operands[2]) > 4) - FAIL; /* Open code as two shifts and an or */ - if (INTVAL (operands[2]) > 1) - { - int i; - rtx tmp; - - /* If we have 4 or fewer shifts, then it is probably faster - to emit separate ROL instructions. A C3x requires - at least 4 instructions (a C4x requires at least 3), to - perform a rotation by shifts. */ - - tmp = operands[1]; - for (i = 0; i < INTVAL (operands[2]) - 1; i++) - { - tmp = gen_reg_rtx (QImode); - emit_insn (gen_rotl_1_clobber (tmp, operands[1])); - operands[1] = tmp; - } - emit_insn (gen_rotl_1_clobber (operands[0], tmp)); - DONE; - }") - -(define_insn "rotl_1_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (rotate:QI (match_operand:QI 1 "reg_operand" "0,0") - (const_int 1))) - (clobber (reg:CC 21))] - "" - "rol\\t%0" - [(set_attr "type" "unarycc,unary")]) -; Default to int16 data attr. - -; -; ROR -; -(define_expand "rotrqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (rotatert:QI (match_operand:QI 1 "reg_operand" "") - (match_operand:QI 2 "const_int_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (INTVAL (operands[2]) > 4) - FAIL; /* Open code as two shifts and an or */ - if (INTVAL (operands[2]) > 1) - { - int i; - rtx tmp; - - /* If we have 4 or fewer shifts, then it is probably faster - to emit separate ROL instructions. A C3x requires - at least 4 instructions (a C4x requires at least 3), to - perform a rotation by shifts. */ - - tmp = operands[1]; - for (i = 0; i < INTVAL (operands[2]) - 1; i++) - { - tmp = gen_reg_rtx (QImode); - emit_insn (gen_rotr_1_clobber (tmp, operands[1])); - operands[1] = tmp; - } - emit_insn (gen_rotr_1_clobber (operands[0], tmp)); - DONE; - }") - -(define_insn "rotr_1_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (rotatert:QI (match_operand:QI 1 "reg_operand" "0,0") - (const_int 1))) - (clobber (reg:CC 21))] - "" - "ror\\t%0" - [(set_attr "type" "unarycc,unary")]) -; Default to int16 data attr. - - -; -; THREE OPERAND INTEGER INSTRUCTIONS -; - -; -; ADDI -; -; This is used by reload when it calls gen_add2_insn for address arithmetic -; so we must emit the pattern that doesn't clobber CC. -; -(define_expand "addqi3" - [(parallel [(set (match_operand:QI 0 "std_or_reg_operand" "") - (plus:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (PLUS, operands, QImode); - if (reload_in_progress - || (! IS_PSEUDO_REG (operands[0]) - && ! IS_EXT_REG (operands[0]))) - { - emit_insn (gen_addqi3_noclobber (operands[0], operands[1], operands[2])); - DONE; - }") - -; This pattern is required primarily for manipulating the stack pointer -; where GCC doesn't expect CC to be clobbered or for calculating -; addresses during reload. Since this is a more specific pattern -; it needs to go first (otherwise we get into problems trying to decide -; to add clobbers). -(define_insn "addqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,c") - (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*addqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0 - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (plus:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(set (match_dup 0) - (plus:QI (match_dup 1) - (match_dup 2)))] - "") - -(define_insn "*addqi3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,d,d"))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -; gcc does this in combine.c we just reverse it here -(define_insn "*cmp_neg" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (neg: QI (match_operand:QI 2 "src_operand" "g,JR,rS<>")))) - (clobber (match_scratch:QI 0 "=d,d,d"))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,d,d") - (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "src_operand" "g,JR,rS<>"))) - (clobber (reg:CC_NOOV 21))]) - (set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_dup 0) (const_int 0)))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*addqi3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,d,d") - (plus:QI (match_dup 1) (match_dup 2)))] - "valid_operands (PLUS, operands, QImode)" - "@ - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - - -; This pattern is required during reload when eliminate_regs_in_insn -; effectively converts a move insn into an add insn when the src -; operand is the frame pointer plus a constant. Without this -; pattern, gen_addqi3 can be called with a register for operand0 -; that can clobber CC. -; For example, we may have (set (mem (reg ar0)) (reg 99)) -; with (set (reg 99) (plus (reg ar3) (const_int 8))) -; Now since ar3, the frame pointer, is unchanging within the function, -; (plus (reg ar3) (const_int 8)) is considered a constant. -; eliminate_regs_in_insn substitutes this constant to give -; (set (mem (reg ar0)) (plus (reg ar3) (const_int 8))). -; This is an invalid C4x insn but if we don't provide a pattern -; for it, it will be considered to be a move insn for reloading. -(define_insn "*addqi3_noclobber_reload" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,c") - (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")))] - "reload_in_progress" - "@ - addi\\t%2,%0 - addi3\\t%2,%1,%0 - addi3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary")]) -; Default to int16 data attr. - - -(define_insn "*addqi3_carry_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>"))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))] - "valid_operands (PLUS, operands, QImode)" - "@ - addc\\t%2,%0 - addc3\\t%2,%1,%0 - addc3\\t%2,%1,%0 - addc\\t%2,%0 - addc3\\t%2,%1,%0 - addc3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - - -; -; SUBI/SUBRI -; -(define_expand "subqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (minus:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MINUS, operands, QImode);") - -(define_insn "*subqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,d,?d,c,c,c,?c") - (minus:QI (match_operand:QI 1 "src_operand" "0,rIm,rR,rS<>,0,rIm,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,0,JR,rS<>,rIm,0,JR,rS<>"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, QImode)" - "@ - subi\\t%2,%0 - subri\\t%1,%0 - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0 - subi\\t%2,%0 - subri\\t%1,%0 - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc,binary,binary,binary,binary")]) -; Default to int16 data attr. - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (minus:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(set (match_dup 0) - (minus:QI (match_dup 1) - (match_dup 2)))] - "") - -(define_insn "*subqi3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "0,rIm,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,0,JR,rS<>")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,d,d,?d"))] - "valid_operands (MINUS, operands, QImode)" - "@ - subi\\t%2,%0 - subri\\t%1,%0 - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,d,d,?d") - (minus:QI (match_operand:QI 1 "src_operand" "0,rIm,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,0,JR,rS<>"))) - (clobber (reg:CC_NOOV 21))]) - (set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_dup 0) (const_int 0)))] - "valid_operands (MINUS, operands, QImode)" - "@ - subi\\t%2,%0 - subri\\t%1,%0 - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -(define_insn "*subqi3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "0,rIm,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,0,JR,rS<>")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,d,d,?d") - (minus:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (MINUS, operands, QImode)" - "@ - subi\\t%2,%0 - subri\\t%1,%0 - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -(define_insn "*subqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,c,?c") - (minus:QI (match_operand:QI 1 "src_operand" "0,rIm,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,0,JR,rS<>")))] - "valid_operands (MINUS, operands, QImode)" - "@ - subi\\t%2,%0 - subri\\t%1,%0 - subi3\\t%2,%1,%0 - subi3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*subqi3_carry_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,d,?d,c,c,c,?c") - (minus:QI (match_operand:QI 1 "src_operand" "0,rIm,rR,rS<>,0,rIm,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,0,JR,rS<>,rIm,0,JR,rS<>"))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, QImode)" - "@ - subb\\t%2,%0 - subrb\\t%1,%0 - subb3\\t%2,%1,%0 - subb3\\t%2,%1,%0 - subb\\t%2,%0 - subrb\\t%1,%0 - subb3\\t%2,%1,%0 - subb3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc,binary,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*subqi3_carry_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "0,rIm,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,0,JR,rS<>")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,d,d,?d") - (minus:QI (match_dup 1) - (match_dup 2))) - (use (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, QImode)" - "@ - subb\\t%2,%0 - subrb\\t%1,%0 - subb3\\t%2,%1,%0 - subb3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -; -; MPYI -; -(define_expand "mulqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (mult:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "if (TARGET_MPYI || (GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2])) >= 0)) - legitimize_operands (MULT, operands, QImode); - else - { - if (GET_CODE (operands[2]) == CONST_INT) - { - /* Let GCC try to synthesize the multiplication using shifts - and adds. In most cases this will be more profitable than - using the C3x MPYI. */ - FAIL; - } - if (operands[1] == operands[2]) - { - /* Do the squaring operation in-line. */ - emit_insn (gen_sqrqi2_inline (operands[0], operands[1])); - DONE; - } - if (TARGET_INLINE) - { - emit_insn (gen_mulqi3_inline (operands[0], operands[1], - operands[2])); - DONE; - } - c4x_emit_libcall3 (optab_libfunc (smul_optab, QImode), - MULT, QImode, operands); - DONE; - } - ") - -(define_insn "*mulqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (mult:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MULT, operands, QImode)" - "* - if (which_alternative == 0 || which_alternative == 3) - { - if (TARGET_C3X - && GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2])) >= 0) - return \"ash\\t%L2,%0\"; - else - return \"mpyi\\t%2,%0\"; - } - else - return \"mpyi3\\t%2,%1,%0\";" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*mulqi3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,d,d"))] - "valid_operands (MULT, operands, QImode)" - "* - if (which_alternative == 0) - { - if (TARGET_C3X - && GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2])) >= 0) - return \"ash\\t%L2,%0\"; - else - return \"mpyi\\t%2,%0\"; - } - else - return \"mpyi3\\t%2,%1,%0\";" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -(define_insn "*mulqi3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,d,d") - (mult:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (MULT, operands, QImode)" - "* - if (which_alternative == 0) - { - if (TARGET_C3X - && GET_CODE (operands[2]) == CONST_INT - && exact_log2 (INTVAL (operands[2])) >= 0) - return \"ash\\t%L2,%0\"; - else - return \"mpyi\\t%2,%0\"; - } - else - return \"mpyi3\\t%2,%1,%0\";" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -; The C3x multiply instruction assumes 24-bit signed integer operands -; and the 48-bit result is truncated to 32-bits. -(define_insn "mulqi3_24_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (mult:QI - (sign_extend:QI - (and:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>") - (const_int 16777215))) - (sign_extend:QI - (and:QI (match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>") - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))] - "TARGET_C3X && valid_operands (MULT, operands, QImode)" - "@ - mpyi\\t%2,%0 - mpyi3\\t%2,%1,%0 - mpyi3\\t%2,%1,%0 - mpyi\\t%2,%0 - mpyi3\\t%2,%1,%0 - mpyi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - - -; Fast square function for C3x where TARGET_MPYI not asserted -(define_expand "sqrqi2_inline" - [(set (match_dup 7) (match_operand:QI 1 "src_operand" "")) - (parallel [(set (match_dup 3) - (lshiftrt:QI (match_dup 7) (const_int 16))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 2) - (and:QI (match_dup 7) (const_int 65535))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 4) - (mult:QI (sign_extend:QI (and:QI (match_dup 2) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 2) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 5) - (mult:QI (sign_extend:QI (and:QI (match_dup 2) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 3) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 6) - (ashift:QI (match_dup 5) (const_int 17))) - (clobber (reg:CC 21))]) - (parallel [(set (match_operand:QI 0 "reg_operand" "") - (plus:QI (match_dup 4) (match_dup 6))) - (clobber (reg:CC_NOOV 21))])] - "" - " - operands[2] = gen_reg_rtx (QImode); /* a = val & 0xffff */ - operands[3] = gen_reg_rtx (QImode); /* b = val >> 16 */ - operands[4] = gen_reg_rtx (QImode); /* a * a */ - operands[5] = gen_reg_rtx (QImode); /* a * b */ - operands[6] = gen_reg_rtx (QImode); /* (a * b) << 17 */ - operands[7] = gen_reg_rtx (QImode); /* val */ - ") - -; Inlined integer multiply for C3x -(define_expand "mulqi3_inline" - [(set (match_dup 12) (const_int -16)) - (set (match_dup 13) (match_operand:QI 1 "src_operand" "")) - (set (match_dup 14) (match_operand:QI 2 "src_operand" "")) - (parallel [(set (match_dup 4) - (lshiftrt:QI (match_dup 13) (neg:QI (match_dup 12)))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 6) - (lshiftrt:QI (match_dup 14) (neg:QI (match_dup 12)))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 3) - (and:QI (match_dup 13) - (const_int 65535))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 5) - (and:QI (match_dup 14) - (const_int 65535))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 7) - (mult:QI (sign_extend:QI (and:QI (match_dup 4) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 5) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 8) - (mult:QI (sign_extend:QI (and:QI (match_dup 3) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 5) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 9) - (mult:QI (sign_extend:QI (and:QI (match_dup 3) - (const_int 16777215))) - (sign_extend:QI (and:QI (match_dup 6) - (const_int 16777215))))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 10) - (plus:QI (match_dup 7) (match_dup 9))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 11) - (ashift:QI (match_dup 10) (const_int 16))) - (clobber (reg:CC 21))]) - (parallel [(set (match_operand:QI 0 "reg_operand" "") - (plus:QI (match_dup 8) (match_dup 11))) - (clobber (reg:CC_NOOV 21))])] - "TARGET_C3X" - " - operands[3] = gen_reg_rtx (QImode); /* a = arg1 & 0xffff */ - operands[4] = gen_reg_rtx (QImode); /* b = arg1 >> 16 */ - operands[5] = gen_reg_rtx (QImode); /* a = arg2 & 0xffff */ - operands[6] = gen_reg_rtx (QImode); /* b = arg2 >> 16 */ - operands[7] = gen_reg_rtx (QImode); /* b * c */ - operands[8] = gen_reg_rtx (QImode); /* a * c */ - operands[9] = gen_reg_rtx (QImode); /* a * d */ - operands[10] = gen_reg_rtx (QImode); /* b * c + a * d */ - operands[11] = gen_reg_rtx (QImode); /* (b *c + a * d) << 16 */ - operands[12] = gen_reg_rtx (QImode); /* -16 */ - operands[13] = gen_reg_rtx (QImode); /* arg1 */ - operands[14] = gen_reg_rtx (QImode); /* arg2 */ - ") - -; -; MPYSHI (C4x only) -; -(define_expand "smulqi3_highpart" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (truncate:QI - (lshiftrt:HI - (mult:HI - (sign_extend:HI (match_operand:QI 1 "src_operand" "")) - (sign_extend:HI (match_operand:QI 2 "src_operand" ""))) - (const_int 32)))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MULT, operands, QImode); - if (TARGET_C3X) - { - c4x_emit_libcall_mulhi (smulhi3_libfunc, SIGN_EXTEND, QImode, operands); - DONE; - } - ") - -(define_insn "*smulqi3_highpart_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (truncate:QI - (lshiftrt:HI - (mult:HI - (sign_extend:HI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>")) - (sign_extend:HI (match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>"))) - (const_int 32)))) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X && valid_operands (MULT, operands, QImode)" - "@ - mpyshi\\t%2,%0 - mpyshi3\\t%2,%1,%0 - mpyshi3\\t%2,%1,%0 - mpyshi\\t%2,%0 - mpyshi3\\t%2,%1,%0 - mpyshi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "int16,int16,int16,int16,int16,int16")]) - -(define_insn "*smulqi3_highpart_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,?c") - (truncate:QI - (lshiftrt:HI - (mult:HI - (sign_extend:HI (match_operand:QI 1 "src_operand" "0,rR,rS<>")) - (sign_extend:HI (match_operand:QI 2 "src_operand" "rIm,JR,rS<>"))) - (const_int 32))))] - "! TARGET_C3X && valid_operands (MULT, operands, QImode)" - "@ - mpyshi\\t%2,%0 - mpyshi3\\t%2,%1,%0 - mpyshi3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary") - (set_attr "data" "int16,int16,int16")]) - -; -; MPYUHI (C4x only) -; -(define_expand "umulqi3_highpart" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (truncate:QI - (lshiftrt:HI - (mult:HI - (zero_extend:HI (match_operand:QI 1 - "nonimmediate_src_operand" "")) - (zero_extend:HI (match_operand:QI 2 - "nonimmediate_lsrc_operand" ""))) - (const_int 32)))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MULT, operands, QImode); - if (TARGET_C3X) - { - c4x_emit_libcall_mulhi (umulhi3_libfunc, ZERO_EXTEND, QImode, operands); - DONE; - } - ") - -(define_insn "*umulqi3_highpart_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (truncate:QI - (lshiftrt:HI - (mult:HI - (zero_extend:HI (match_operand:QI 1 - "nonimmediate_src_operand" "%0,rR,rS<>,0,rR,rS<>")) - (zero_extend:HI (match_operand:QI 2 - "nonimmediate_lsrc_operand" "rm,R,rS<>,rm,R,rS<>"))) - (const_int 32)))) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X && valid_operands (MULT, operands, QImode)" - "@ - mpyuhi\\t%2,%0 - mpyuhi3\\t%2,%1,%0 - mpyuhi3\\t%2,%1,%0 - mpyuhi\\t%2,%0 - mpyuhi3\\t%2,%1,%0 - mpyuhi3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "uint16,uint16,uint16,uint16,uint16,uint16")]) - -(define_insn "*umulqi3_highpart_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,?c") - (truncate:QI - (lshiftrt:HI - (mult:HI - (zero_extend:HI (match_operand:QI 1 - "nonimmediate_src_operand" "0,rR,rS<>")) - (zero_extend:HI (match_operand:QI 2 - "nonimmediate_lsrc_operand" "rm,R,rS<>"))) - (const_int 32))))] - "! TARGET_C3X && valid_operands (MULT, operands, QImode)" - "@ - mpyuhi\\t%2,%0 - mpyuhi3\\t%2,%1,%0 - mpyuhi3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary") - (set_attr "data" "uint16,uint16,uint16")]) - -; -; AND -; -(define_expand "andqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (and:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "tsrc_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (AND, operands, QImode);") - - -(define_insn "*andqi3_255_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (and:QI (match_operand:QI 1 "src_operand" "mr,mr") - (const_int 255))) - (clobber (reg:CC 21))] - "! TARGET_C3X" - "lbu0\\t%1,%0" - [(set_attr "type" "unarycc,unary")]) - -(define_insn "*andqi3_255_noclobber" - [(set (match_operand:QI 0 "reg_operand" "=c") - (and:QI (match_operand:QI 1 "src_operand" "mr") - (const_int 255)))] - "! TARGET_C3X" - "lbu0\\t%1,%0" - [(set_attr "type" "unary")]) - - -(define_insn "*andqi3_65535_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (and:QI (match_operand:QI 1 "src_operand" "mr,mr") - (const_int 65535))) - (clobber (reg:CC 21))] - "! TARGET_C3X" - "lhu0\\t%1,%0" - [(set_attr "type" "unarycc,unary")]) - -(define_insn "*andqi3_65535_noclobber" - [(set (match_operand:QI 0 "reg_operand" "=c") - (and:QI (match_operand:QI 1 "src_operand" "mr") - (const_int 65535)))] - "! TARGET_C3X" - "lhu0\\t%1,%0" - [(set_attr "type" "unary")]) - -(define_insn "*andqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,d,?d,c,c,c,?c") - (and:QI (match_operand:QI 1 "src_operand" "%0,0,rR,rS<>,0,0,rR,rS<>") - (match_operand:QI 2 "tsrc_operand" "N,rLm,JR,rS<>,N,rLm,JR,rS<>"))) - (clobber (reg:CC 21))] - "valid_operands (AND, operands, QImode)" - "@ - andn\\t%N2,%0 - and\\t%2,%0 - and3\\t%2,%1,%0 - and3\\t%2,%1,%0 - andn\\t%N2,%0 - and\\t%2,%0 - and3\\t%2,%1,%0 - and3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc,binary,binary,binary,binary") - (set_attr "data" "not_uint16,uint16,int16,uint16,not_uint16,uint16,int16,uint16")]) - -(define_insn "*andqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,c,?c") - (and:QI (match_operand:QI 1 "src_operand" "%0,0,rR,rS<>") - (match_operand:QI 2 "tsrc_operand" "N,rLm,JR,rS<>")))] - "valid_operands (AND, operands, QImode)" - "@ - andn\\t%N2,%0 - and\\t%2,%0 - and3\\t%2,%1,%0 - and3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary,binary") - (set_attr "data" "not_uint16,uint16,int16,uint16")]) - -(define_insn "andn_st" - [(set (unspec:QI [(reg:QI 21)] 20) - (and:QI (unspec:QI [(reg:QI 21)] UNSPEC_ANDN_ST) - (match_operand:QI 0 "" "N"))) - (use (match_dup 0)) - (use (reg:CC 21)) - (clobber (reg:CC 21))] - "" - "andn\\t%N0,st" - [(set_attr "type" "misc") - (set_attr "data" "not_uint16")]) - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (and:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "tsrc_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(set (match_dup 0) - (and:QI (match_dup 1) - (match_dup 2)))] - "") - -(define_insn "*andqi3_test" - [(set (reg:CC 21) - (compare:CC (and:QI (match_operand:QI 1 "src_operand" "%0,r,rR,rS<>") - (match_operand:QI 2 "tsrc_operand" "N,rLm,JR,rS<>")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,X,X,?X"))] - "valid_operands (AND, operands, QImode)" - "@ - andn\\t%N2,%0 - tstb\\t%2,%1 - tstb3\\t%2,%1 - tstb3\\t%2,%1" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc") - (set_attr "data" "not_uint16,uint16,int16,uint16")]) - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,d,d,?d") - (and:QI (match_operand:QI 1 "src_operand" "%0,0,rR,rS<>") - (match_operand:QI 2 "tsrc_operand" "N,rLm,JR,rS<>"))) - (clobber (reg:CC 21))]) - (set (reg:CC 21) - (compare:CC (match_dup 0) (const_int 0)))] - "valid_operands (AND, operands, QImode)" - "@ - andn\\t%N2,%0 - and\\t%2,%0 - and3\\t%2,%1,%0 - and3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc") - (set_attr "data" "not_uint16,uint16,int16,uint16")]) - -(define_insn "*andqi3_set" - [(set (reg:CC 21) - (compare:CC (and:QI (match_operand:QI 1 "src_operand" "%0,0,rR,rS<>") - (match_operand:QI 2 "tsrc_operand" "N,rLm,JR,rS<>")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,d,d,?d") - (and:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (AND, operands, QImode)" - "@ - andn\\t%N2,%0 - and\\t%2,%0 - and3\\t%2,%1,%0 - and3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc") - (set_attr "data" "not_uint16,uint16,int16,uint16")]) - -; -; ANDN -; -; NB, this insn doesn't have commutative operands, but valid_operands -; assumes that the code AND does. We might have to kludge this if -; we make valid_operands stricter. -(define_insn "*andnqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>,rLm,JR,rS<>")) - (match_operand:QI 1 "src_operand" "0,rR,rS<>,0,rR,rS<>"))) - (clobber (reg:CC 21))] - "valid_operands (AND, operands, QImode)" - "@ - andn\\t%2,%0 - andn3\\t%2,%1,%0 - andn3\\t%2,%1,%0 - andn\\t%2,%0 - andn3\\t%2,%1,%0 - andn3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "uint16,int16,uint16,uint16,int16,uint16")]) - -(define_insn "*andnqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,?c") - (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")) - (match_operand:QI 1 "src_operand" "0,rR,rS<>")))] - "valid_operands (AND, operands, QImode)" - "@ - andn\\t%2,%0 - andn3\\t%2,%1,%0 - andn3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary") - (set_attr "data" "uint16,int16,uint16")]) - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "")) - (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(set (match_dup 0) - (and:QI (not:QI (match_dup 2)) - (match_dup 1)))] - "") - -(define_insn "*andnqi3_test" - [(set (reg:CC 21) - (compare:CC (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")) - (match_operand:QI 1 "src_operand" "0,rR,rS<>")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,d,d"))] - "valid_operands (AND, operands, QImode)" - "@ - andn\\t%2,%0 - andn3\\t%2,%1,%0 - andn3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "uint16,int16,uint16")]) - -(define_insn "*andnqi3_set" - [(set (reg:CC 21) - (compare:CC (and:QI (not:QI (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")) - (match_operand:QI 1 "src_operand" "0,rR,rS<>")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,d,d") - (and:QI (not:QI (match_dup 2)) - (match_dup 1)))] - "valid_operands (AND, operands, QImode)" - "@ - andn\\t%2,%0 - andn3\\t%2,%1,%0 - andn3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "uint16,int16,uint16")]) - -; -; OR -; -(define_expand "iorqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (ior:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "lsrc_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (IOR, operands, QImode);") - -(define_insn "*iorqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (ior:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>") - (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>,rLm,JR,rS<>"))) - (clobber (reg:CC 21))] - "valid_operands (IOR, operands, QImode)" - "@ - or\\t%2,%0 - or3\\t%2,%1,%0 - or3\\t%2,%1,%0 - or\\t%2,%0 - or3\\t%2,%1,%0 - or3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "uint16,int16,uint16,uint16,int16,uint16")]) - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (ior:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "lsrc_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(set (match_dup 0) - (ior:QI (match_dup 1) - (match_dup 2)))] - "") - -(define_insn "*iorqi3_test" - [(set (reg:CC 21) - (compare:CC (ior:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,d,d"))] - "valid_operands (IOR, operands, QImode)" - "@ - or\\t%2,%0 - or3\\t%2,%1,%0 - or3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "uint16,int16,uint16")]) - -(define_peephole - [(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,d,d") - (ior:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>"))) - (clobber (reg:CC 21))]) - (set (reg:CC 21) - (compare:CC (match_dup 0) (const_int 0)))] - "valid_operands (IOR, operands, QImode)" - "@ - or\\t%2,%0 - or3\\t%2,%1,%0 - or3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "uint16,int16,uint16")]) - -(define_insn "*iorqi3_set" - [(set (reg:CC 21) - (compare:CC (ior:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,d,d") - (ior:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (IOR, operands, QImode)" - "@ - or\\t%2,%0 - or3\\t%2,%1,%0 - or3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "uint16,int16,uint16")]) - -; This pattern is used for loading symbol references in several parts. -(define_insn "iorqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,c") - (ior:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")))] - "valid_operands (IOR, operands, QImode)" - "@ - or\\t%2,%0 - or3\\t%2,%1,%0 - or3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary") - (set_attr "data" "uint16,int16,uint16")]) - -; -; XOR -; -(define_expand "xorqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (xor:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "lsrc_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (XOR, operands, QImode);") - -(define_insn "*xorqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (xor:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>") - (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>,rLm,JR,rS<>"))) - (clobber (reg:CC 21))] - "valid_operands (XOR, operands, QImode)" - "@ - xor\\t%2,%0 - xor3\\t%2,%1,%0 - xor3\\t%2,%1,%0 - xor\\t%2,%0 - xor3\\t%2,%1,%0 - xor3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary") - (set_attr "data" "uint16,int16,uint16,uint16,int16,uint16")]) - -(define_insn "*xorqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,?c") - (xor:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")))] - "valid_operands (XOR, operands, QImode)" - "@ - xor\\t%2,%0 - xor3\\t%2,%1,%0 - xor3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary") - (set_attr "data" "uint16,int16,uint16")]) - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (xor:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "lsrc_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(set (match_dup 0) - (xor:QI (match_dup 1) - (match_dup 2)))] - "") - -(define_insn "*xorqi3_test" - [(set (reg:CC 21) - (compare:CC (xor:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d,d,d"))] - "valid_operands (XOR, operands, QImode)" - "@ - xor\\t%2,%0 - xor3\\t%2,%1,%0 - xor3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "uint16,int16,uint16")]) - -(define_insn "*xorqi3_set" - [(set (reg:CC 21) - (compare:CC (xor:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>") - (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d,d,d") - (xor:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (XOR, operands, QImode)" - "@ - xor\\t%2,%0 - xor3\\t%2,%1,%0 - xor3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc") - (set_attr "data" "uint16,int16,uint16")]) - -; -; LSH/ASH (left) -; -; The C3x and C4x have two shift instructions ASH and LSH -; If the shift count is positive, a left shift is performed -; otherwise a right shift is performed. The number of bits -; shifted is determined by the seven LSBs of the shift count. -; If the absolute value of the count is 32 or greater, the result -; using the LSH instruction is zero; with the ASH insn the result -; is zero or negative 1. Note that the ISO C standard allows -; the result to be machine dependent whenever the shift count -; exceeds the size of the object. -(define_expand "ashlqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (ashift:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (ASHIFT, operands, QImode);") - -(define_insn "*ashlqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (ashift:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>,0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>"))) - (clobber (reg:CC 21))] - "valid_operands (ASHIFT, operands, QImode)" - "@ - ash\\t%2,%0 - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0 - ash\\t%2,%0 - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*ashlqi3_set" - [(set (reg:CC 21) - (compare:CC - (ashift:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=d,d,d") - (ashift:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (ASHIFT, operands, QImode)" - "@ - ash\\t%2,%0 - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) -; Default to int16 data attr. - -(define_insn "ashlqi3_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,?c") - (ashift:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>") - (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")))] - "valid_operands (ASHIFT, operands, QImode)" - "@ - ash\\t%2,%0 - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary")]) -; Default to int16 data attr. - -(define_split - [(set (match_operand:QI 0 "std_reg_operand" "") - (ashift:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(set (match_dup 0) - (ashift:QI (match_dup 1) - (match_dup 2)))] - "") - -; This is only used by lshrhi3_reg where we need a LSH insn that will -; shift both ways. -(define_insn "*lshlqi3_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (ashift:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>,0,rR,rS<>") - (unspec:QI [(match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>")] UNSPEC_LSH))) - (clobber (reg:CC 21))] - "valid_operands (ASHIFT, operands, QImode)" - "@ - lsh\\t%2,%0 - lsh3\\t%2,%1,%0 - lsh3\\t%2,%1,%0 - lsh\\t%2,%0 - lsh3\\t%2,%1,%0 - lsh3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -; -; LSH (right) -; -; Logical right shift on the C[34]x works by negating the shift count, -; then emitting a right shift with the shift count negated. This means -; that all actual shift counts in the RTL will be positive. -; -(define_expand "lshrqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (LSHIFTRT, operands, QImode);") - - -(define_insn "*lshrqi3_24_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "mr,mr") - (const_int 24))) - (clobber (reg:CC 21))] - "! TARGET_C3X" - "lbu3\\t%1,%0" - [(set_attr "type" "unarycc")]) - - -(define_insn "*ashrqi3_24_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "mr,mr") - (const_int 24))) - (clobber (reg:CC 21))] - "! TARGET_C3X" - "lb3\\t%1,%0" - [(set_attr "type" "unarycc")]) - - -(define_insn "lshrqi3_16_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "mr,mr") - (const_int 16))) - (clobber (reg:CC 21))] - "! TARGET_C3X" - "lhu1\\t%1,%0" - [(set_attr "type" "unarycc")]) - - -(define_insn "*ashrqi3_16_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "mr,mr") - (const_int 16))) - (clobber (reg:CC 21))] - "! TARGET_C3X" - "lh1\\t%1,%0" - [(set_attr "type" "unarycc")]) - - -; When the shift count is greater than the size of the word -; the result can be implementation specific -(define_insn "*lshrqi3_const_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c,?d,?c") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "0,0,r,r") - (match_operand:QI 2 "const_int_operand" "n,n,J,J"))) - (clobber (reg:CC 21))] - "valid_operands (LSHIFTRT, operands, QImode)" - "@ - lsh\\t%n2,%0 - lsh\\t%n2,%0 - lsh3\\t%n2,%1,%0 - lsh3\\t%n2,%1,%0" - [(set_attr "type" "binarycc,binary,binarycc,binary")]) - -(define_insn "*lshrqi3_const_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,?c") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "0,r") - (match_operand:QI 2 "const_int_operand" "n,J")))] - "valid_operands (LSHIFTRT, operands, QImode)" - "@ - lsh\\t%n2,%0 - lsh3\\t%n2,%1,%0" - [(set_attr "type" "binary,binary")]) - -; When the shift count is greater than the size of the word -; the result can be implementation specific -(define_insn "*lshrqi3_const_set" - [(set (reg:CC 21) - (compare:CC - (lshiftrt:QI (match_operand:QI 1 "src_operand" "0,r") - (match_operand:QI 2 "const_int_operand" "n,J")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=?d,d") - (lshiftrt:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (LSHIFTRT, operands, QImode)" - "@ - lsh\\t%n2,%0 - lsh3\\t%n2,%1,%0" - [(set_attr "type" "binarycc,binarycc")]) - -(define_insn "*lshrqi3_nonconst_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>,0,rR,rS<>") - (neg:QI (match_operand:QI 2 "src_operand" "rm,R,rS<>,rm,R,rS<>")))) - (clobber (reg:CC 21))] - "valid_operands (LSHIFTRT, operands, QImode)" - "@ - lsh\\t%2,%0 - lsh3\\t%2,%1,%0 - lsh3\\t%2,%1,%0 - lsh\\t%2,%0 - lsh3\\t%2,%1,%0 - lsh3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*lshrqi3_nonconst_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,?c") - (lshiftrt:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>") - (neg:QI (match_operand:QI 2 "src_operand" "rm,R,rS<>"))))] - "valid_operands (LSHIFTRT, operands, QImode)" - "@ - lsh\\t%2,%0 - lsh3\\t%2,%1,%0 - lsh3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary")]) -; Default to int16 data attr. - -; -; ASH (right) -; -; Arithmetic right shift on the C[34]x works by negating the shift count, -; then emitting a right shift with the shift count negated. This means -; that all actual shift counts in the RTL will be positive. - -(define_expand "ashrqi3" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (ASHIFTRT, operands, QImode);") - -; When the shift count is greater than the size of the word -; the result can be implementation specific -(define_insn "*ashrqi3_const_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c,?d,?c") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "0,0,r,r") - (match_operand:QI 2 "const_int_operand" "n,n,J,J"))) - (clobber (reg:CC 21))] - "valid_operands (ASHIFTRT, operands, QImode)" - "@ - ash\\t%n2,%0 - ash\\t%n2,%0 - ash3\\t%n2,%1,%0 - ash3\\t%n2,%1,%0" - [(set_attr "type" "binarycc,binary,binarycc,binary")]) - -(define_insn "*ashrqi3_const_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,?c") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "0,r") - (match_operand:QI 2 "const_int_operand" "n,J")))] - "valid_operands (ASHIFTRT, operands, QImode)" - "@ - ash\\t%n2,%0 - ash3\\t%n2,%1,%0" - [(set_attr "type" "binarycc,binarycc")]) - -; When the shift count is greater than the size of the word -; the result can be implementation specific -(define_insn "*ashrqi3_const_set" - [(set (reg:CC 21) - (compare:CC - (ashiftrt:QI (match_operand:QI 1 "src_operand" "0,r") - (match_operand:QI 2 "const_int_operand" "n,J")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=?d,d") - (ashiftrt:QI (match_dup 1) - (match_dup 2)))] - "valid_operands (ASHIFTRT, operands, QImode)" - "@ - ash\\t%n2,%0 - ash3\\t%n2,%1,%0" - [(set_attr "type" "binarycc,binarycc")]) - -(define_insn "*ashrqi3_nonconst_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>,0,rR,rS<>") - (neg:QI (match_operand:QI 2 "src_operand" "rm,R,rS<>,rm,R,rS<>")))) - (clobber (reg:CC 21))] - "valid_operands (ASHIFTRT, operands, QImode)" - "@ - ash\\t%2,%0 - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0 - ash\\t%2,%0 - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binary,binary,binary")]) -; Default to int16 data attr. - -(define_insn "*ashrqi3_nonconst_noclobber" - [(set (match_operand:QI 0 "std_reg_operand" "=c,c,?c") - (ashiftrt:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>") - (neg:QI (match_operand:QI 2 "src_operand" "rm,R,rS<>"))))] - "valid_operands (ASHIFTRT, operands, QImode)" - "@ - ash\\t%2,%0 - ash3\\t%2,%1,%0 - ash3\\t%2,%1,%0" - [(set_attr "type" "binary,binary,binary")]) -; Default to int16 data attr. - -; -; CMPI -; -; Unfortunately the C40 doesn't allow cmpi3 7, *ar0++ so the next best -; thing would be to get the small constant loaded into a register (say r0) -; so that it could be hoisted out of the loop so that we only -; would need to do cmpi3 *ar0++, r0. Now the loop optimization pass -; comes before the flow pass (which finds autoincrements) so we're stuck. -; Ideally, GCC requires another loop optimization pass (preferably after -; reload) so that it can hoist invariants out of loops. -; The current solution modifies legitimize_operands () so that small -; constants are forced into a pseudo register. -; -(define_expand "cmpqi" - [(set (reg:CC 21) - (compare:CC (match_operand:QI 0 "src_operand" "") - (match_operand:QI 1 "src_operand" "")))] - "" - "legitimize_operands (COMPARE, operands, QImode); - c4x_compare_op0 = operands[0]; - c4x_compare_op1 = operands[1]; - DONE;") - -(define_insn "*cmpqi_test" - [(set (reg:CC 21) - (compare:CC (match_operand:QI 0 "src_operand" "r,rR,rS<>") - (match_operand:QI 1 "src_operand" "rIm,JR,rS<>")))] - "valid_operands (COMPARE, operands, QImode)" - "@ - cmpi\\t%1,%0 - cmpi3\\t%1,%0 - cmpi3\\t%1,%0" - [(set_attr "type" "compare,compare,compare")]) - -(define_insn "*cmpqi_test_noov" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:QI 0 "src_operand" "r,rR,rS<>") - (match_operand:QI 1 "src_operand" "rIm,JR,rS<>")))] - "valid_operands (COMPARE, operands, QImode)" - "@ - cmpi\\t%1,%0 - cmpi3\\t%1,%0 - cmpi3\\t%1,%0" - [(set_attr "type" "compare,compare,compare")]) - - -; -; BIT-FIELD INSTRUCTIONS -; - -; -; LBx/LHw (C4x only) -; -(define_expand "extv" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (sign_extract:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "const_int_operand" "") - (match_operand:QI 3 "const_int_operand" ""))) - (clobber (reg:CC 21))])] - "! TARGET_C3X" - "if ((INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16) - || (INTVAL (operands[3]) % INTVAL (operands[2]) != 0)) - FAIL; - ") - -(define_insn "*extv_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (sign_extract:QI (match_operand:QI 1 "src_operand" "rLm,rLm") - (match_operand:QI 2 "const_int_operand" "n,n") - (match_operand:QI 3 "const_int_operand" "n,n"))) - (clobber (reg:CC 21))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lb%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lh%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc,binary") - (set_attr "data" "int16,int16")]) - -(define_insn "*extv_clobber_test" - [(set (reg:CC 21) - (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "rLm") - (match_operand:QI 2 "const_int_operand" "n") - (match_operand:QI 3 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lb%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lh%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "int16")]) - -(define_insn "*extv_clobber_set" - [(set (reg:CC 21) - (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "rLm") - (match_operand:QI 2 "const_int_operand" "n") - (match_operand:QI 3 "const_int_operand" "n")) - (const_int 0))) - (set (match_operand:QI 0 "reg_operand" "=d") - (sign_extract:QI (match_dup 1) - (match_dup 2) - (match_dup 3)))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lb%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lh%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "int16")]) - -; -; LBUx/LHUw (C4x only) -; -(define_expand "extzv" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (zero_extract:QI (match_operand:QI 1 "src_operand" "") - (match_operand:QI 2 "const_int_operand" "") - (match_operand:QI 3 "const_int_operand" ""))) - (clobber (reg:CC 21))])] - "! TARGET_C3X" - "if ((INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16) - || (INTVAL (operands[3]) % INTVAL (operands[2]) != 0)) - FAIL; - ") - -(define_insn "*extzv_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (zero_extract:QI (match_operand:QI 1 "src_operand" "rLm,rLm") - (match_operand:QI 2 "const_int_operand" "n,n") - (match_operand:QI 3 "const_int_operand" "n,n"))) - (clobber (reg:CC 21))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lbu%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lhu%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc,binary") - (set_attr "data" "uint16,uint16")]) - -(define_insn "*extzv_test" - [(set (reg:CC 21) - (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "rLm") - (match_operand:QI 2 "const_int_operand" "n") - (match_operand:QI 3 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:QI 0 "=d"))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lbu%3\\t%1,%0\"; - } - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lhu%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "uint16")]) - -(define_insn "*extzv_set" - [(set (reg:CC 21) - (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "rLm") - (match_operand:QI 2 "const_int_operand" "n") - (match_operand:QI 3 "const_int_operand" "n")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (zero_extract:QI (match_dup 1) - (match_dup 2) - (match_dup 3)))] - "! TARGET_C3X - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && (INTVAL (operands[3]) % INTVAL (operands[2]) == 0)" - "* - if (INTVAL (operands[2]) == 8) - { - /* 8 bit extract. */ - operands[3] = GEN_INT (INTVAL (operands[3]) / 8); - return \"lbu%3\\t%1,%0\"; - } - /* 16 bit extract. */ - operands[3] = GEN_INT (INTVAL (operands[3]) / 16); - return \"lhu%3\\t%1,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "uint16")]) - -; -; MBx/MHw (C4x only) -; -(define_expand "insv" - [(parallel [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "const_int_operand" "") - (match_operand:QI 2 "const_int_operand" "")) - (match_operand:QI 3 "src_operand" "")) - (clobber (reg:CC 21))])] - "! TARGET_C3X" - "if (! (((INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) - && (INTVAL (operands[2]) % INTVAL (operands[1]) == 0)) - || (INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8))) - FAIL; - ") - -(define_insn "*insv_clobber" - [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "+d,c") - (match_operand:QI 1 "const_int_operand" "n,n") - (match_operand:QI 2 "const_int_operand" "n,n")) - (match_operand:QI 3 "src_operand" "rLm,rLm")) - (clobber (reg:CC 21))] - "! TARGET_C3X - && (((INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) - && (INTVAL (operands[2]) % INTVAL (operands[1]) == 0)) - || (INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8))" - "* - if (INTVAL (operands[1]) == 8) - { - /* 8 bit insert. */ - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); - return \"mb%2\\t%3,%0\"; - } - else if (INTVAL (operands[1]) == 16) - { - /* 16 bit insert. */ - operands[2] = GEN_INT (INTVAL (operands[2]) / 16); - return \"mh%2\\t%3,%0\"; - } - /* 24 bit insert. */ - return \"lwl1\\t%3,%0\"; - " - [(set_attr "type" "binarycc,binary") - (set_attr "data" "uint16,uint16")]) - -(define_peephole - [(parallel [(set (zero_extract:QI (match_operand:QI 0 "ext_reg_operand" "+d") - (match_operand:QI 1 "const_int_operand" "n") - (match_operand:QI 2 "const_int_operand" "n")) - (match_operand:QI 3 "src_operand" "rLm")) - (clobber (reg:CC 21))]) - (set (reg:CC 21) - (compare:CC (match_dup 0) (const_int 0)))] - "! TARGET_C3X - && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) - && (INTVAL (operands[2]) % INTVAL (operands[1]) == 0)" - "* - if (INTVAL (operands[1]) == 8) - { - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); - return \"mb%2\\t%3,%0\"; - } - operands[2] = GEN_INT (INTVAL (operands[2]) / 16); - return \"mh%2\\t%3,%0\"; - " - [(set_attr "type" "binarycc") - (set_attr "data" "uint16")]) - - -; TWO OPERAND FLOAT INSTRUCTIONS -; - -; -; LDF/STF -; -; If one of the operands is not a register, then we should -; emit two insns, using a scratch register. This will produce -; better code in loops if the source operand is invariant, since -; the source reload can be optimized out. During reload we cannot -; use change_address or force_reg. -(define_expand "movqf" - [(set (match_operand:QF 0 "src_operand" "") - (match_operand:QF 1 "src_operand" ""))] - "" - " -{ - if (c4x_emit_move_sequence (operands, QFmode)) - DONE; -}") - -; This can generate invalid stack slot displacements -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (unspec:QI [(match_operand:QF 1 "reg_operand" "")] UNSPEC_STOREQF_INT))] - "reload_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 0) (match_dup 2))] - "operands[2] = assign_stack_temp (QImode, GET_MODE_SIZE (QImode), 0); - operands[3] = copy_rtx (operands[2]); - PUT_MODE (operands[3], QFmode);") - - -(define_insn "storeqf_int" - [(set (match_operand:QI 0 "reg_operand" "=r") - (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] UNSPEC_STOREQF_INT))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (unspec:QI [(match_operand:QF 1 "reg_operand" "")] UNSPEC_STOREQF_INT)) - (clobber (reg:CC 21))])] - "reload_completed" - [(set (mem:QF (pre_inc:QI (reg:QI 20))) - (match_dup 1)) - (parallel [(set (match_dup 0) - (mem:QI (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))])] - "") - - -; We need accurate death notes for this... -;(define_peephole -; [(set (match_operand:QF 0 "reg_operand" "=f") -; (match_operand:QF 1 "memory_operand" "m")) -; (set (mem:QF (pre_inc:QI (reg:QI 20))) -; (match_dup 0)) -; (parallel [(set (match_operand:QI 2 "reg_operand" "r") -; (mem:QI (post_dec:QI (reg:QI 20)))) -; (clobber (reg:CC 21))])] -; "" -; "ldiu\\t%1,%0") - -(define_insn "storeqf_int_clobber" - [(parallel [(set (match_operand:QI 0 "reg_operand" "=r") - (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] UNSPEC_STOREQF_INT)) - (clobber (reg:CC 21))])] - "" - "#" - [(set_attr "type" "multi")]) - - -; This can generate invalid stack slot displacements -(define_split - [(set (match_operand:QF 0 "reg_operand" "") - (unspec:QF [(match_operand:QI 1 "reg_operand" "")] UNSPEC_LOADQF_INT))] - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 0) (match_dup 3))] - "operands[2] = assign_stack_temp (QImode, GET_MODE_SIZE (QImode), 0); - operands[3] = copy_rtx (operands[2]); - PUT_MODE (operands[3], QFmode);") - - -(define_insn "loadqf_int" - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] UNSPEC_LOADQF_INT))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (unspec:QF [(match_operand:QI 1 "reg_operand" "")] UNSPEC_LOADQF_INT)) - (clobber (reg:CC 21))])] - "reload_completed" - [(set (mem:QI (pre_inc:QI (reg:QI 20))) - (match_dup 1)) - (parallel [(set (match_dup 0) - (mem:QF (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))])] - "") - -(define_insn "loadqf_int_clobber" - [(parallel [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] UNSPEC_LOADQF_INT)) - (clobber (reg:CC 21))])] - "" - "#" - [(set_attr "type" "multi")]) - -; We must provide an alternative to store to memory in case we have to -; spill a register. -(define_insn "movqf_noclobber" - [(set (match_operand:QF 0 "dst_operand" "=f,m") - (match_operand:QF 1 "src_operand" "fHm,f"))] - "REG_P (operands[0]) || REG_P (operands[1])" - "@ - ldfu\\t%1,%0 - stf\\t%1,%0" - [(set_attr "type" "unary,store")]) - -;(define_insn "*movqf_clobber" -; [(set (match_operand:QF 0 "reg_operand" "=f") -; (match_operand:QF 1 "src_operand" "fHm")) -; (clobber (reg:CC 21))] -; "0" -; "ldf\\t%1,%0" -; [(set_attr "type" "unarycc")]) - -(define_insn "*movqf_test" - [(set (reg:CC 21) - (compare:CC (match_operand:QF 1 "src_operand" "fHm") - (const_int 0))) - (clobber (match_scratch:QF 0 "=f"))] - "" - "ldf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*movqf_set" - [(set (reg:CC 21) - (compare:CC (match_operand:QF 1 "src_operand" "fHm") - (match_operand:QF 2 "fp_zero_operand" "G"))) - (set (match_operand:QF 0 "reg_operand" "=f") - (match_dup 1))] - "" - "ldf\\t%1,%0" - [(set_attr "type" "unarycc")]) - - -(define_insn "*movqf_parallel" - [(set (match_operand:QF 0 "parallel_operand" "=q,S<>!V,q,S<>!V") - (match_operand:QF 1 "parallel_operand" "S<>!V,q,S<>!V,q")) - (set (match_operand:QF 2 "parallel_operand" "=q,S<>!V,S<>!V,q") - (match_operand:QF 3 "parallel_operand" "S<>!V,q,q,S<>!V"))] - "TARGET_PARALLEL && valid_parallel_load_store (operands, QFmode)" - "@ - ldf1\\t%1,%0\\n||\\tldf2\\t%3,%2 - stf1\\t%1,%0\\n||\\tstf2\\t%3,%2 - ldf\\t%1,%0\\n||\\tstf\\t%3,%2 - ldf\\t%3,%2\\n||\\tstf\\t%1,%0" - [(set_attr "type" "load_load,store_store,load_store,store_load")]) - - -; -; PUSH/POP -; -(define_insn "pushqf" - [(set (mem:QF (pre_inc:QI (reg:QI 20))) - (match_operand:QF 0 "reg_operand" "f"))] - "" - "pushf\\t%0" - [(set_attr "type" "push")]) - -(define_insn "popqf" - [(set (match_operand:QF 0 "reg_operand" "=f") - (mem:QF (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))] - "" - "popf\\t%0" - [(set_attr "type" "pop")]) - -(define_insn "popqf_unspec" - [(set (unspec:QF [(match_operand:QF 0 "reg_operand" "=f")] UNSPEC_POPQF) - (mem:QF (post_dec:QI (reg:QI 20)))) - (clobber (match_dup 0)) - (clobber (reg:CC 21))] - "" - "popf\\t%0" - [(set_attr "type" "pop")]) - -; -; ABSF -; -(define_expand "absqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (abs:QF (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] -"" -"") - -(define_insn "*absqf2_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (abs:QF (match_operand:QF 1 "src_operand" "fHm"))) - (clobber (reg:CC_NOOV 21))] - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*absqf2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fHm")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (clobber (match_scratch:QF 0 "=f"))] - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*absqf2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fHm")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (set (match_operand:QF 0 "reg_operand" "=f") - (abs:QF (match_dup 1)))] - - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; NEGF -; -(define_expand "negqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (neg:QF (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] -"" -"") - -(define_insn "*negqf2_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (neg:QF (match_operand:QF 1 "src_operand" "fHm"))) - (clobber (reg:CC_NOOV 21))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*negqf2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fHm")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (clobber (match_scratch:QF 0 "=f"))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*negqf2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fHm")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (set (match_operand:QF 0 "reg_operand" "=f") - (neg:QF (match_dup 1)))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; FLOAT -; -(define_insn "floatqiqf2" - [(set (match_operand:QF 0 "reg_operand" "=f") - (float:QF (match_operand:QI 1 "src_operand" "rIm"))) - (clobber (reg:CC 21))] - "" - "float\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*floatqiqf2_set" - [(set (reg:CC 21) - (compare:CC (float:QF (match_operand:QI 1 "src_operand" "rIm")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (set (match_operand:QF 0 "reg_operand" "=f") - (float:QF (match_dup 1)))] - "" - "float\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; Unsigned conversions are a little tricky because we need to -; add the value for the high bit if necessary. -; -; -(define_expand "floatunsqiqf2" - [(set (match_dup 2) (match_dup 3)) - (parallel [(set (reg:CC 21) - (compare:CC (float:QF (match_operand:QI 1 "src_operand" "")) - (match_dup 3))) - (set (match_dup 4) - (float:QF (match_dup 1)))]) - (set (match_dup 2) - (if_then_else:QF (lt (reg:CC 21) (const_int 0)) - (match_dup 5) - (match_dup 2))) - (parallel [(set (match_operand:QF 0 "reg_operand" "") - (plus:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))])] - "" - "operands[2] = gen_reg_rtx (QFmode); - operands[3] = CONST0_RTX (QFmode); - operands[4] = gen_reg_rtx (QFmode); - operands[5] = gen_reg_rtx (QFmode); - emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", QFmode));") - -(define_expand "floatunsqihf2" - [(set (match_dup 2) (match_dup 3)) - (parallel [(set (reg:CC 21) - (compare:CC (float:HF (match_operand:QI 1 "src_operand" "")) - (match_dup 3))) - (set (match_dup 4) - (float:HF (match_dup 1)))]) - (set (match_dup 2) - (if_then_else:HF (lt (reg:CC 21) (const_int 0)) - (match_dup 5) - (match_dup 2))) - (parallel [(set (match_operand:HF 0 "reg_operand" "") - (plus:HF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))])] - "" - "operands[2] = gen_reg_rtx (HFmode); - operands[3] = CONST0_RTX (HFmode); - operands[4] = gen_reg_rtx (HFmode); - operands[5] = gen_reg_rtx (HFmode); - emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", HFmode));") - -(define_insn "floatqihf2" - [(set (match_operand:HF 0 "reg_operand" "=h") - (float:HF (match_operand:QI 1 "src_operand" "rIm"))) - (clobber (reg:CC 21))] - "" - "float\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*floatqihf2_set" - [(set (reg:CC 21) - (compare:CC (float:HF (match_operand:QI 1 "src_operand" "rIm")) - (match_operand:QF 2 "fp_zero_operand" "G"))) - (set (match_operand:HF 0 "reg_operand" "=h") - (float:HF (match_dup 1)))] - "" - "float\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; FIX -; -(define_insn "fixqfqi_clobber" - [(set (match_operand:QI 0 "reg_operand" "=d,c") - (fix:QI (match_operand:QF 1 "src_operand" "fHm,fHm"))) - (clobber (reg:CC 21))] - "" - "fix\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*fixqfqi_set" - [(set (reg:CC 21) - (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fHm")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (fix:QI (match_dup 1)))] - "" - "fix\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; The C[34]x fix instruction implements a floor, not a straight trunc, -; so we have to invert the number, fix it, and reinvert it if negative -; -(define_expand "fix_truncqfqi2" - [(parallel [(set (match_dup 2) - (fix:QI (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 3) (neg:QF (match_dup 1))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (fix:QI (match_dup 3))) - (clobber (reg:CC 21))]) - (parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_dup 4)) (const_int 0))) - (set (match_dup 5) (neg:QI (match_dup 4)))]) - (set (match_dup 2) - (if_then_else:QI (le (reg:CC 21) (const_int 0)) - (match_dup 5) - (match_dup 2))) - (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 2))] - "" - "if (TARGET_FAST_FIX) - { - emit_insn (gen_fixqfqi_clobber (operands[0], operands[1])); - DONE; - } - operands[2] = gen_reg_rtx (QImode); - operands[3] = gen_reg_rtx (QFmode); - operands[4] = gen_reg_rtx (QImode); - operands[5] = gen_reg_rtx (QImode); - ") - -(define_expand "fix_truncqfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (fix:HI (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (fix_truncqfhi2_libfunc, FIX, HImode, QFmode, 2, operands); - DONE;") - -(define_expand "fixuns_truncqfqi2" - [(parallel [(set (match_dup 2) - (fix:QI (match_operand:QF 1 "src_operand" "fHm"))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 3) - (minus:QF (match_dup 1) (match_dup 5))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (reg:CC 21) - (compare:CC (fix:QI (match_dup 3)) - (const_int 0))) - (set (match_dup 4) - (fix:QI (match_dup 3)))]) - (parallel [(set (match_dup 4) (unspec:QI [(match_dup 2)] UNSPEC_LDIV)) - (use (reg:CC 21))]) - (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 4))] - "" - "operands[2] = gen_reg_rtx (QImode); - operands[3] = gen_reg_rtx (QFmode); - operands[4] = gen_reg_rtx (QImode); - operands[5] = gen_reg_rtx (QFmode); - emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", QFmode));") - -(define_expand "fixuns_truncqfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (unsigned_fix:HI (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (fixuns_truncqfhi2_libfunc, UNSIGNED_FIX, - HImode, QFmode, 2, operands); - DONE;") - -; -; RCPF -; -(define_insn "rcpfqf_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_RCPF)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rcpf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RSQRF -; -(define_insn "*rsqrfqf_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_RSQRF)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rsqrf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RNDF -; -(define_insn "*rndqf_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_RND)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rnd\\t%1,%0" - [(set_attr "type" "unarycc")]) - - -; Inlined float square root for C4x -(define_expand "sqrtqf2_inline" - [(parallel [(set (match_dup 2) - (unspec:QF [(match_operand:QF 1 "src_operand" "")] UNSPEC_RSQRF)) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:QF (match_dup 5) (match_dup 1))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:QF (match_dup 6) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 2) (mult:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:QF (match_dup 6) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 2) (mult:QF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 1))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:QF 0 "reg_operand" "") - (unspec:QF [(match_dup 4)] UNSPEC_RND)) - (clobber (reg:CC_NOOV 21))])] - "! TARGET_C3X" - "if (! reload_in_progress - && ! reg_operand (operands[1], QFmode)) - operands[1] = force_reg (QFmode, operands[1]); - operands[2] = gen_reg_rtx (QFmode); - operands[3] = gen_reg_rtx (QFmode); - operands[4] = gen_reg_rtx (QFmode); - operands[5] = CONST_DOUBLE_ATOF (\"0.5\", QFmode); - operands[6] = CONST_DOUBLE_ATOF (\"1.5\", QFmode);") - -(define_expand "sqrtqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (sqrt:QF (match_operand:QF 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "! TARGET_C3X && TARGET_INLINE" - "emit_insn (gen_sqrtqf2_inline (operands[0], operands[1])); - DONE;") - -; -; TOIEEE / FRIEEE -; -(define_insn "toieee" - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_TOIEEE)) - (clobber (reg:CC 21))] - "" - "toieee\\t%1,%0") - -(define_insn "frieee" - [(set (match_operand:QF 0 "reg_operand" "=f") - (unspec:QF [(match_operand:QF 1 "memory_operand" "m")] UNSPEC_FRIEEE)) - (clobber (reg:CC 21))] - "" - "frieee\\t%1,%0") - -; -; THREE OPERAND FLOAT INSTRUCTIONS -; - -; -; ADDF -; -(define_expand "addqf3" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (plus:QF (match_operand:QF 1 "src_operand" "") - (match_operand:QF 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (PLUS, operands, QFmode);") - -(define_insn "*addqf3_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f,f,?f") - (plus:QF (match_operand:QF 1 "src_operand" "%0,fR,fS<>") - (match_operand:QF 2 "src_operand" "fHm,R,fS<>"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (PLUS, operands, QFmode)" - "@ - addf\\t%2,%0 - addf3\\t%2,%1,%0 - addf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*addqf3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%0,fR,fS<>") - (match_operand:QF 2 "src_operand" "fHm,R,fS<>")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) - (clobber (match_scratch:QF 0 "=f,f,?f"))] - "valid_operands (PLUS, operands, QFmode)" - "@ - addf\\t%2,%0 - addf3\\t%2,%1,%0 - addf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*addqf3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%0,fR,fS<>") - (match_operand:QF 2 "src_operand" "fHm,R,fS<>")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) - (set (match_operand:QF 0 "reg_operand" "=f,f,?f") - (plus:QF (match_dup 1) - (match_dup 2)))] - "valid_operands (PLUS, operands, QFmode)" - "@ - addf\\t%2,%0 - addf3\\t%2,%1,%0 - addf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -; -; SUBF/SUBRF -; -(define_expand "subqf3" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (minus:QF (match_operand:QF 1 "src_operand" "") - (match_operand:QF 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MINUS, operands, QFmode);") - -(define_insn "*subqf3_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f,f,f,?f") - (minus:QF (match_operand:QF 1 "src_operand" "0,fHm,fR,fS<>") - (match_operand:QF 2 "src_operand" "fHm,0,R,fS<>"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, QFmode)" - "@ - subf\\t%2,%0 - subrf\\t%1,%0 - subf3\\t%2,%1,%0 - subf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -(define_insn "*subqf3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "0,fHm,fR,fS<>") - (match_operand:QF 2 "src_operand" "fHm,0,R,fS<>")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G,G"))) - (clobber (match_scratch:QF 0 "=f,f,f,?f"))] - "valid_operands (MINUS, operands, QFmode)" - "@ - subf\\t%2,%0 - subrf\\t%1,%0 - subf3\\t%2,%1,%0 - subf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -(define_insn "*subqf3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "0,fHm,fR,fS<>") - (match_operand:QF 2 "src_operand" "fHm,0,R,fS<>")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G,G"))) - (set (match_operand:QF 0 "reg_operand" "=f,f,f,?f") - (minus:QF (match_dup 1) - (match_dup 2)))] - "valid_operands (MINUS, operands, QFmode)" - "@ - subf\\t%2,%0 - subrf\\t%1,%0 - subf3\\t%2,%1,%0 - subf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - -; -; MPYF -; -(define_expand "mulqf3" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (mult:QF (match_operand:QF 1 "src_operand" "") - (match_operand:QF 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MULT, operands, QFmode);") - -(define_insn "*mulqf3_clobber" - [(set (match_operand:QF 0 "reg_operand" "=f,f,?f") - (mult:QF (match_operand:QF 1 "src_operand" "%0,fR,fS<>") - (match_operand:QF 2 "src_operand" "fHm,R,fS<>"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MULT, operands, QFmode)" - "@ - mpyf\\t%2,%0 - mpyf3\\t%2,%1,%0 - mpyf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*mulqf3_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%0,fR,fS<>") - (match_operand:QF 2 "src_operand" "fHm,R,fS<>")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) - (clobber (match_scratch:QF 0 "=f,f,?f"))] - "valid_operands (MULT, operands, QFmode)" - "@ - mpyf\\t%2,%0 - mpyf3\\t%2,%1,%0 - mpyf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -(define_insn "*mulqf3_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%0,fR,fS<>") - (match_operand:QF 2 "src_operand" "fHm,R,fS<>")) - (match_operand:QF 3 "fp_zero_operand" "G,G,G"))) - (set (match_operand:QF 0 "reg_operand" "=f,f,?f") - (mult:QF (match_dup 1) - (match_dup 2)))] - "valid_operands (MULT, operands, QFmode)" - "@ - mpyf\\t%2,%0 - mpyf3\\t%2,%1,%0 - mpyf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -; -; CMPF -; -(define_expand "cmpqf" - [(set (reg:CC 21) - (compare:CC (match_operand:QF 0 "src_operand" "") - (match_operand:QF 1 "src_operand" "")))] - "" - "legitimize_operands (COMPARE, operands, QFmode); - c4x_compare_op0 = operands[0]; - c4x_compare_op1 = operands[1]; - DONE;") - -(define_insn "*cmpqf" - [(set (reg:CC 21) - (compare:CC (match_operand:QF 0 "src_operand" "f,fR,fS<>") - (match_operand:QF 1 "src_operand" "fHm,R,fS<>")))] - "valid_operands (COMPARE, operands, QFmode)" - "@ - cmpf\\t%1,%0 - cmpf3\\t%1,%0 - cmpf3\\t%1,%0" - [(set_attr "type" "compare,compare,compare")]) - -(define_insn "*cmpqf_noov" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:QF 0 "src_operand" "f,fR,fS<>") - (match_operand:QF 1 "src_operand" "fHm,R,fS<>")))] - "valid_operands (COMPARE, operands, QFmode)" - "@ - cmpf\\t%1,%0 - cmpf3\\t%1,%0 - cmpf3\\t%1,%0" - [(set_attr "type" "compare,compare,compare")]) - -; Inlined float divide for C4x -(define_expand "divqf3_inline" - [(parallel [(set (match_dup 3) - (unspec:QF [(match_operand:QF 2 "src_operand" "")] UNSPEC_RCPF)) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:QF (match_dup 5) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:QF (match_dup 3) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:QF (match_dup 5) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:QF (match_dup 3) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) - (mult:QF (match_operand:QF 1 "src_operand" "") - (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:QF 0 "reg_operand" "") - (unspec:QF [(match_dup 3)] UNSPEC_RND)) - (clobber (reg:CC_NOOV 21))])] - "! TARGET_C3X" - "if (! reload_in_progress - && ! reg_operand (operands[2], QFmode)) - operands[2] = force_reg (QFmode, operands[2]); - operands[3] = gen_reg_rtx (QFmode); - operands[4] = gen_reg_rtx (QFmode); - operands[5] = CONST2_RTX (QFmode);") - -(define_expand "divqf3" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (div:QF (match_operand:QF 1 "src_operand" "") - (match_operand:QF 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "! TARGET_C3X && TARGET_INLINE" - "emit_insn (gen_divqf3_inline (operands[0], operands[1], operands[2])); - DONE;") - -; -; CONDITIONAL MOVES -; - -; ??? We should make these pattern fail if the src operand combination -; is not valid. Although reload will fix things up, it will introduce -; extra load instructions that won't be hoisted out of a loop. - -(define_insn "*ldi_conditional" - [(set (match_operand:QI 0 "reg_operand" "=r,r") - (if_then_else:QI (match_operator 1 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (match_operand:QI 2 "src_operand" "rIm,0") - (match_operand:QI 3 "src_operand" "0,rIm")))] - "valid_operands (IF_THEN_ELSE, operands, QImode)" - "@ - ldi%1\\t%2,%0 - ldi%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -(define_insn "*ldi_conditional_noov" - [(set (match_operand:QI 0 "reg_operand" "=r,r") - (if_then_else:QI (match_operator 1 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (match_operand:QI 2 "src_operand" "rIm,0") - (match_operand:QI 3 "src_operand" "0,rIm")))] - "GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE - && GET_CODE (operands[1]) != LT - && GET_CODE (operands[1]) != GT - && valid_operands (IF_THEN_ELSE, operands, QImode)" - "@ - ldi%1\\t%2,%0 - ldi%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -(define_insn "*ldi_on_overflow" - [(set (match_operand:QI 0 "reg_operand" "=r") - (unspec:QI [(match_operand:QI 1 "src_operand" "rIm")] UNSPEC_LDIV)) - (use (reg:CC 21))] - "" - "ldiv\\t%1,%0" - [(set_attr "type" "unary")]) - -; Move operand 2 to operand 0 if condition (operand 1) is true -; else move operand 3 to operand 0. -; The temporary register is required below because some of the operands -; might be identical (namely 0 and 2). -; -(define_expand "movqicc" - [(set (match_operand:QI 0 "reg_operand" "") - (if_then_else:QI (match_operand 1 "comparison_operator" "") - (match_operand:QI 2 "src_operand" "") - (match_operand:QI 3 "src_operand" "")))] - "" - "{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1); - if (ccreg == NULL_RTX) FAIL; - emit_insn (gen_rtx_SET (QImode, operands[0], - gen_rtx_IF_THEN_ELSE (QImode, - gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx), - operands[2], operands[3]))); - DONE;}") - -(define_insn "*ldf_conditional" - [(set (match_operand:QF 0 "reg_operand" "=f,f") - (if_then_else:QF (match_operator 1 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (match_operand:QF 2 "src_operand" "fHm,0") - (match_operand:QF 3 "src_operand" "0,fHm")))] - "valid_operands (IF_THEN_ELSE, operands, QFmode)" - "@ - ldf%1\\t%2,%0 - ldf%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -(define_insn "*ldf_conditional_noov" - [(set (match_operand:QF 0 "reg_operand" "=f,f") - (if_then_else:QF (match_operator 1 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (match_operand:QF 2 "src_operand" "fHm,0") - (match_operand:QF 3 "src_operand" "0,fHm")))] - "GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE - && GET_CODE (operands[1]) != LT - && GET_CODE (operands[1]) != GT - && valid_operands (IF_THEN_ELSE, operands, QFmode)" - "@ - ldf%1\\t%2,%0 - ldf%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -(define_expand "movqfcc" - [(set (match_operand:QF 0 "reg_operand" "") - (if_then_else:QF (match_operand 1 "comparison_operator" "") - (match_operand:QF 2 "src_operand" "") - (match_operand:QF 3 "src_operand" "")))] - "" - "{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1); - if (ccreg == NULL_RTX) FAIL; - emit_insn (gen_rtx_SET (QFmode, operands[0], - gen_rtx_IF_THEN_ELSE (QFmode, - gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx), - operands[2], operands[3]))); - DONE;}") - -(define_insn "*ldhf_conditional" - [(set (match_operand:HF 0 "reg_operand" "=h,h") - (if_then_else:HF (match_operator 1 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (match_operand:HF 2 "src_operand" "hH,0") - (match_operand:HF 3 "src_operand" "0,hH")))] - "" - "@ - ldf%1\\t%2,%0 - ldf%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -(define_insn "*ldhf_conditional_noov" - [(set (match_operand:HF 0 "reg_operand" "=h,h") - (if_then_else:HF (match_operator 1 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (match_operand:HF 2 "src_operand" "hH,0") - (match_operand:HF 3 "src_operand" "0,hH")))] - "GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE - && GET_CODE (operands[1]) != LT - && GET_CODE (operands[1]) != GT" - "@ - ldf%1\\t%2,%0 - ldf%I1\\t%3,%0" - [(set_attr "type" "binary")]) - -(define_expand "movhfcc" - [(set (match_operand:HF 0 "reg_operand" "") - (if_then_else:HF (match_operand 1 "comparison_operator" "") - (match_operand:HF 2 "src_operand" "") - (match_operand:HF 3 "src_operand" "")))] - "" - "{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1); - if (ccreg == NULL_RTX) FAIL; - emit_insn (gen_rtx_SET (HFmode, operands[0], - gen_rtx_IF_THEN_ELSE (HFmode, - gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx), - operands[2], operands[3]))); - DONE;}") - -(define_expand "seq" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (eq (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (EQ, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "sne" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (ne (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (NE, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "slt" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (lt (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (LT, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "sltu" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (ltu (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (LTU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "sgt" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (gt (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (GT, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "sgtu" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (gtu (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (GTU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "sle" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (le (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (LE, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "sleu" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (leu (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (LEU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "sge" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (ge (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (GE, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "sgeu" - [(set (match_operand:QI 0 "reg_operand" "") - (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (geu (match_dup 1) (const_int 0)) - (const_int 1) - (match_dup 0)))] - "" - "operands[1] = c4x_gen_compare_reg (GEU, c4x_compare_op0, c4x_compare_op1);") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operator:QI 1 "comparison_operator" [(reg:CC 21) (const_int 0)]))] - "reload_completed" - [(set (match_dup 0) (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (match_op_dup 1 [(reg:CC 21) (const_int 0)]) - (const_int 1) - (match_dup 0)))] - "") - -(define_split - [(set (match_operand:QI 0 "reg_operand" "") - (match_operator:QI 1 "comparison_operator" [(reg:CC_NOOV 21) (const_int 0)]))] - "reload_completed" - [(set (match_dup 0) (const_int 0)) - (set (match_dup 0) - (if_then_else:QI (match_op_dup 1 [(reg:CC_NOOV 21) (const_int 0)]) - (const_int 1) - (match_dup 0)))] - "") - -(define_insn "*bu" - [(set (pc) - (unspec [(match_operand:QI 0 "reg_operand" "r")] UNSPEC_BU))] - "" - "bu%#\\t%0" - [(set_attr "type" "jump")]) - -(define_expand "caseqi" - [(parallel [(set (match_dup 5) - (minus:QI (match_operand:QI 0 "reg_operand" "") - (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (reg:CC 21) - (compare:CC (match_dup 5) - (match_operand:QI 2 "src_operand" ""))) - (set (pc) - (if_then_else (gtu (reg:CC 21) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (parallel [(set (match_dup 6) - (plus:QI (match_dup 5) - (label_ref:QI (match_operand 3 "" "")))) - (clobber (reg:CC_NOOV 21))]) - (set (match_dup 7) - (mem:QI (match_dup 6))) - (set (pc) (match_dup 7))] - "" - "operands[5] = gen_reg_rtx (QImode); - operands[6] = gen_reg_rtx (QImode); - operands[7] = gen_reg_rtx (QImode);") - -; -; PARALLEL FLOAT INSTRUCTIONS -; -; This patterns are under development - -; -; ABSF/STF -; - -(define_insn "*absqf2_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (abs:QF (match_operand:QF 1 "par_ind_operand" "S<>"))) - (set (match_operand:QF 2 "par_ind_operand" "=S<>") - (match_operand:QF 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC_NOOV 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" - "absf\\t%1,%0\\n||\\tstf\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; ADDF/STF -; - -(define_insn "*addqf3_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q,q") - (plus:QF (match_operand:QF 1 "parallel_operand" "%q,S<>") - (match_operand:QF 2 "parallel_operand" "S<>,q"))) - (set (match_operand:QF 3 "par_ind_operand" "=S<>,S<>") - (match_operand:QF 4 "ext_low_reg_operand" "q,q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QFmode)" - "addf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3" - [(set_attr "type" "binarycc,binarycc")]) - -; -; FLOAT/STF -; - -(define_insn "*floatqiqf2_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (float:QF (match_operand:QI 1 "par_ind_operand" "S<>"))) - (set (match_operand:QF 2 "par_ind_operand" "=S<>") - (match_operand:QF 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" - "float\\t%1,%0\\n||\\tstf\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; MPYF/ADDF -; - -(define_insn "*mulqf3_addqf3_clobber" - [(set (match_operand:QF 0 "r0r1_reg_operand" "=t,t,t,t") - (mult:QF (match_operand:QF 1 "parallel_operand" "%S<>!V,q,S<>!V,q") - (match_operand:QF 2 "parallel_operand" "q,S<>!V,S<>!V,q"))) - (set (match_operand:QF 3 "r2r3_reg_operand" "=u,u,u,u") - (plus:QF (match_operand:QF 4 "parallel_operand" "%S<>!V,q,q,S<>!V") - (match_operand:QF 5 "parallel_operand" "q,S<>!V,q,S<>!V"))) - (clobber (reg:CC_NOOV 21))] - "TARGET_PARALLEL_MPY && valid_parallel_operands_6 (operands, QFmode)" - "mpyf3\\t%2,%1,%0\\n||\\taddf3\\t%5,%4,%3" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - - -; -; MPYF/STF -; - -(define_insn "*mulqf3_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q,q") - (mult:QF (match_operand:QF 1 "parallel_operand" "%q,S<>") - (match_operand:QF 2 "parallel_operand" "S<>,q"))) - (set (match_operand:QF 3 "par_ind_operand" "=S<>,S<>") - (match_operand:QF 4 "ext_low_reg_operand" "q,q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QFmode)" - "mpyf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3" - [(set_attr "type" "binarycc,binarycc")]) - -; -; MPYF/SUBF -; - -(define_insn "*mulqf3_subqf3_clobber" - [(set (match_operand:QF 0 "r0r1_reg_operand" "=t,t") - (mult:QF (match_operand:QF 1 "parallel_operand" "S<>,q") - (match_operand:QF 2 "parallel_operand" "q,S<>"))) - (set (match_operand:QF 3 "r2r3_reg_operand" "=u,u") - (minus:QF (match_operand:QF 4 "parallel_operand" "S<>,q") - (match_operand:QF 5 "parallel_operand" "q,S<>"))) - (clobber (reg:CC 21))] - "TARGET_PARALLEL_MPY && valid_parallel_operands_6 (operands, QFmode)" - "mpyf3\\t%2,%1,%0\\n||\\tsubf3\\t%5,%4,%3" - [(set_attr "type" "binarycc,binarycc")]) - -; -; MPYF/LDF 0 -; - -(define_insn "*mulqf3_clrqf_clobber" - [(set (match_operand:QF 0 "r0r1_reg_operand" "=t") - (mult:QF (match_operand:QF 1 "par_ind_operand" "%S<>") - (match_operand:QF 2 "par_ind_operand" "S<>"))) - (set (match_operand:QF 3 "r2r3_reg_operand" "=u") - (match_operand:QF 4 "fp_zero_operand" "G")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL_MPY" - "mpyf3\\t%2,%1,%0\\n||\\tsubf3\\t%3,%3,%3" - [(set_attr "type" "binarycc")]) - -; -; NEGF/STF -; - -(define_insn "*negqf2_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (neg:QF (match_operand:QF 1 "par_ind_operand" "S<>"))) - (set (match_operand:QF 2 "par_ind_operand" "=S<>") - (match_operand:QF 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" - "negf\\t%1,%0\\n||\\tstf\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; SUBF/STF -; - -(define_insn "*subqf3_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (minus:QF (match_operand:QF 1 "ext_low_reg_operand" "q") - (match_operand:QF 2 "par_ind_operand" "S<>"))) - (set (match_operand:QF 3 "par_ind_operand" "=S<>") - (match_operand:QF 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QFmode)" - "subf3\\t%2,%1,%0\\n||\\tstf\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; TOIEEE/STF -; - -(define_insn "*toieee_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (unspec:QF [(match_operand:QF 1 "par_ind_operand" "S<>")] UNSPEC_TOIEEE)) - (set (match_operand:QF 2 "par_ind_operand" "=S<>") - (match_operand:QF 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" - "toieee\\t%1,%0\\n||\\tstf\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; FRIEEE/STF -; - -(define_insn "*frieee_movqf_clobber" - [(set (match_operand:QF 0 "ext_low_reg_operand" "=q") - (unspec:QF [(match_operand:QF 1 "par_ind_operand" "S<>")] UNSPEC_FRIEEE)) - (set (match_operand:QF 2 "par_ind_operand" "=S<>") - (match_operand:QF 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)" - "frieee\\t%1,%0\\n||\\tstf\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; PARALLEL INTEGER INSTRUCTIONS -; - -; -; ABSI/STI -; - -(define_insn "*absqi2_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (abs:QI (match_operand:QI 1 "par_ind_operand" "S<>"))) - (set (match_operand:QI 2 "par_ind_operand" "=S<>") - (match_operand:QI 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC_NOOV 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)" - "absi\\t%1,%0\\n||\\tsti\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; ADDI/STI -; - -(define_insn "*addqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q,q") - (plus:QI (match_operand:QI 1 "parallel_operand" "%q,S<>") - (match_operand:QI 2 "parallel_operand" "S<>,q"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>,S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q,q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "addi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc,binarycc")]) - -; -; AND/STI -; - -(define_insn "*andqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q,q") - (and:QI (match_operand:QI 1 "parallel_operand" "%q,S<>") - (match_operand:QI 2 "parallel_operand" "S<>,q"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>,S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q,q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "and3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc,binarycc")]) - -; -; ASH(left)/STI -; - -(define_insn "*ashlqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (ashift:QI (match_operand:QI 1 "par_ind_operand" "S<>") - (match_operand:QI 2 "ext_low_reg_operand" "q"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; ASH(right)/STI -; - -(define_insn "*ashrqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (ashiftrt:QI (match_operand:QI 1 "par_ind_operand" "S<>") - (neg:QI (match_operand:QI 2 "ext_low_reg_operand" "q")))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "ash3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; FIX/STI -; - -(define_insn "*fixqfqi2_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (fix:QI (match_operand:QF 1 "par_ind_operand" "S<>"))) - (set (match_operand:QI 2 "par_ind_operand" "=S<>") - (match_operand:QI 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)" - "fix\\t%1,%0\\n||\\tsti\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; LSH(right)/STI -; - -(define_insn "*lshrqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (lshiftrt:QI (match_operand:QI 1 "par_ind_operand" "S<>") - (neg:QI (match_operand:QI 2 "ext_low_reg_operand" "q")))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "lsh3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; MPYI/ADDI -; - -(define_insn "*mulqi3_addqi3_clobber" - [(set (match_operand:QI 0 "r0r1_reg_operand" "=t,t,t,t") - (mult:QI (match_operand:QI 1 "parallel_operand" "%S<>!V,q,S<>!V,q") - (match_operand:QI 2 "parallel_operand" "q,S<>!V,S<>!V,q"))) - (set (match_operand:QI 3 "r2r3_reg_operand" "=u,u,u,u") - (plus:QI (match_operand:QI 4 "parallel_operand" "%S<>!V,q,q,S<>!V") - (match_operand:QI 5 "parallel_operand" "q,S<>!V,q,S<>!V"))) - (clobber (reg:CC 21))] - "TARGET_PARALLEL_MPY && TARGET_MPYI - && valid_parallel_operands_6 (operands, QImode)" - "mpyi3\\t%2,%1,%0\\n||\\taddi3\\t%5,%4,%3" - [(set_attr "type" "binarycc,binarycc,binarycc,binarycc")]) - - -; -; MPYI/STI -; - -(define_insn "*mulqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q,q") - (mult:QI (match_operand:QI 1 "parallel_operand" "%q,S<>") - (match_operand:QI 2 "parallel_operand" "S<>,q"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>,S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q,q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && TARGET_MPYI - && valid_parallel_operands_5 (operands, QImode)" - "mpyi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc,binarycc")]) - -; -; MPYI/SUBI -; - -(define_insn "*mulqi3_subqi3_clobber" - [(set (match_operand:QI 0 "r0r1_reg_operand" "=t,t") - (mult:QI (match_operand:QI 1 "parallel_operand" "S<>,q") - (match_operand:QI 2 "parallel_operand" "q,S<>"))) - (set (match_operand:QI 3 "r2r3_reg_operand" "=u,u") - (minus:QI (match_operand:QI 4 "parallel_operand" "S<>,q") - (match_operand:QI 5 "parallel_operand" "q,S<>"))) - (clobber (reg:CC 21))] - "TARGET_PARALLEL_MPY && TARGET_MPYI - && valid_parallel_operands_6 (operands, QImode)" - "mpyi3\\t%2,%1,%0\\n||\\tsubi3\\t%5,%4,%3" - [(set_attr "type" "binarycc,binarycc")]) - -; -; MPYI/LDI 0 -; - -(define_insn "*mulqi3_clrqi_clobber" - [(set (match_operand:QI 0 "r0r1_reg_operand" "=t") - (mult:QI (match_operand:QI 1 "par_ind_operand" "%S<>") - (match_operand:QI 2 "par_ind_operand" "S<>"))) - (set (match_operand:QI 3 "r2r3_reg_operand" "=u") - (const_int 0)) - (clobber (reg:CC 21))] - "TARGET_PARALLEL_MPY && TARGET_MPYI" - "mpyi3\\t%2,%1,%0\\n||\\tsubi3\\t%3,%3,%3" - [(set_attr "type" "binarycc")]) - -; -; NEGI/STI -; - -(define_insn "*negqi2_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (neg:QI (match_operand:QI 1 "par_ind_operand" "S<>"))) - (set (match_operand:QI 2 "par_ind_operand" "=S<>") - (match_operand:QI 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)" - "negi\\t%1,%0\\n||\\tsti\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; NOT/STI -; - -(define_insn "*notqi2_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (not:QI (match_operand:QI 1 "par_ind_operand" "S<>"))) - (set (match_operand:QI 2 "par_ind_operand" "=S<>") - (match_operand:QI 3 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QImode)" - "not\\t%1,%0\\n||\\tsti\\t%3,%2" - [(set_attr "type" "binarycc")]) - -; -; OR/STI -; - -(define_insn "*iorqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q,q") - (ior:QI (match_operand:QI 1 "parallel_operand" "%q,S<>") - (match_operand:QI 2 "parallel_operand" "S<>,q"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>,S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q,q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "or3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc,binarycc")]) - -; -; SUBI/STI -; - -(define_insn "*subqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q") - (minus:QI (match_operand:QI 1 "par_ind_operand" "S<>") - (match_operand:QI 2 "ext_low_reg_operand" "q"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "subi3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc")]) - -; -; XOR/STI -; - -(define_insn "*xorqi3_movqi_clobber" - [(set (match_operand:QI 0 "ext_low_reg_operand" "=q,q") - (xor:QI (match_operand:QI 1 "parallel_operand" "%q,S<>") - (match_operand:QI 2 "parallel_operand" "S<>,q"))) - (set (match_operand:QI 3 "par_ind_operand" "=S<>,S<>") - (match_operand:QI 4 "ext_low_reg_operand" "q,q")) - (clobber (reg:CC 21))] - "TARGET_PARALLEL && valid_parallel_operands_5 (operands, QImode)" - "xor3\\t%2,%1,%0\\n||\\tsti\\t%4,%3" - [(set_attr "type" "binarycc,binarycc")]) - -; -; BRANCH/CALL INSTRUCTIONS -; - -; -; Branch instructions -; -(define_insn "*b" - [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "* - return c4x_output_cbranch (\"b%0\", insn);" - [(set_attr "type" "jmpc")]) - -(define_insn "*b_rev" - [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "* - return c4x_output_cbranch (\"b%I0\", insn);" - [(set_attr "type" "jmpc")]) - -(define_insn "*b_noov" - [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "GET_CODE (operands[0]) != LE - && GET_CODE (operands[0]) != GE - && GET_CODE (operands[0]) != LT - && GET_CODE (operands[0]) != GT" - "* - return c4x_output_cbranch (\"b%0\", insn);" - [(set_attr "type" "jmpc")]) - -(define_insn "*b_noov_rev" - [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "GET_CODE (operands[0]) != LE - && GET_CODE (operands[0]) != GE - && GET_CODE (operands[0]) != LT - && GET_CODE (operands[0]) != GT" - "* - return c4x_output_cbranch (\"b%I0\", insn);" - [(set_attr "type" "jmpc")]) - -(define_expand "beq" - [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (EQ, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "bne" - [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (NE, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "blt" - [(set (pc) (if_then_else (lt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (LT, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "bltu" - [(set (pc) (if_then_else (ltu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (LTU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "bgt" - [(set (pc) (if_then_else (gt (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (GT, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "bgtu" - [(set (pc) (if_then_else (gtu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (GTU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "ble" - [(set (pc) (if_then_else (le (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (LE, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "bleu" - [(set (pc) (if_then_else (leu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (LEU, c4x_compare_op0, c4x_compare_op1);") - -(define_expand "bge" - [(set (pc) (if_then_else (ge (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (GE, c4x_compare_op0, c4x_compare_op1); - if (operands[1] == NULL_RTX) FAIL;") - -(define_expand "bgeu" - [(set (pc) (if_then_else (geu (match_dup 1) (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = c4x_gen_compare_reg (GEU, c4x_compare_op0, c4x_compare_op1);") - -(define_insn "*b_reg" - [(set (pc) (match_operand:QI 0 "reg_operand" "r"))] - "" - "bu%#\\t%0" - [(set_attr "type" "jump")]) - -(define_expand "indirect_jump" - [(set (pc) (match_operand:QI 0 "reg_operand" ""))] - "" - "") - -(define_insn "tablejump" - [(set (pc) (match_operand:QI 0 "src_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "" - "bu%#\\t%0" - [(set_attr "type" "jump")]) - -; -; CALL -; -(define_insn "*call_c3x" - [(call (mem:QI (match_operand:QI 0 "call_address_operand" "Ur")) - (match_operand:QI 1 "general_operand" "")) - (clobber (reg:QI 31))] - ;; Operand 1 not really used on the C4x. The C30 doesn't have reg 31. - - "TARGET_C3X" - "call%U0\\t%C0" - [(set_attr "type" "call")]) - -; LAJ requires R11 (31) for the return address -(define_insn "*laj" - [(call (mem:QI (match_operand:QI 0 "call_address_operand" "Ur")) - (match_operand:QI 1 "general_operand" "")) - (clobber (reg:QI 31))] - ;; Operand 1 not really used on the C4x. - - "! TARGET_C3X" - "* - if (final_sequence) - return c4x_check_laj_p (insn) - ? \"nop\\n\\tlaj%U0\\t%C0\" : \"laj%U0\\t%C0\"; - else - return \"call%U0\\t%C0\";" - [(set_attr "type" "laj")]) - -(define_expand "call" - [(parallel [(call (match_operand:QI 0 "" "") - (match_operand:QI 1 "general_operand" "")) - (clobber (reg:QI 31))])] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! call_address_operand (XEXP (operands[0], 0), Pmode)) - operands[0] = gen_rtx_MEM (GET_MODE (operands[0]), - force_reg (Pmode, XEXP (operands[0], 0))); -}") - -(define_insn "nodb_call" - [(call (mem:QI (match_operand:QI 0 "call_address_operand" "Ur")) - (const_int 0))] - "" - "call%U0\\t%C0" - [(set_attr "type" "call")]) - -(define_insn "*callv_c3x" - [(set (match_operand 0 "" "=r") - (call (mem:QI (match_operand:QI 1 "call_address_operand" "Ur")) - (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:QI 31))] - ;; Operand 0 and 2 not really used for the C4x. - ;; The C30 doesn't have reg 31. - - "TARGET_C3X" - "call%U1\\t%C1" - [(set_attr "type" "call")]) - -; LAJ requires R11 (31) for the return address -(define_insn "*lajv" - [(set (match_operand 0 "" "=r") - (call (mem:QI (match_operand:QI 1 "call_address_operand" "Ur")) - (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:QI 31))] - ;; Operand 0 and 2 not really used in the C30 instruction. - - "! TARGET_C3X" - "* - if (final_sequence) - return c4x_check_laj_p (insn) - ? \"nop\\n\\tlaj%U1\\t%C1\" : \"laj%U1\\t%C1\"; - else - return \"call%U1\\t%C1\";" - [(set_attr "type" "laj")]) - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "" "") - (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:QI 31))])] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! call_address_operand (XEXP (operands[1], 0), Pmode)) - operands[0] = gen_rtx_MEM (GET_MODE (operands[1]), - force_reg (Pmode, XEXP (operands[1], 0))); -}") - -(define_insn "return" - [(return)] - "! c4x_null_epilogue_p ()" - "rets" - [(set_attr "type" "rets")]) - -(define_insn "return_from_epilogue" - [(return)] - "reload_completed && ! c4x_interrupt_function_p ()" - "rets" - [(set_attr "type" "rets")]) - -(define_insn "return_from_interrupt_epilogue" - [(return)] - "reload_completed && c4x_interrupt_function_p ()" - "reti" - [(set_attr "type" "rets")]) - -(define_insn "*return_cc" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (return) - (pc)))] - "! c4x_null_epilogue_p ()" - "rets%0" - [(set_attr "type" "rets")]) - -(define_insn "*return_cc_noov" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (return) - (pc)))] - "GET_CODE (operands[0]) != LE - && GET_CODE (operands[0]) != GE - && GET_CODE (operands[0]) != LT - && GET_CODE (operands[0]) != GT - && ! c4x_null_epilogue_p ()" - "rets%0" - [(set_attr "type" "rets")]) - -(define_insn "*return_cc_inverse" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (pc) - (return)))] - "! c4x_null_epilogue_p ()" - "rets%I0" - [(set_attr "type" "rets")]) - -(define_insn "*return_cc_noov_inverse" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (pc) - (return)))] - "GET_CODE (operands[0]) != LE - && GET_CODE (operands[0]) != GE - && GET_CODE (operands[0]) != LT - && GET_CODE (operands[0]) != GT - && ! c4x_null_epilogue_p ()" - "rets%I0" - [(set_attr "type" "rets")]) - -(define_insn "jump" - [(set (pc) (label_ref (match_operand 0 "" "")))] - "" - "br%#\\t%l0" - [(set_attr "type" "jump")]) - -(define_insn "trap" - [(trap_if (const_int 1) (const_int 31))] - "" - "trapu\\t31" - [(set_attr "type" "call")]) - -(define_expand "conditional_trap" - [(trap_if (match_operand 0 "comparison_operator" "") - (match_operand 1 "const_int_operand" ""))] - "" - "{ - enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1); - if (ccreg == NULL_RTX) FAIL; - if (GET_MODE (ccreg) == CCmode) - emit_insn (gen_cond_trap_cc (operands[0], operands[1])); - else - emit_insn (gen_cond_trap_cc_noov (operands[0], operands[1])); - DONE;}") - -(define_insn "cond_trap_cc" - [(trap_if (match_operator 0 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (match_operand 1 "const_int_operand" ""))] - "" - "trap%0\\t31" - [(set_attr "type" "call")]) - -(define_insn "cond_trap_cc_noov" - [(trap_if (match_operator 0 "comparison_operator" - [(reg:CC_NOOV 21) (const_int 0)]) - (match_operand 1 "const_int_operand" ""))] - "GET_CODE (operands[0]) != LE - && GET_CODE (operands[0]) != GE - && GET_CODE (operands[0]) != LT - && GET_CODE (operands[0]) != GT" - "trap%0\\t31" - [(set_attr "type" "call")]) - -; -; DBcond -; -; Note we have to emit a dbu instruction if there are no delay slots -; to fill. -; Also note that GCC will try to reverse a loop to see if it can -; utilize this instruction. However, if there are more than one -; memory reference in the loop, it cannot guarantee that reversing -; the loop will work :( (see check_dbra_loop() in loop.c) -; Note that the C3x only decrements the 24 LSBs of the address register -; and the 8 MSBs are untouched. The C4x uses all 32-bits. We thus -; have an option to disable this instruction. -(define_insn "*db" - [(set (pc) - (if_then_else (ne (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (use (reg:QI 20)) - (clobber (reg:CC_NOOV 21))] - "TARGET_DB && TARGET_LOOP_UNSIGNED" - "* - if (which_alternative == 0) - return \"dbu%#\\t%0,%l1\"; - else if (which_alternative == 1) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tbge\", insn); - else if (which_alternative == 2) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tcmpi\\t0,%0\\n\\tbge\", insn); - else - return c4x_output_cbranch (\"push\\tr0\\n\\tldi\\t%0,r0\\n\\tsubi\\t1,r0\\n\\tsti\\tr0,%0\\n\\tpop\\tr0\\n\\tbhs\", insn); - " - [(set_attr "type" "db,jmpc,jmpc,jmpc")]) - -(define_insn "*db_noclobber" - [(set (pc) - (if_then_else (ne (match_operand:QI 0 "addr_reg_operand" "+a") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1)))] - "reload_completed && TARGET_DB && TARGET_LOOP_UNSIGNED" - "dbu%#\\t%0,%l1" - [(set_attr "type" "db")]) - -(define_split - [(set (pc) - (if_then_else (ne (match_operand:QI 0 "addr_reg_operand" "") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (use (reg:QI 20)) - (clobber (reg:CC_NOOV 21))] - "reload_completed && TARGET_DB && TARGET_LOOP_UNSIGNED" - [(parallel [(set (pc) - (if_then_else (ne (match_dup 0) - (const_int 0)) - (label_ref (match_dup 1)) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1)))])] - "") - - -; This insn is used for some loop tests, typically loops reversed when -; strength reduction is used. It is actually created when the instruction -; combination phase combines the special loop test. Since this insn -; is both a jump insn and has an output, it must deal with its own -; reloads, hence the `m' constraints. - -; The C4x does the decrement and then compares the result against zero. -; It branches if the result was greater than or equal to zero. -; In the RTL the comparison and decrement are assumed to happen -; at the same time so we bias the iteration counter with by -1 -; when we make the test. -(define_insn "decrement_and_branch_until_zero" - [(set (pc) - (if_then_else (ge (plus:QI (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (use (reg:QI 20)) - (clobber (reg:CC_NOOV 21))] - "TARGET_DB && (find_reg_note (insn, REG_NONNEG, 0) || TARGET_LOOP_UNSIGNED)" - "* - if (which_alternative == 0) - return \"dbu%#\\t%0,%l1\"; - else if (which_alternative == 1) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tbge\", insn); - else if (which_alternative == 2) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tcmpi\\t0,%0\\n\\tbge\", insn); - else - return c4x_output_cbranch (\"push\\tr0\\n\\tldi\\t%0,r0\\n\\tsubi\\t1,r0\\n\\tsti\\tr0,%0\\n\\tpop\\tr0\\n\\tbhs\", insn); - " - [(set_attr "type" "db,jmpc,jmpc,jmpc")]) - -(define_insn "*decrement_and_branch_until_zero_noclobber" - [(set (pc) - (if_then_else (ge (plus:QI (match_operand:QI 0 "addr_reg_operand" "+a") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1)))] - "reload_completed && TARGET_DB && TARGET_LOOP_UNSIGNED" - "dbu%#\\t%0,%l1" - [(set_attr "type" "db")]) - -(define_split - [(set (pc) - (if_then_else (ge (plus:QI (match_operand:QI 0 "addr_reg_operand" "") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (use (reg:QI 20)) - (clobber (reg:CC_NOOV 21))] - "reload_completed && TARGET_DB && TARGET_LOOP_UNSIGNED" - [(parallel [(set (pc) - (if_then_else (ge (plus:QI (match_dup 0) - (const_int -1)) - (const_int 0)) - (label_ref (match_dup 1)) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1)))])] - "") - -; -; MISC INSTRUCTIONS -; - -; -; NOP -; -(define_insn "nop" - [(const_int 0)] - "" - "nop") -; Default to misc type attr. - -(define_insn "return_indirect_internal" - [(return) - (use (match_operand:QI 0 "reg_operand" ""))] - "reload_completed" - "bu%#\\t%0" - [(set_attr "type" "jump")]) - -(define_expand "prologue" - [(const_int 1)] - "" - "c4x_expand_prologue (); DONE;") - -(define_expand "epilogue" - [(const_int 1)] - "" - "c4x_expand_epilogue (); DONE;") - -; -; RPTB -; -(define_insn "rptb_top" - [(use (label_ref (match_operand 0 "" ""))) - (use (label_ref (match_operand 1 "" ""))) - (clobber (reg:QI 25)) - (clobber (reg:QI 26))] - "" - "* - return ! final_sequence && c4x_rptb_rpts_p (insn, operands[0]) - ? \"rpts\\trc\" : \"rptb%#\\t%l1-1\"; - " - [(set_attr "type" "repeat_top")]) - -(define_insn "rpts_top" - [(unspec [(use (label_ref (match_operand 0 "" ""))) - (use (label_ref (match_operand 1 "" "")))] UNSPEC_RPTS) - (clobber (reg:QI 25)) - (clobber (reg:QI 26))] - "" - "* - return ! final_sequence && c4x_rptb_rpts_p (insn, operands[0]) - ? \"rpts\\trc\" : \"rptb%#\\t%l1-1\"; - " - [(set_attr "type" "repeat")]) - -; This pattern needs to be emitted at the start of the loop to -; say that RS and RE are loaded. -(define_insn "rptb_init" - [(unspec [(match_operand:QI 0 "register_operand" "va")] UNSPEC_RPTB_INIT) - (clobber (reg:QI 25)) - (clobber (reg:QI 26))] - "" - "" - [(set_attr "type" "repeat")]) - - -; operand 0 is the loop count pseudo register -; operand 1 is the number of loop iterations or 0 if it is unknown -; operand 2 is the maximum number of loop iterations -; operand 3 is the number of levels of enclosed loops -(define_expand "doloop_begin" - [(use (match_operand 0 "register_operand" "")) - (use (match_operand:QI 1 "const_int_operand" "")) - (use (match_operand:QI 2 "const_int_operand" "")) - (use (match_operand:QI 3 "const_int_operand" ""))] - "" - "if (INTVAL (operands[3]) > 1 || ! TARGET_RPTB) - FAIL; - emit_insn (gen_rptb_init (operands[0])); - DONE; - ") - - -; The RS (25) and RE (26) registers must be unviolate from the top of the loop -; to here. -(define_insn "rptb_end" - [(set (pc) - (if_then_else (ge (match_operand:QI 0 "register_operand" "+v,?a,!*d,!*x*k,!m") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (use (reg:QI 25)) - (use (reg:QI 26)) - (use (reg:QI 20)) - (clobber (reg:CC_NOOV 21))] - "" - "* - if (which_alternative == 0) - return c4x_rptb_nop_p (insn) ? \"nop\" : \"\"; - else if (which_alternative == 1 && TARGET_DB) - return \"dbu%#\\t%0,%l1\"; - else if (which_alternative == 2) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tbge\", insn); - else if (which_alternative == 3 || (which_alternative == 1 && ! TARGET_DB)) - return c4x_output_cbranch (\"subi\\t1,%0\\n\\tcmpi\\t0,%0\\n\\tbge\", insn); - else - return c4x_output_cbranch (\"push\\tr0\\n\\tldi\\t%0,r0\\n\\tsubi\\t1,r0\\n\\tsti\\tr0,%0\\n\\tpop\\tr0\\n\\tbhs\", insn); - " - [(set_attr "type" "repeat,db,jmpc,jmpc,jmpc")]) - -(define_split - [(set (pc) - (if_then_else (ge (match_operand:QI 0 "addr_reg_operand" "") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (use (match_operand:QI 2 "const_int_operand" "")) - (use (match_operand:QI 3 "const_int_operand" "")) - (use (match_operand:QI 4 "const_int_operand" "")) - (use (reg:QI 25)) - (use (reg:QI 26)) - (use (reg:QI 20)) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(parallel [(set (pc) - (if_then_else (ge (match_dup 0) - (const_int 0)) - (label_ref (match_dup 1)) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1)))])] - "") - -; operand 0 is the loop count pseudo register -; operand 1 is the number of loop iterations or 0 if it is unknown -; operand 2 is the maximum number of loop iterations -; operand 3 is the number of levels of enclosed loops -; operand 4 is the label to jump to at the top of the loop -(define_expand "doloop_end" - [(use (match_operand 0 "register_operand" "")) - (use (match_operand:QI 1 "const_int_operand" "")) - (use (match_operand:QI 2 "const_int_operand" "")) - (use (match_operand:QI 3 "const_int_operand" "")) - (use (label_ref (match_operand 4 "" "")))] - "" - "if (! TARGET_LOOP_UNSIGNED - && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > ((unsigned) 1 << 31)) - FAIL; - if (INTVAL (operands[3]) > 1 || ! TARGET_RPTB) - { - /* The C30 maximum iteration count for DB is 2^24. */ - if (! TARGET_DB) - FAIL; - emit_jump_insn (gen_decrement_and_branch_until_zero (operands[0], - operands[4])); - DONE; - } - emit_jump_insn (gen_rptb_end (operands[0], operands[4])); - DONE; - ") - -(define_expand "decrement_and_branch_on_count" - [(parallel [(set (pc) - (if_then_else (ge (match_operand:QI 0 "register_operand" "") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (use (reg:QI 25)) - (use (reg:QI 26)) - (clobber (reg:CC_NOOV 21))])] - "0" - "") - -(define_expand "movmemqi_small" - [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" "")) - (mem:BLK (match_operand:BLK 1 "src_operand" ""))) - (use (match_operand:QI 2 "immediate_operand" "")) - (use (match_operand:QI 3 "immediate_operand" "")) - (clobber (match_operand:QI 4 "ext_low_reg_operand" ""))])] - "" - " - { - rtx src, dst, tmp; - rtx src_mem, dst_mem; - int len; - int i; - - dst = operands[0]; - src = operands[1]; - len = INTVAL (operands[2]); - tmp = operands[4]; - - src_mem = gen_rtx_MEM (QImode, src); - dst_mem = gen_rtx_MEM (QImode, dst); - - if (TARGET_PARALLEL) - { - emit_insn (gen_movqi (tmp, src_mem)); - emit_insn (gen_addqi3_noclobber (src, src, const1_rtx)); - for (i = 1; i < len; i++) - { - emit_insn (gen_movqi_parallel (tmp, src_mem, dst_mem, tmp)); - emit_insn (gen_addqi3_noclobber (src, src, const1_rtx)); - emit_insn (gen_addqi3_noclobber (dst, dst, const1_rtx)); - } - emit_insn (gen_movqi (dst_mem, tmp)); - emit_insn (gen_addqi3_noclobber (dst, dst, const1_rtx)); - } - else - { - for (i = 0; i < len; i++) - { - emit_insn (gen_movqi (tmp, src_mem)); - emit_insn (gen_movqi (dst_mem, tmp)); - emit_insn (gen_addqi3_noclobber (src, src, const1_rtx)); - emit_insn (gen_addqi3_noclobber (dst, dst, const1_rtx)); - } - } - DONE; - } - ") - - -; -; BLOCK MOVE -; We should probably get RC loaded when using RPTB automagically... -; There's probably no need to call _memcpy() if we don't get -; an immediate operand for the size. We could do a better job here -; than most memcpy() implementations. -; operand 2 is the number of bytes -; operand 3 is the shared alignment -; operand 4 is a scratch register - -(define_insn "movmemqi_large" - [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "a")) - (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a"))) - (use (match_operand:QI 2 "immediate_operand" "i")) - (use (match_operand:QI 3 "immediate_operand" "")) - (clobber (match_operand:QI 4 "ext_low_reg_operand" "=&q")) - (clobber (match_scratch:QI 5 "=0")) - (clobber (match_scratch:QI 6 "=1")) - (clobber (reg:QI 25)) - (clobber (reg:QI 26)) - (clobber (reg:QI 27))] - "" - "* - { - int i; - int len = INTVAL (operands[2]); - - output_asm_insn (\"ldiu\\t*%1++,%4\", operands); - if (len < 8) - { - for (i = 1; i < len; i++) - { - output_asm_insn (\"sti\\t%4,*%0++\", operands); - output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); - } - } - else - { - if (TARGET_RPTS_CYCLES (len)) - { - output_asm_insn (\"rpts\\t%2-2\", operands); - output_asm_insn (\"sti\\t%4,*%0++\", operands); - output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); - } - else - { - output_asm_insn (\"ldiu\\t%2-2,rc\", operands); - output_asm_insn (\"rptb\\t$+1\", operands); - output_asm_insn (\"sti\\t%4,*%0++\", operands); - output_asm_insn (\"|| ldi\\t*%1++,%4\", operands); - } - } - return \"sti\\t%4,*%0++\"; - }" - [(set_attr "type" "multi")]) - -; Operand 2 is the count, operand 3 is the alignment. -(define_expand "movmemqi" - [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" "")) - (mem:BLK (match_operand:BLK 1 "src_operand" ""))) - (use (match_operand:QI 2 "immediate_operand" "")) - (use (match_operand:QI 3 "immediate_operand" ""))])] - "" - " - { - rtx tmp; - if (GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) > 32767 - || INTVAL (operands[2]) <= 0) - { - FAIL; /* Try to call _memcpy */ - } - - operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - tmp = gen_reg_rtx (QImode); - /* Disabled because of reload problems. */ - if (0 && INTVAL (operands[2]) < 8) - emit_insn (gen_movmemqi_small (operands[0], operands[1], operands[2], - operands[3], tmp)); - else - { - emit_insn (gen_movmemqi_large (operands[0], operands[1], operands[2], - operands[3], tmp)); - } - DONE; - }") - - -(define_insn "*cmpstrnqi" - [(set (match_operand:QI 0 "ext_reg_operand" "=d") - (compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a")) - (mem:BLK (match_operand:QI 2 "addr_reg_operand" "+a")))) - (use (match_operand:QI 3 "immediate_operand" "i")) - (use (match_operand:QI 4 "immediate_operand" "")) - (clobber (match_operand:QI 5 "std_reg_operand" "=&c")) - (clobber (reg:QI 21))] - "" - "* - { - output_asm_insn (\"ldi\\t%3-1,%5\", operands); - output_asm_insn (\"$1:\tsubi3\\t*%1++,*%2++,%0\", operands); - output_asm_insn (\"dbeq\\t%5,$1\", operands); - return \"\"; - }") - -(define_expand "cmpstrnqi" - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (compare:QI (match_operand:BLK 1 "general_operand" "") - (match_operand:BLK 2 "general_operand" ""))) - (use (match_operand:QI 3 "immediate_operand" "")) - (use (match_operand:QI 4 "immediate_operand" "")) - (clobber (match_dup 5)) - (clobber (reg:QI 21))])] - "" - " -{ - if (GET_CODE (operands[3]) != CONST_INT - || INTVAL (operands[3]) > 32767 - || INTVAL (operands[3]) <= 0) - { - FAIL; - } - operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - operands[2] = copy_to_mode_reg (Pmode, XEXP (operands[2], 0)); - operands[5] = gen_reg_rtx (QImode); -}") - -; -; TWO OPERAND LONG DOUBLE INSTRUCTIONS -; - -(define_expand "movhf" - [(set (match_operand:HF 0 "src_operand" "") - (match_operand:HF 1 "src_operand" ""))] - "" - "if (c4x_emit_move_sequence (operands, HFmode)) - DONE;") - -(define_insn "*movhf_noclobber_reg" - [(set (match_operand:HF 0 "reg_operand" "=h") - (match_operand:HF 1 "src_operand" "Hh"))] - "GET_CODE (operands[1]) != MEM" - "ldfu\\t%1,%0" - [(set_attr "type" "unary")]) - -(define_insn "*movhf_noclobber" - [(set (match_operand:HF 0 "dst_operand" "=h,m") - (match_operand:HF 1 "src_operand" "Hm,h"))] - "reg_operand (operands[0], HFmode) ^ reg_operand (operands[1], HFmode)" - "#" - [(set_attr "type" "multi,multi")]) - -(define_insn "*movhf_test" - [(set (reg:CC 21) - (compare:CC (match_operand:HF 1 "reg_operand" "h") - (const_int 0))) - (clobber (match_scratch:HF 0 "=h"))] - "" - "ldf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*movhf_set" - [(set (reg:CC 21) - (compare:CC (match_operand:HF 1 "reg_operand" "h") - (match_operand:HF 2 "fp_zero_operand" "G"))) - (set (match_operand:HF 0 "reg_operand" "=h") - (match_dup 1))] - "" - "ldf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_split - [(set (match_operand:HF 0 "reg_operand" "") - (match_operand:HF 1 "memory_operand" ""))] - "reload_completed" - [(set (match_dup 0) (float_extend:HF (match_dup 2))) - (set (match_dup 0) (unspec:HF [(subreg:QI (match_dup 0) 0) - (match_dup 3)] UNSPEC_LOADHF_INT))] - "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode); - operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode); - PUT_MODE (operands[2], QFmode); - PUT_MODE (operands[3], QImode);") - -(define_split - [(set (match_operand:HF 0 "reg_operand" "") - (match_operand:HF 1 "const_operand" ""))] - "reload_completed && 0" - [(set (match_dup 0) (float_extend:HF (match_dup 2))) - (set (match_dup 0) (unspec:HF [(subreg:QI (match_dup 0) 0) - (match_dup 3)] UNSPEC_LOADHF_INT))] - "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode); - operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode); - PUT_MODE (operands[2], QFmode); - PUT_MODE (operands[3], QImode);") - -(define_split - [(set (match_operand:HF 0 "memory_operand" "") - (match_operand:HF 1 "reg_operand" ""))] - "reload_completed" - [(set (match_dup 2) (float_truncate:QF (match_dup 1))) - (set (match_dup 3) (unspec:QI [(match_dup 1)] UNSPEC_STOREHF_INT))] - "operands[2] = c4x_operand_subword (operands[0], 0, 1, HFmode); - operands[3] = c4x_operand_subword (operands[0], 1, 1, HFmode); - PUT_MODE (operands[2], QFmode); - PUT_MODE (operands[3], QImode);") - -(define_insn "*loadhf_float" - [(set (match_operand:HF 0 "reg_operand" "=h") - (float_extend:HF (match_operand:QF 1 "src_operand" "fHm")))] - "" - "ldfu\\t%1,%0" - [(set_attr "type" "unary")]) - -(define_insn "*loadhf_int" - [(set (match_operand:HF 0 "reg_operand" "+h") - (unspec:HF [(subreg:QI (match_dup 0) 0) - (match_operand:QI 1 "src_operand" "rIm")] UNSPEC_LOADHF_INT))] - "" - "ldiu\\t%1,%0" - [(set_attr "type" "unary")]) - -(define_insn "*storehf_float" - [(set (match_operand:QF 0 "memory_operand" "=m") - (float_truncate:QF (match_operand:HF 1 "reg_operand" "h")))] - "" - "stf\\t%1,%0" - [(set_attr "type" "store")]) - -(define_insn "*storehf_int" - [(set (match_operand:QI 0 "memory_operand" "=m") - (unspec:QI [(match_operand:HF 1 "reg_operand" "h")] UNSPEC_STOREHF_INT))] - "" - "sti\\t%1,%0" - [(set_attr "type" "store")]) - -(define_insn "extendqfhf2" - [(set (match_operand:HF 0 "reg_operand" "=h") - (float_extend:HF (match_operand:QF 1 "reg_operand" "h")))] - "" - "ldfu\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "trunchfqf2" - [(set (match_operand:QF 0 "reg_operand" "=h") - (float_truncate:QF (match_operand:HF 1 "reg_operand" "0"))) - (clobber (reg:CC 21))] - "" - "andn\\t0ffh,%0" - [(set_attr "type" "unarycc")]) - -; -; PUSH/POP -; -(define_insn "pushhf" - [(set (mem:HF (pre_inc:QI (reg:QI 20))) - (match_operand:HF 0 "reg_operand" "h"))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (mem:HF (pre_inc:QI (reg:QI 20))) - (match_operand:HF 0 "reg_operand" ""))] - "reload_completed" - [(set (mem:QF (pre_inc:QI (reg:QI 20))) - (float_truncate:QF (match_dup 0))) - (set (mem:QI (pre_inc:QI (reg:QI 20))) - (unspec:QI [(match_dup 0)] UNSPEC_STOREHF_INT))] - "") - -(define_insn "pushhf_trunc" - [(set (mem:QF (pre_inc:QI (reg:QI 20))) - (float_truncate:QF (match_operand:HF 0 "reg_operand" "h")))] - "" - "pushf\\t%0" - [(set_attr "type" "push")]) - -(define_insn "pushhf_int" - [(set (mem:QI (pre_inc:QI (reg:QI 20))) - (unspec:QI [(match_operand:HF 0 "reg_operand" "h")] UNSPEC_STOREHF_INT))] - "" - "push\\t%0" - [(set_attr "type" "push")]) - -; we cannot use this because the popf will destroy the low 8 bits -;(define_insn "pophf" -; [(set (match_operand:HF 0 "reg_operand" "=h") -; (mem:HF (post_dec:QI (reg:QI 20)))) -; (clobber (reg:CC 21))] -; "" -; "#" -; [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HF 0 "reg_operand" "") - (mem:HF (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_operand:HF 0 "reg_operand" "=h") - (float_extend:HF (mem:QF (post_dec:QI (reg:QI 20))))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 0) - (unspec:HF [(subreg:QI (match_dup 0) 0) - (mem:QI (post_dec:QI (reg:QI 20)))] UNSPEC_LOADHF_INT)) - (clobber (reg:CC 21))])] - "") - -(define_insn "*pophf_int" - [(set (match_operand:HF 0 "reg_operand" "+h") - (unspec:HF [(subreg:QI (match_dup 0) 0) - (mem:QI (post_dec:QI (reg:QI 20)))] UNSPEC_LOADHF_INT)) - (clobber (reg:CC 21))] - "" - "pop\\t%0" - [(set_attr "type" "pop")]) - -(define_insn "*pophf_float" - [(set (match_operand:HF 0 "reg_operand" "=h") - (float_extend:HF (mem:QF (post_dec:QI (reg:QI 20))))) - (clobber (reg:CC 21))] - "" - "popf\\t%0" - [(set_attr "type" "pop")]) - -; -; FIX -; -(define_expand "fixuns_trunchfqi2" - [(parallel [(set (match_dup 2) - (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH"))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 3) - (minus:HF (match_dup 1) (match_dup 5))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (reg:CC 21) - (compare:CC (fix:QI (match_dup 3)) - (const_int 0))) - (set (match_dup 4) - (fix:QI (match_dup 3)))]) - (parallel [(set (match_dup 4) (unspec:QI [(match_dup 2)] UNSPEC_LDIV)) - (use (reg:CC 21))]) - (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 4))] - "" - "operands[2] = gen_reg_rtx (QImode); - operands[3] = gen_reg_rtx (HFmode); - operands[4] = gen_reg_rtx (QImode); - operands[5] = gen_reg_rtx (HFmode); - emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", HFmode));") - -(define_expand "fix_trunchfqi2" - [(parallel [(set (match_dup 2) - (fix:QI (match_operand:HF 1 "reg_or_const_operand" ""))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 3) (neg:HF (match_dup 1))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (fix:QI (match_dup 3))) - (clobber (reg:CC 21))]) - (parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_dup 4)) (const_int 0))) - (set (match_dup 5) (neg:QI (match_dup 4)))]) - (set (match_dup 2) - (if_then_else:QI (le (reg:CC 21) (const_int 0)) - (match_dup 5) - (match_dup 2))) - (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 2))] - "" - "if (TARGET_FAST_FIX) - { - emit_insn (gen_fixhfqi_clobber (operands[0], operands[1])); - DONE; - } - operands[2] = gen_reg_rtx (QImode); - operands[3] = gen_reg_rtx (HFmode); - operands[4] = gen_reg_rtx (QImode); - operands[5] = gen_reg_rtx (QImode); - ") - -(define_insn "*fixhfqi_set" - [(set (reg:CC 21) - (compare:CC (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH")) - (const_int 0))) - (set (match_operand:QI 0 "ext_reg_operand" "=d") - (fix:QI (match_dup 1)))] - "" - "fix\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "fixhfqi_clobber" - [(set (match_operand:QI 0 "reg_operand" "=dc") - (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH"))) - (clobber (reg:CC 21))] - "" - "fix\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_expand "fix_trunchfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (fix:HI (match_operand:HF 1 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (fix_trunchfhi2_libfunc, FIX, HImode, HFmode, 2, operands); - DONE;") - -(define_expand "fixuns_trunchfhi2" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (unsigned_fix:HI (match_operand:HF 1 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (fixuns_trunchfhi2_libfunc, UNSIGNED_FIX, - HImode, HFmode, 2, operands); - DONE;") - -; -; ABSF -; -(define_expand "abshf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (abs:HF (match_operand:HF 1 "reg_or_const_operand" ""))) - (clobber (reg:CC_NOOV 21))])] -"" -"") - -(define_insn "*abshf2_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (abs:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))) - (clobber (reg:CC_NOOV 21))] - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*abshf2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:HF (match_operand:HF 1 "reg_operand" "h")) - (match_operand:HF 2 "fp_zero_operand" "G"))) - (clobber (match_scratch:HF 0 "=h"))] - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*abshf2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (abs:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) - (match_operand:HF 2 "fp_zero_operand" "G"))) - (set (match_operand:HF 0 "reg_operand" "=h") - (abs:HF (match_dup 1)))] - - "" - "absf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; NEGF -; -(define_expand "neghf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (neg:HF (match_operand:HF 1 "reg_or_const_operand" ""))) - (clobber (reg:CC_NOOV 21))])] -"" -"") - -(define_insn "*neghf2_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))) - (clobber (reg:CC_NOOV 21))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*neghf2_test" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) - (match_operand:HF 2 "fp_zero_operand" "G"))) - (clobber (match_scratch:HF 0 "=h"))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -(define_insn "*neghf2_set" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")) - (match_operand:HF 2 "fp_zero_operand" "G"))) - (set (match_operand:HF 0 "reg_operand" "=h") - (neg:HF (match_dup 1)))] - "" - "negf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RCPF -; -(define_insn "*rcpfhf_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] UNSPEC_RCPF)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rcpf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RSQRF -; -(define_insn "*rsqrfhf_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] UNSPEC_RSQRF)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rsqrf\\t%1,%0" - [(set_attr "type" "unarycc")]) - -; -; RNDF -; -(define_insn "*rndhf_clobber" - [(set (match_operand:HF 0 "reg_operand" "=h") - (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] UNSPEC_RND)) - (clobber (reg:CC_NOOV 21))] - "! TARGET_C3X" - "rnd\\t%1,%0" - [(set_attr "type" "unarycc")]) - - -; Inlined float square root for C4x -(define_expand "sqrthf2_inline" - [(parallel [(set (match_dup 2) - (unspec:HF [(match_operand:HF 1 "reg_operand" "")] UNSPEC_RSQRF)) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:HF (match_dup 5) (match_dup 1))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:HF (match_dup 6) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 2) (mult:HF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:HF (match_dup 6) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 2) (mult:HF (match_dup 2) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:HF 0 "reg_operand" "") - (mult:HF (match_dup 2) (match_dup 1))) - (clobber (reg:CC_NOOV 21))])] - "! TARGET_C3X" - " - operands[2] = gen_reg_rtx (HFmode); - operands[3] = gen_reg_rtx (HFmode); - operands[4] = gen_reg_rtx (HFmode); - operands[5] = CONST_DOUBLE_ATOF (\"0.5\", HFmode); - operands[6] = CONST_DOUBLE_ATOF (\"1.5\", HFmode); - ") - - -(define_expand "sqrthf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (sqrt:HF (match_operand:HF 1 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "! TARGET_C3X && TARGET_INLINE" - "emit_insn (gen_sqrthf2_inline (operands[0], operands[1])); - DONE;") - -; -; THREE OPERAND LONG DOUBLE INSTRUCTIONS -; - -; -; ADDF -; -(define_insn "addhf3" - [(set (match_operand:HF 0 "reg_operand" "=h,?h") - (plus:HF (match_operand:HF 1 "reg_operand" "%0,h") - (match_operand:HF 2 "reg_or_const_operand" "H,h"))) - (clobber (reg:CC_NOOV 21))] - "" - "@ - addf\\t%2,%0 - addf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc")]) - -; -; SUBF -; -(define_insn "subhf3" - [(set (match_operand:HF 0 "reg_operand" "=h,h,?h") - (minus:HF (match_operand:HF 1 "reg_or_const_operand" "0,H,h") - (match_operand:HF 2 "reg_or_const_operand" "H,0,h"))) - (clobber (reg:CC_NOOV 21))] - "" - "@ - subf\\t%2,%0 - subrf\\t%1,%0 - subf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc,binarycc")]) - -; -; MULF -; -; The C3x MPYF only uses 24-bit precision while the C4x uses 32-bit precision. -; -(define_expand "mulhf3" - [(parallel [(set (match_operand:HF 0 "reg_operand" "=h") - (mult:HF (match_operand:HF 1 "reg_operand" "h") - (match_operand:HF 2 "reg_operand" "h"))) - (clobber (reg:CC_NOOV 21))])] - "! TARGET_C3X" - "") - -(define_insn "*mulhf3_c40" - [(set (match_operand:HF 0 "reg_operand" "=h,?h") - (mult:HF (match_operand:HF 1 "reg_operand" "%0,h") - (match_operand:HF 2 "reg_or_const_operand" "hH,h"))) - (clobber (reg:CC_NOOV 21))] - "" - "@ - mpyf\\t%2,%0 - mpyf3\\t%2,%1,%0" - [(set_attr "type" "binarycc,binarycc")]) - -; -; CMPF -; -(define_expand "cmphf" - [(set (reg:CC 21) - (compare:CC (match_operand:HF 0 "reg_operand" "") - (match_operand:HF 1 "reg_or_const_operand" "")))] - "" - "c4x_compare_op0 = operands[0]; - c4x_compare_op1 = operands[1]; - DONE;") - -(define_insn "*cmphf" - [(set (reg:CC 21) - (compare:CC (match_operand:HF 0 "reg_operand" "h") - (match_operand:HF 1 "reg_or_const_operand" "hH")))] - "" - "cmpf\\t%1,%0" - [(set_attr "type" "compare")]) - -(define_insn "*cmphf_noov" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:HF 0 "reg_operand" "h") - (match_operand:HF 1 "reg_or_const_operand" "hH")))] - "" - "cmpf\\t%1,%0" - [(set_attr "type" "compare")]) - -; Inlined float divide for C4x -(define_expand "divhf3_inline" - [(parallel [(set (match_dup 3) - (unspec:HF [(match_operand:HF 2 "reg_operand" "")] UNSPEC_RCPF)) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:HF (match_dup 5) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:HF (match_dup 3) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 4) (minus:HF (match_dup 5) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_dup 3) (mult:HF (match_dup 3) (match_dup 4))) - (clobber (reg:CC_NOOV 21))]) - (parallel [(set (match_operand:HF 0 "reg_operand" "") - (mult:HF (match_operand:HF 1 "reg_operand" "") - (match_dup 3))) - (clobber (reg:CC_NOOV 21))])] - "! TARGET_C3X" - " - operands[3] = gen_reg_rtx (HFmode); - operands[4] = gen_reg_rtx (HFmode); - operands[5] = CONST2_RTX (HFmode); - ") - -(define_expand "divhf3" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (div:HF (match_operand:HF 1 "reg_operand" "") - (match_operand:HF 2 "reg_operand" ""))) - (clobber (reg:CC 21))])] - "! TARGET_C3X && TARGET_INLINE" - "emit_insn (gen_divhf3_inline (operands[0], operands[1], operands[2])); - DONE;") - - -; -; TWO OPERAND LONG LONG INSTRUCTIONS -; - -(define_insn "*movhi_stik" - [(set (match_operand:HI 0 "memory_operand" "=m") - (match_operand:HI 1 "stik_const_operand" "K"))] - "! TARGET_C3X" - "#" - [(set_attr "type" "multi")]) - -; We could load some constants using define_splits for the C30 -; in the large memory model---these would emit shift and or insns. -(define_expand "movhi" - [(set (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" ""))] - "" - "if (c4x_emit_move_sequence (operands, HImode)) - DONE;") - -; The constraints for movhi must include 'r' if we don't -; restrict HImode regnos to start on an even number, since -; we can get RC, R8 allocated as a pair. We want more -; votes for FP_REGS so we use dr as the constraints. -(define_insn "*movhi_noclobber" - [(set (match_operand:HI 0 "dst_operand" "=dr,m") - (match_operand:HI 1 "src_operand" "drIm,r"))] - "reg_operand (operands[0], HImode) - || reg_operand (operands[1], HImode)" - "#" - [(set_attr "type" "multi,multi")]) - -; This will fail miserably if the destination register is used in the -; source memory address. -; The usual strategy in this case is to swap the order of insns we emit, -; however, this will fail if we have an autoincrement memory address. -; For example: -; ldi *ar0++, ar0 -; ldi *ar0++, ar1 -; -; We could convert this to -; ldi *ar0(1), ar1 -; ldi *ar0, ar0 -; -; However, things are likely to be very screwed up if we get this. - -(define_split - [(set (match_operand:HI 0 "dst_operand" "") - (match_operand:HI 1 "src_operand" ""))] - "reload_completed - && (reg_operand (operands[0], HImode) - || reg_operand (operands[1], HImode) - || stik_const_operand (operands[1], HImode))" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - "operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode); - if (reg_overlap_mentioned_p (operands[2], operands[5])) - { - /* Swap order of move insns. */ - rtx tmp; - tmp = operands[2]; - operands[2] =operands[3]; - operands[3] = tmp; - tmp = operands[4]; - operands[4] =operands[5]; - operands[5] = tmp; - }") - - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "reg_operand" "=dc") - (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm"))) - (clobber (reg:CC 21))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (sign_extend:HI (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed && TARGET_C3X" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (match_dup 2)) - (parallel [(set (match_dup 3) (ashiftrt:QI (match_dup 3) (const_int 31))) - (clobber (reg:CC 21))])] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (sign_extend:HI (match_operand:QI 1 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed && ! TARGET_C3X" - [(set (match_dup 2) (match_dup 1)) - (parallel [(set (match_dup 3) (ashiftrt:QI (match_dup 2) (const_int 31))) - (clobber (reg:CC 21))])] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "reg_operand" "=?dc") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "rm"))) - (clobber (reg:CC 21))] - "" - "#" - [(set_attr "type" "multi")]) - -; If operand0 and operand1 are the same register we don't need -; the first set. -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (const_int 0))] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -; -; PUSH/POP -; -(define_insn "*pushhi" - [(set (mem:HI (pre_inc:QI (reg:QI 20))) - (match_operand:HI 0 "reg_operand" "r"))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (mem:HI (pre_inc:QI (reg:QI 20))) - (match_operand:HI 0 "reg_operand" ""))] - "reload_completed" - [(set (mem:QI (pre_inc:QI (reg:QI 20))) (match_dup 2)) - (set (mem:QI (pre_inc:QI (reg:QI 20))) (match_dup 3))] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -(define_insn "*pophi" - [(set (match_operand:HI 0 "reg_operand" "=r") - (mem:HI (post_dec:QI (reg:QI 20)))) - (clobber (reg:CC 21))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (mem:HI (pre_inc:QI (reg:QI 20))))] - "reload_completed" - [(set (match_dup 2) (mem:QI (pre_inc:QI (reg:QI 20)))) - (set (match_dup 3) (mem:QI (pre_inc:QI (reg:QI 20))))] - "operands[2] = c4x_operand_subword (operands[0], 0, 0, HImode); - operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);") - -; -; NEG -; -(define_insn "neghi2" - [(set (match_operand:HI 0 "ext_reg_operand" "=d") - (neg:HI (match_operand:HI 1 "src_operand" "rm"))) - (clobber (reg:CC_NOOV 21))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HI 0 "ext_reg_operand" "") - (neg:HI (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (neg:QI (match_dup 3)) - (const_int 0))) - (set (match_dup 2) (neg:QI (match_dup 3)))]) - (parallel [(set (match_dup 4) (neg:QI (match_dup 5))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))])] - "operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[3] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode);") - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "reg_operand" "=r") - (not:HI (match_operand:HI 1 "src_operand" "rm"))) - (clobber (reg:CC 21))] - "" - "#" - [(set_attr "type" "multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (not:HI (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_dup 2) (not:QI (match_dup 3))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 4) (not:QI (match_dup 5))) - (clobber (reg:CC 21))])] - "operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[3] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode);") - -(define_expand "floathiqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (float:QF (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (floathiqf2_libfunc, FLOAT, QFmode, HImode, 2, operands); - DONE;") - -(define_expand "floatunshiqf2" - [(parallel [(set (match_operand:QF 0 "reg_operand" "") - (unsigned_float:QF (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (floatunshiqf2_libfunc, UNSIGNED_FLOAT, - QFmode, HImode, 2, operands); - DONE;") - -(define_expand "floathihf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (float:HF (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (floathihf2_libfunc, FLOAT, HFmode, HImode, 2, operands); - DONE;") - -(define_expand "floatunshihf2" - [(parallel [(set (match_operand:HF 0 "reg_operand" "") - (unsigned_float:HF (match_operand:HI 1 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall (floatunshihf2_libfunc, UNSIGNED_FLOAT, - HFmode, HImode, 2, operands); - DONE;") - - -; -; THREE OPERAND LONG LONG INSTRUCTIONS -; - -(define_expand "addhi3" - [(parallel [(set (match_operand:HI 0 "ext_reg_operand" "") - (plus:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (PLUS, operands, HImode);") - -(define_insn "*addhi3_clobber" - [(set (match_operand:HI 0 "ext_reg_operand" "=d,d,?d") - (plus:HI (match_operand:HI 1 "src_operand" "%0,rR,rS<>") - (match_operand:HI 2 "src_operand" "rm,R,rS<>"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (PLUS, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "ext_reg_operand" "") - (plus:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (plus:QI (match_dup 4) (match_dup 5)) - (const_int 0))) - (set (match_dup 3) (plus:QI (match_dup 4) (match_dup 5)))]) - (parallel [(set (match_dup 6) (plus:QI (match_dup 7) (match_dup 8))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -(define_expand "subhi3" - [(parallel [(set (match_operand:HI 0 "ext_reg_operand" "") - (minus:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))])] - "" - "legitimize_operands (MINUS, operands, HImode);") - - -(define_insn "*subhi3_clobber" - [(set (match_operand:HI 0 "ext_reg_operand" "=d,d,?d") - (minus:HI (match_operand:HI 1 "src_operand" "0,rR,rS<>") - (match_operand:HI 2 "src_operand" "rm,R,rS<>"))) - (clobber (reg:CC_NOOV 21))] - "valid_operands (MINUS, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "ext_reg_operand" "") - (minus:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC_NOOV 21))] - "reload_completed" - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (minus:QI (match_dup 4) (match_dup 5)) - (const_int 0))) - (set (match_dup 3) (minus:QI (match_dup 4) (match_dup 5)))]) - (parallel [(set (match_dup 6) (minus:QI (match_dup 7) (match_dup 8))) - (use (reg:CC_NOOV 21)) - (clobber (reg:CC_NOOV 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -(define_expand "iorhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (ior:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (IOR, operands, HImode);") - -(define_insn "*iorhi3_clobber" - [(set (match_operand:HI 0 "reg_operand" "=d,d,?d") - (ior:HI (match_operand:HI 1 "src_operand" "%0,rR,rS<>") - (match_operand:HI 2 "src_operand" "rm,R,rS<>"))) - (clobber (reg:CC 21))] - "valid_operands (IOR, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (ior:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_dup 3) (ior:QI (match_dup 4) (match_dup 5))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 6) (ior:QI (match_dup 7) (match_dup 8))) - (clobber (reg:CC 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -(define_expand "andhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (and:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (AND, operands, HImode);") - -(define_insn "*andhi3_clobber" - [(set (match_operand:HI 0 "reg_operand" "=d,d,?d") - (and:HI (match_operand:HI 1 "src_operand" "%0,rR,rS<>") - (match_operand:HI 2 "src_operand" "rm,R,rS<>"))) - (clobber (reg:CC 21))] - "valid_operands (AND, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (and:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_dup 3) (and:QI (match_dup 4) (match_dup 5))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 6) (and:QI (match_dup 7) (match_dup 8))) - (clobber (reg:CC 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -(define_expand "xorhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (xor:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "legitimize_operands (XOR, operands, HImode);") - - -(define_insn "*xorhi3_clobber" - [(set (match_operand:HI 0 "reg_operand" "=d,d,?d") - (xor:HI (match_operand:HI 1 "src_operand" "%0,rR,rS<>") - (match_operand:HI 2 "src_operand" "rm,R,rS<>"))) - (clobber (reg:CC 21))] - "valid_operands (XOR, operands, HImode)" - "#" - [(set_attr "type" "multi,multi,multi")]) - -(define_split - [(set (match_operand:HI 0 "reg_operand" "") - (xor:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))] - "reload_completed" - [(parallel [(set (match_dup 3) (xor:QI (match_dup 4) (match_dup 5))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 6) (xor:QI (match_dup 7) (match_dup 8))) - (clobber (reg:CC 21))])] - "operands[3] = c4x_operand_subword (operands[0], 0, 1, HImode); - operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); - operands[5] = c4x_operand_subword (operands[2], 0, 1, HImode); - operands[6] = c4x_operand_subword (operands[0], 1, 1, HImode); - operands[7] = c4x_operand_subword (operands[1], 1, 1, HImode); - operands[8] = c4x_operand_subword (operands[2], 1, 1, HImode);") - -(define_expand "ashlhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (ashift:HI (match_operand:HI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32) - { - rtx op0hi = operand_subword (operands[0], 1, 0, HImode); - rtx op0lo = operand_subword (operands[0], 0, 0, HImode); - rtx op1lo = operand_subword (operands[1], 0, 0, HImode); - rtx count = GEN_INT ((INTVAL (operands[2]) - 32)); - - if (INTVAL (count)) - emit_insn (gen_ashlqi3 (op0hi, op1lo, count)); - else - emit_insn (gen_movqi (op0hi, op1lo)); - emit_insn (gen_movqi (op0lo, const0_rtx)); - DONE; - } - if (! REG_P (operands[1])) - operands[1] = force_reg (HImode, operands[1]); - emit_insn (gen_ashlhi3_reg (operands[0], operands[1], operands[2])); - DONE; - ") - -; %0.lo = %1.lo << %2 -; %0.hi = (%1.hi << %2 ) | (%1.lo >> (32 - %2)) -; This algorithm should work for shift counts greater than 32 -(define_expand "ashlhi3_reg" - [(use (match_operand:HI 1 "reg_operand" "")) - (use (match_operand:HI 0 "reg_operand" "")) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 7) - (ashift:QI (match_dup 3) - (match_operand:QI 2 "reg_operand" ""))) - (clobber (reg:CC 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 8) - (ashift:QI (match_dup 4) (match_dup 2))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 10) - (plus:QI (match_dup 2) (const_int -32))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will do a left shift. */ - (parallel [(set (match_dup 9) - (lshiftrt:QI (match_dup 3) (neg:QI (match_dup 10)))) - (clobber (reg:CC 21))]) - (set (match_dup 5) (match_dup 7)) - (parallel [(set (match_dup 6) - (ior:QI (match_dup 8) (match_dup 9))) - (clobber (reg:CC 21))])] - "" - " - operands[3] = operand_subword (operands[1], 0, 1, HImode); /* lo */ - operands[4] = operand_subword (operands[1], 1, 1, HImode); /* hi */ - operands[5] = operand_subword (operands[0], 0, 1, HImode); /* lo */ - operands[6] = operand_subword (operands[0], 1, 1, HImode); /* hi */ - operands[7] = gen_reg_rtx (QImode); /* lo << count */ - operands[8] = gen_reg_rtx (QImode); /* hi << count */ - operands[9] = gen_reg_rtx (QImode); /* lo >> (32 - count) */ - operands[10] = gen_reg_rtx (QImode); /* 32 - count */ - ") - -; This should do all the dirty work with define_split -(define_expand "lshrhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (lshiftrt:HI (match_operand:HI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32) - { - rtx op0hi = operand_subword (operands[0], 1, 0, HImode); - rtx op0lo = operand_subword (operands[0], 0, 0, HImode); - rtx op1hi = operand_subword (operands[1], 1, 0, HImode); - rtx count = GEN_INT ((INTVAL (operands[2]) - 32)); - - if (INTVAL (count)) - emit_insn (gen_lshrqi3 (op0lo, op1hi, count)); - else - emit_insn (gen_movqi (op0lo, op1hi)); - emit_insn (gen_movqi (op0hi, const0_rtx)); - DONE; - } - if (! REG_P (operands[1])) - operands[1] = force_reg (HImode, operands[1]); - emit_insn (gen_lshrhi3_reg (operands[0], operands[1], operands[2])); - DONE;") - -; %0.hi = %1.hi >> %2 -; %0.lo = (%1.lo >> %2 ) | (%1.hi << (32 - %2)) -; This algorithm should work for shift counts greater than 32 -(define_expand "lshrhi3_reg" - [(use (match_operand:HI 1 "reg_operand" "")) - (use (match_operand:HI 0 "reg_operand" "")) - (parallel [(set (match_dup 11) - (neg:QI (match_operand:QI 2 "reg_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 7) - (lshiftrt:QI (match_dup 3) - (neg:QI (match_dup 11)))) - (clobber (reg:CC 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 8) - (lshiftrt:QI (match_dup 4) - (neg:QI (match_dup 11)))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 10) - (plus:QI (match_dup 11) (const_int 32))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will do an arithmetic - right shift. However, we need a logical right shift. */ - (parallel [(set (match_dup 9) - (ashift:QI (match_dup 4) (unspec:QI [(match_dup 10)] UNSPEC_LSH))) - (clobber (reg:CC 21))]) - (set (match_dup 6) (match_dup 8)) - (parallel [(set (match_dup 5) - (ior:QI (match_dup 7) (match_dup 9))) - (clobber (reg:CC 21))])] - "" - " - operands[3] = operand_subword (operands[1], 0, 1, HImode); /* lo */ - operands[4] = operand_subword (operands[1], 1, 1, HImode); /* hi */ - operands[5] = operand_subword (operands[0], 0, 1, HImode); /* lo */ - operands[6] = operand_subword (operands[0], 1, 1, HImode); /* hi */ - operands[7] = gen_reg_rtx (QImode); /* lo >> count */ - operands[8] = gen_reg_rtx (QImode); /* hi >> count */ - operands[9] = gen_reg_rtx (QImode); /* hi << (32 - count) */ - operands[10] = gen_reg_rtx (QImode); /* 32 - count */ - operands[11] = gen_reg_rtx (QImode); /* -count */ - ") - -; This should do all the dirty work with define_split -(define_expand "ashrhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (ashiftrt:HI (match_operand:HI 1 "src_operand" "") - (match_operand:QI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32) - { - rtx op0hi = operand_subword (operands[0], 1, 0, HImode); - rtx op0lo = operand_subword (operands[0], 0, 0, HImode); - rtx op1hi = operand_subword (operands[1], 1, 0, HImode); - rtx count = GEN_INT ((INTVAL (operands[2]) - 32)); - - if (INTVAL (count)) - emit_insn (gen_ashrqi3 (op0lo, op1hi, count)); - else - emit_insn (gen_movqi (op0lo, op1hi)); - emit_insn (gen_ashrqi3 (op0hi, op1hi, GEN_INT (31))); - DONE; - } - if (! REG_P (operands[1])) - operands[1] = force_reg (HImode, operands[1]); - emit_insn (gen_ashrhi3_reg (operands[0], operands[1], operands[2])); - DONE;") - -; %0.hi = %1.hi >> %2 -; %0.lo = (%1.lo >> %2 ) | (%1.hi << (32 - %2)) -; This algorithm should work for shift counts greater than 32 -(define_expand "ashrhi3_reg" - [(use (match_operand:HI 1 "reg_operand" "")) - (use (match_operand:HI 0 "reg_operand" "")) - (parallel [(set (match_dup 11) - (neg:QI (match_operand:QI 2 "reg_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 7) - (lshiftrt:QI (match_dup 3) - (neg:QI (match_dup 11)))) - (clobber (reg:CC 21))]) - /* If the shift count is greater than 32 this will give zero. */ - (parallel [(set (match_dup 8) - (ashiftrt:QI (match_dup 4) - (neg:QI (match_dup 11)))) - (clobber (reg:CC 21))]) - (parallel [(set (match_dup 10) - (plus:QI (match_dup 11) (const_int 32))) - (clobber (reg:CC_NOOV 21))]) - /* If the shift count is greater than 32 this will do an arithmetic - right shift. */ - (parallel [(set (match_dup 9) - (ashift:QI (match_dup 4) (match_dup 10))) - (clobber (reg:CC 21))]) - (set (match_dup 6) (match_dup 8)) - (parallel [(set (match_dup 5) - (ior:QI (match_dup 7) (match_dup 9))) - (clobber (reg:CC 21))])] - "" - " - operands[3] = operand_subword (operands[1], 0, 1, HImode); /* lo */ - operands[4] = operand_subword (operands[1], 1, 1, HImode); /* hi */ - operands[5] = operand_subword (operands[0], 0, 1, HImode); /* lo */ - operands[6] = operand_subword (operands[0], 1, 1, HImode); /* hi */ - operands[7] = gen_reg_rtx (QImode); /* lo >> count */ - operands[8] = gen_reg_rtx (QImode); /* hi >> count */ - operands[9] = gen_reg_rtx (QImode); /* hi << (32 - count) */ - operands[10] = gen_reg_rtx (QImode); /* 32 - count */ - operands[11] = gen_reg_rtx (QImode); /* -count */ - ") - -(define_expand "cmphi" - [(set (reg:CC 21) - (compare:CC (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" "")))] - "" - "legitimize_operands (COMPARE, operands, HImode); - c4x_compare_op0 = operands[0]; - c4x_compare_op1 = operands[1]; - DONE;") - -(define_insn "*cmphi_cc" - [(set (reg:CC 21) - (compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>")))] - "valid_operands (COMPARE, operands, HImode)" - "#" - [(set_attr "type" "multi")]) - -(define_insn "*cmphi_cc_noov" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>")))] - "valid_operands (COMPARE, operands, HImode)" - "#" - [(set_attr "type" "multi")]) - -; This works only before reload because we need 2 extra registers. -; Use unspec to avoid recursive split. -(define_split - [(set (reg:CC 21) - (compare:CC (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" "")))] - "! reload_completed" - [(parallel [(set (reg:CC 21) - (unspec:CC [(compare:CC (match_dup 0) - (match_dup 1))] UNSPEC_CMPHI)) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 ""))])] - "") - -(define_split - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" "")))] - "! reload_completed" - [(parallel [(set (reg:CC_NOOV 21) - (unspec:CC_NOOV [(compare:CC_NOOV (match_dup 0) - (match_dup 1))] UNSPEC_CMPHI)) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 ""))])] - "") - -; This is normally not used. The define splits above are used first. -(define_split - [(set (reg:CC 21) - (compare:CC (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" "")))] - "reload_completed" - [(parallel [(set (reg:CC 21) - (compare:CC (match_dup 0) (match_dup 1))) - (use (reg:QI 20))])] - "") - -(define_split - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:HI 0 "src_operand" "") - (match_operand:HI 1 "src_operand" "")))] - "reload_completed" - [(parallel [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_dup 0) (match_dup 1))) - (use (reg:QI 20))])] - "") - -(define_insn "*cmphi" - [(set (reg:CC 21) - (compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>"))) - (use (reg:QI 20))] - "valid_operands (COMPARE, operands, HImode)" - "* - { - int use_ir1 = (reg_operand (operands[0], HImode) - && REG_P (operands[0]) - && REGNO (operands[0]) == IR1_REGNO) - || (reg_operand (operands[1], HImode) - && REG_P (operands[1]) - && REGNO (operands[1]) == IR1_REGNO); - - if (use_ir1) - output_asm_insn (\"push\\tir1\", operands); - else - output_asm_insn (\"push\\tbk\", operands); - output_asm_insn (\"push\\tr0\", operands); - output_asm_insn (\"subi3\\t%1,%0,r0\", operands); - if (use_ir1) - { - output_asm_insn (\"ldiu\\tst,ir1\", operands); - output_asm_insn (\"or\\t07bh,ir1\", operands); - } - else - { - output_asm_insn (\"ldiu\\tst,bk\", operands); - output_asm_insn (\"or\\t07bh,bk\", operands); - } - output_asm_insn (\"subb3\\t%O1,%O0,r0\", operands); - if (use_ir1) - output_asm_insn (\"and3\\tir1,st,ir1\", operands); - else - output_asm_insn (\"and3\\tbk,st,bk\", operands); - output_asm_insn (\"pop\\tr0\", operands); - if (use_ir1) - { - output_asm_insn (\"ldiu\\tir1,st\", operands); - output_asm_insn (\"pop\\tir1\", operands); - } - else - { - output_asm_insn (\"ldiu\\tbk,st\", operands); - output_asm_insn (\"pop\\tbk\", operands); - } - return \"\"; - }" - [(set_attr "type" "multi")]) - -(define_insn "*cmphi_noov" - [(set (reg:CC_NOOV 21) - (compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>"))) - (use (reg:QI 20))] - "valid_operands (COMPARE, operands, HImode)" - "* - { - int use_ir1 = (reg_operand (operands[0], HImode) - && REG_P (operands[0]) - && REGNO (operands[0]) == IR1_REGNO) - || (reg_operand (operands[1], HImode) - && REG_P (operands[1]) - && REGNO (operands[1]) == IR1_REGNO); - - if (use_ir1) - output_asm_insn (\"push\\tir1\", operands); - else - output_asm_insn (\"push\\tbk\", operands); - output_asm_insn (\"push\\tr0\", operands); - output_asm_insn (\"subi3\\t%1,%0,r0\", operands); - if (use_ir1) - { - output_asm_insn (\"ldiu\\tst,ir1\", operands); - output_asm_insn (\"or\\t07bh,ir1\", operands); - } - else - { - output_asm_insn (\"ldiu\\tst,bk\", operands); - output_asm_insn (\"or\\t07bh,bk\", operands); - } - output_asm_insn (\"subb3\\t%O1,%O0,r0\", operands); - if (use_ir1) - output_asm_insn (\"and3\\tir1,st,ir1\", operands); - else - output_asm_insn (\"and3\\tbk,st,bk\", operands); - output_asm_insn (\"pop\\tr0\", operands); - if (use_ir1) - { - output_asm_insn (\"ldiu\\tir1,st\", operands); - output_asm_insn (\"pop\\tir1\", operands); - } - else - { - output_asm_insn (\"ldiu\\tbk,st\", operands); - output_asm_insn (\"pop\\tbk\", operands); - } - return \"\"; - }" - [(set_attr "type" "multi")]) - - -(define_insn "cmphi_cc" - [(set (reg:CC 21) - (unspec:CC [(compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>"))] UNSPEC_CMPHI)) - (clobber (match_scratch:QI 2 "=&d,&d")) - (clobber (match_scratch:QI 3 "=&c,&c"))] - "valid_operands (COMPARE, operands, HImode)" - "* - output_asm_insn (\"subi3\\t%1,%0,%2\", operands); - output_asm_insn (\"ldiu\\tst,%3\", operands); - output_asm_insn (\"or\\t07bh,%3\", operands); - output_asm_insn (\"subb3\\t%O1,%O0,%2\", operands); - output_asm_insn (\"and\\t%3,st\", operands); - return \"\";" - [(set_attr "type" "multi")]) - -(define_insn "cmphi_cc_noov" - [(set (reg:CC_NOOV 21) - (unspec:CC_NOOV [(compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>") - (match_operand:HI 1 "src_operand" "R,rS<>"))] UNSPEC_CMPHI)) - (clobber (match_scratch:QI 2 "=&d,&d")) - (clobber (match_scratch:QI 3 "=&c,&c"))] - "valid_operands (COMPARE, operands, HImode)" - "* - output_asm_insn (\"subi3\\t%1,%0,%2\", operands); - output_asm_insn (\"ldiu\\tst,%3\", operands); - output_asm_insn (\"or\\t07bh,%3\", operands); - output_asm_insn (\"subb3\\t%O1,%O0,%2\", operands); - output_asm_insn (\"and\\t%3,st\", operands); - return \"\";" - [(set_attr "type" "multi")]) - -(define_expand "mulhi3" - [(parallel [(set (match_operand:HI 0 "reg_operand" "") - (mult:HI (match_operand:HI 1 "src_operand" "") - (match_operand:HI 2 "src_operand" ""))) - (clobber (reg:CC 21))])] - "" - "c4x_emit_libcall3 (optab_libfunc (smul_optab, HImode), - MULT, HImode, operands); - DONE;") - - -; -; PEEPHOLES -; - -; dbCC peepholes -; -; Turns -; loop: -; [ ... ] -; bCC label ; abnormal loop termination -; dbu aN, loop ; normal loop termination -; -; Into -; loop: -; [ ... ] -; dbCC aN, loop -; bCC label -; -; Which moves the bCC condition outside the inner loop for free. -; -(define_peephole - [(set (pc) (if_then_else (match_operator 3 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc))) - (parallel - [(set (pc) - (if_then_else - (ge (plus:QI (match_operand:QI 0 "addr_reg_operand" "+a") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1))) - (use (reg:QI 20)) - (clobber (reg:CC_NOOV 21))])] - "! c4x_label_conflict (insn, operands[2], operands[1])" - "db%I3\\t%0,%l1\\n\\tb%3\\t%l2" - [(set_attr "type" "multi")]) - -(define_peephole - [(set (pc) (if_then_else (match_operator 3 "comparison_operator" - [(reg:CC 21) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc))) - (parallel - [(set (pc) - (if_then_else - (ne (match_operand:QI 0 "addr_reg_operand" "+a") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:QI (match_dup 0) - (const_int -1)))])] - "! c4x_label_conflict (insn, operands[2], operands[1])" - "db%I3\\t%0,%l1\\n\\tb%3\\t%l2" - [(set_attr "type" "multi")]) - -; -; Peepholes to convert 'call label; rets' into jump label -; - -(define_peephole - [(parallel [(call (mem:QI (match_operand:QI 0 "call_address_operand" "")) - (match_operand:QI 1 "general_operand" "")) - (clobber (reg:QI 31))]) - (return)] - "! c4x_null_epilogue_p ()" - "* - if (REG_P (operands[0])) - return \"bu%#\\t%C0\"; - else - return \"br%#\\t%C0\";" - [(set_attr "type" "jump")]) - -(define_peephole - [(parallel [(set (match_operand 0 "" "") - (call (mem:QI (match_operand:QI 1 "call_address_operand" "")) - (match_operand:QI 2 "general_operand" ""))) - (clobber (reg:QI 31))]) - (return)] - "! c4x_null_epilogue_p ()" - "* - if (REG_P (operands[1])) - return \"bu%#\\t%C1\"; - else - return \"br%#\\t%C1\";" - [(set_attr "type" "jump")]) - - -; This peephole should be unnecessary with my patches to flow.c -; for better autoincrement detection -(define_peephole - [(set (match_operand:QF 0 "ext_low_reg_operand" "") - (mem:QF (match_operand:QI 1 "addr_reg_operand" ""))) - (set (match_operand:QF 2 "ext_low_reg_operand" "") - (mem:QF (plus:QI (match_dup 1) (const_int 1)))) - (parallel [(set (match_dup 1) (plus:QI (match_dup 1) (const_int 2))) - (clobber (reg:CC_NOOV 21))])] - "" - "ldf\\t*%1++,%0\\n\\tldf\\t*%1++,%2") - - -; This peephole should be unnecessary with my patches to flow.c -; for better autoincrement detection -(define_peephole - [(set (mem:QF (match_operand:QI 0 "addr_reg_operand" "")) - (match_operand:QF 1 "ext_low_reg_operand" "")) - (set (mem:QF (plus:QI (match_dup 0) (const_int 1))) - (match_operand:QF 2 "ext_low_reg_operand" "")) - (parallel [(set (match_dup 0) (plus:QI (match_dup 0) (const_int 2))) - (clobber (reg:CC_NOOV 21))])] - "" - "stf\\t%1,*%0++\\n\\tstf\\t%2,*%0++") - - -; The following two peepholes remove an unnecessary load -; often found at the end of a function. These peepholes -; could be generalized to other binary operators. They shouldn't -; be required if we run a post reload mop-up pass. -(define_peephole - [(parallel [(set (match_operand:QF 0 "ext_reg_operand" "") - (plus:QF (match_operand:QF 1 "ext_reg_operand" "") - (match_operand:QF 2 "ext_reg_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QF 3 "ext_reg_operand" "") - (match_dup 0))] - "dead_or_set_p (insn, operands[0])" - "addf3\\t%2,%1,%3") - -(define_peephole - [(parallel [(set (match_operand:QI 0 "reg_operand" "") - (plus:QI (match_operand:QI 1 "reg_operand" "") - (match_operand:QI 2 "reg_operand" ""))) - (clobber (reg:CC_NOOV 21))]) - (set (match_operand:QI 3 "reg_operand" "") - (match_dup 0))] - "dead_or_set_p (insn, operands[0])" - "addi3\\t%2,%1,%3") diff --git a/gcc/config/c4x/c4x.opt b/gcc/config/c4x/c4x.opt deleted file mode 100644 index b52f6f6bdd6..00000000000 --- a/gcc/config/c4x/c4x.opt +++ /dev/null @@ -1,139 +0,0 @@ -; Options for the TMS320C[34]x port of the compiler. - -; Copyright (C) 2005, 2007 Free Software Foundation, Inc. -; -; This file is part of GCC. -; -; GCC is free software; you can redistribute it and/or modify it under -; the terms of the GNU General Public License as published by the Free -; Software Foundation; either version 3, or (at your option) any later -; version. -; -; GCC is distributed in the hope that it will be useful, but WITHOUT ANY -; WARRANTY; without even the implied warranty of MERCHANTABILITY or -; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -; for more details. -; -; You should have received a copy of the GNU General Public License -; along with GCC; see the file COPYING3. If not see -; <http://www.gnu.org/licenses/>. - -m30 -Target RejectNegative -Generate code for C30 CPU - -m31 -Target RejectNegative -Generate code for C31 CPU - -m32 -Target RejectNegative -Generate code for C32 CPU - -m33 -Target RejectNegative -Generate code for C33 CPU - -m40 -Target RejectNegative -Generate code for C40 CPU - -m44 -Target RejectNegative -Generate code for C44 CPU - -maliases -Target Report Mask(ALIASES) -Assume that pointers may be aliased - -mbig -Target RejectNegative Report InverseMask(SMALL) -Big memory model - -mbk -Target Report Mask(BK) -Use the BK register as a general purpose register - -mcpu= -Target RejectNegative Joined --mcpu=CPU Generate code for CPU - -mdb -Target Report Mask(DB) -Enable use of DB instruction - -mdebug -Target Report Mask(DEBUG) -Enable debugging - -mdevel -Target Report Mask(DEVEL) -Enable new features under development - -mfast-fix -Target Report Mask(FAST_FIX) -Use fast but approximate float to integer conversion - -mforce -Target Report Mask(FORCE) -Force RTL generation to emit valid 3 operand insns - -mhoist -Target Report Mask(HOIST) -Force constants into registers to improve hoisting - -misr-dp-reload -Target Mask(PARANOID) MaskExists -Save DP across ISR in small memory model - -mloop-unsigned -Target Report Mask(LOOP_UNSIGNED) -Allow unsigned iteration counts for RPTB/DB - -mmemparm -Target RejectNegative Report Mask(MEMPARM) -Pass arguments on the stack - -mmpyi -Target Report Mask(MPYI) -Use MPYI instruction for C3x - -mparallel-insns -Target Report Mask(PARALLEL) -Enable parallel instructions - -mparallel-mpy -Target Report Mask(PARALLEL_MPY) -Enable MPY||ADD and MPY||SUB instructions - -mparanoid -Target Report Mask(PARANOID) -Save DP across ISR in small memory model - -mpreserve-float -Target Report Mask(PRESERVE_FLOAT) -Preserve all 40 bits of FP reg across call - -mregparm -Target RejectNegative Report InverseMask(MEMPARM) -Pass arguments in registers - -mrptb -Target Report Mask(RPTB) -Enable use of RTPB instruction - -mrpts -Target Report Mask(RPTS) -Enable use of RTPS instruction - -mrpts= -Target RejectNegative Joined UInteger Var(c4x_rpts_cycles) --mrpts=N Set the maximum number of iterations for RPTS to N - -msmall -Target RejectNegative Report Mask(SMALL) -Small memory model - -mti -Target Report Mask(TI) -Emit code compatible with TI tools diff --git a/gcc/config/c4x/libgcc.S b/gcc/config/c4x/libgcc.S deleted file mode 100644 index 8f801da6af7..00000000000 --- a/gcc/config/c4x/libgcc.S +++ /dev/null @@ -1,1502 +0,0 @@ -/* libgcc routines for the Texas Instruments TMS320C[34]x - Copyright (C) 1997,98, 1999 Free Software Foundation, Inc. - - Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz) - and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl). - - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -In addition to the permissions in the GNU General Public License, the -Free Software Foundation gives you unlimited permission to link the -compiled version of this file into combinations with other programs, -and to distribute those combinations without any restriction coming -from the use of this file. (The General Public License restrictions -do apply in other respects; for example, they cover modification of -the file, and distribution when not linked into a combine -executable.) - -This file is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; see the file COPYING. If not, write to -the Free Software Foundation, 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ - -; These routines are called using the standard TI register argument -; passing model. -; The following registers do not have to be saved: -; r0, r1, r2, r3, ar0, ar1, ar2, ir0, ir1, bk, rs, rc, re, (r9, r10, r11) -; -; Perform floating point divqf3 -; -; This routine performs a reciprocal of the divisor using the method -; described in the C30/C40 user manuals. It then multiplies that -; result by the dividend. -; -; Let r be the reciprocal of the divisor v and let the ith estimate -; of r be denoted by r[i]. An iterative approach can be used to -; improve the estimate of r, given an initial estimate r[0], where -; -; r[i + 1] = r[i] * (2.0 - v * r[i]) -; -; The normalized error e[i] at the ith iteration is -; -; e[i] = (r - r[i]) / r = (1 / v - r[i]) * v = (1 - v * r[i]) -; -; Note that -; -; e[i + 1] = (1 - v * r[i + 1]) = 1 - 2 * v * r[i] + v^2 + (r[i])^2 -; = (1 - v * r[i])^2 = (e[i])^2 - -; r2 dividend, r3 divisor, r0 quotient -; clobbers r1, ar1 -#ifdef L_divsf3 - .text - .global ___divqf3 -___divqf3: - -#ifdef _TMS320C4x - .if .REGPARM == 0 - lda sp,ar0 - ldf *-ar0(2), r3 - .endif - - pop ar1 ; Pop return address - -; r0 = estimate of r, r1 = tmp, r2 = dividend, r3 = divisor - rcpf r3, r0 ; Compute initial estimate r[0] - - mpyf3 r0, r3, r1 ; r1 = r[0] * v - subrf 2.0, r1 ; r1 = 2.0 - r[0] * v - mpyf r1, r0 ; r0 = r[0] * (2.0 - r[0] * v) = r[1] -; End of 1st iteration (16 bits accuracy) - - mpyf3 r0, r3, r1 ; r1 = r[1] * v - subrf 2.0, r1 ; r1 = 2.0 - r[1] * v - - bud ar1 ; Delayed branch - mpyf r1, r0 ; r0 = r[1] * (2.0 - r[1] * v) = r[2] -; End of 2nd iteration (32 bits accuracy) - .if .REGPARM == 0 - mpyf *-ar0(1), r0 ; Multiply by the dividend - .else - mpyf r2, r0 ; Multiply by the dividend - .endif - rnd r0 - ; Branch occurs here -#else - .if .REGPARM == 0 - ldiu sp,ar0 - ldf *-ar0(2), r3 - .endif - - pop ar1 ; Pop return address - -; Initial estimate r[0] = 1.0 * 2^(-e - 1) -; where v = m * 2^e - -; r0 = estimate of r, r1 = tmp, r2 = dividend, r3 = divisor - -; Calculate initial estimate r[0] - pushf r3 - pop r0 - not r0 ; r0 = -e - ; complement exponent = -e -1 - ; complement sign (side effect) - ; complement mantissa (almost 3 bit accurate) - push r0 - popf r0 ; r0 = 1.0 * e^(-e - 1) + inverted mantissa - ldf -1.0, r1 ; undo complement sign bit - xor r1, r0 - - mpyf3 r0, r3, r1 ; r1 = r[0] * v - subrf 2.0, r1 ; r1 = 2.0 - r[0] * v - mpyf r1, r0 ; r0 = r[0] * (2.0 - r[0] * v) = r[1] -; End of 1st iteration - - mpyf3 r0, r3, r1 ; r1 = r[1] * v - subrf 2.0, r1 ; r1 = 2.0 - r[1] * v - mpyf r1, r0 ; r0 = r[1] * (2.0 - r[1] * v) = r[2] -; End of 2nd iteration - - mpyf3 r0, r3, r1 ; r1 = r[2] * v - subrf 2.0, r1 ; r1 = 2.0 - r[2] * v - mpyf r1, r0 ; r0 = r[2] * (2.0 - r[2] * v) = r[3] -; End of 3rd iteration - - rnd r0 ; Minimize error in x[3]'s LSBs - -; Use modified last iteration -; r[4] = (r[3] * (1.0 - (v * r[3]))) + r[3] - mpyf3 r0, r3, r1 ; r1 = r[3] * v - subrf 1.0, r1 ; r1 = 1.0 - r[3] * v - mpyf r0, r1 ; r1 = r[3] * (1.0 - r[3] * v) - addf r1, r0 ; r0 = r[3] * (1.0 - r[3] * v) + r[3] = r[4] - - rnd r0 ; Minimize error in x[4]'s LSBs - - bud ar1 ; Delayed branch - - .if .REGPARM == 0 - ldfu *-ar0(1), r2 ; Dividend in mem has only 24 bits significance - .else - rnd r2 ; Minimize error in reg dividend's LSBs - ; since this may have 32 bit significance - .endif - - mpyf r2, r0 ; Multiply by the dividend - rnd r0 ; Round result to 32 bits - - ; Branch occurs here -#endif - -#endif -; -; Integer signed division -; -; ar2 dividend, r2 divisor, r0 quotient -; clobbers r1, r3, ar0, ar1, ir0, ir1, rc, rs, re -#ifdef L_divsi3 - .text - .global ___divqi3 - .ref udivqi3n -___divqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - - xor3 ar2, r2, r3 ; Get the sign - absi ar2, r0 - bvd divq32 - ldi r0, ar2 - absi r2, r2 - cmpi ar2, r2 ; Divisor > dividend? - - pop ir1 - bhid zero ; If so, return 0 - -; -; Normalize oeprands. Use difference exponents as shift count -; for divisor, and as repeat count for "subc" -; - float ar2, r1 ; Normalize dividend - pushf r1 ; Get as integer - pop ar0 - lsh -24, ar0 ; Get exponent - - float r2, r1 ; Normalize divisor - pushf r1 ; Get as integer - pop ir0 - lsh -24, ir0 ; Get exponent - - subi ir0, ar0 ; Get difference of exponents - lsh ar0, r2 ; Align divisor with dividend - -; -; Do count + 1 subtracts and shifts -; - rpts ar0 - subc r2, ar2 - -; -; Mask off the lower count+1 bits of ar2 -; - subri 31, ar0 ; Shift count is (32 - (ar0 + 1)) - lsh ar0, ar2 ; Shift left - negi ar0, ar0 - lsh3 ar0, ar2, r0 ; Shift right and put result in r0 - -; -; Check sign and negate result if necessary -; - bud ir1 ; Delayed return - negi r0, r1 ; Negate result - ash -31, r3 ; Check sign - ldinz r1, r0 ; If set, use negative result - ; Branch occurs here - -zero: bud ir1 ; Delayed branch - ldi 0, r0 - nop - nop - ; Branch occurs here -; -; special case where ar2 = abs(ar2) = 0x80000000. We handle this by -; calling unsigned divide and negating the result if necessary. -; -divq32: - push r3 ; Save sign - call udivqi3n - pop r3 - pop ir1 - bd ir1 - negi r0, r1 ; Negate result - ash -31, r3 ; Check sign - ldinz r1, r0 ; If set, use negative result - ; Branch occurs here -#endif -; -; -; ar2 dividend, r2 divisor, r0 quotient, -; clobbers r1, r3, ar0, ar1, ir0, ir1, rc, rs, re -#ifdef L_udivsi3 - .text - .global ___udivqi3 - .global udivqi3n -___udivqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - -udivqi3n: - pop ir1 - - cmpi ar2, r2 ; If divisor > dividend - bhi qzero ; return zero - ldi r2, ar1 ; Store divisor in ar1 - - tstb ar2, ar2 ; Check top bit, jump if set to special handler - bld div_32 ; Delayed branch - -; -; Get divisor exponent -; - float ar1, r1 ; Normalize the divisor - pushf r1 ; Get into int register - pop rc - ; branch occurs here - - bzd qzero ; if (float) divisor zero, return zero - - float ar2, r1 ; Normalize the dividend - pushf r1 ; Get into int register - pop ar0 - lsh -24, ar0 ; Get both the exponents - lsh -24, rc - - subi rc, ar0 ; Get the difference between the exponents - lsh ar0, ar1 ; Normalize the divisor with the dividend - -; -; Do count_1 subtracts and shifts -; - rpts ar0 - subc ar1, ar2 - -; -; mask off the lower count+1 bits -; - subri 31, ar0 ; Shift count (31 - (ar0+1)) - bud ir1 ; Delayed return - lsh3 ar0, ar2, r0 - negi ar0, ar0 - lsh ar0, r0 - ; Branch occurs here - -; -; Handle a full 32-bit dividend -; -div_32: tstb ar1, ar1 - bld qone ; if divisor high bit is one, the result is one - lsh -24, rc - subri 31, rc - lsh rc, ar1 ; Line up the divisor - -; -; Now divisor and dividend are aligned. Do first SUBC by hand, save -; of the forst quotient digit. Then, shift divisor right rather -; than shifting dividend left. This leaves a zero in the top bit of -; the dividend -; - ldi 1, ar0 ; Initizialize MSB of quotient - lsh rc, ar0 ; create a mask for MSBs - subi 1, ar0 ; mask is (2 << count) - 1 - - subi3 ar1, ar2, r1 - ldihs r1, ar2 - ldihs 1, r1 - ldilo 0, r1 - lsh rc, r1 - - lsh -1, ar1 - subi 1, rc -; -; do the rest of the shifts and subtracts -; - rpts rc - subc ar1, ar2 - - bud ir1 - and ar0, ar2 - or3 r1, ar2, r0 - nop - -qone: - bud ir1 - ldi 1, r0 - nop - nop - -qzero: - bud ir1 - ldi 0, r0 - nop - nop -#endif - -#ifdef L_umodsi3 - .text - .global ___umodqi3 - .global umodqi3n -___umodqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - -umodqi3n: - pop ir1 ; return address - cmpi ar2, r2 ; divisor > dividend ? - bhi uzero ; if so, return dividend - ldi r2, ar1 ; load divisor -; -; If top bit of dividend is set, handle specially. -; - tstb ar2, ar2 ; check top bit - bld umod_32 ; get divisor exponent, then jump. -; -; Get divisor exponent by converting to float. -; - float ar1, r1 ; normalize divisor - pushf r1 ; push as float - pop rc ; pop as int to get exponent - bzd uzero ; if (float)divisor was zero, return -; -; 31 or less bits in dividend. Get dividend exponent. -; - float ar2, r1 ; normalize dividend - pushf r1 ; push as float - pop ar0 ; pop as int to get exponent -; -; Use difference in exponents as shift count to line up MSBs. -; - lsh -24, rc ; divisor exponent - lsh -24, ar0 ; dividend exponent - subi rc, ar0 ; difference - lsh ar0, ar1 ; shift divisor up -; -; Do COUNT+1 subtract & shifts. -; - rpts ar0 - subc ar1, ar2 -; -; Remainder is in upper 31-COUNT bits. -; - bud ir1 ; delayed branch to return - addi 1, ar0 ; shift count is COUNT+1 - negi ar0, ar0 ; negate for right shift - lsh3 ar0, ar2, r0 ; shift to get result - ; Return occurs here - -; -; The following code handles cases of a full 32-bit dividend. Before -; SUBC can be used, the top bit must be cleared (otherwise SUBC can -; possibly shift a significant 1 out the top of the dividend). This -; is accomplished by first doing a normal subtraction, then proceeding -; with SUBCs. -; -umod_32: -; -; If the top bit of the divisor is set too, the remainder is simply -; the difference between the dividend and divisor. Otherwise, shift -; the divisor up to line up the MSBs. -; - tstb ar1, ar1 ; check divisor - bld uone ; if negative, remainder is diff - - lsh -24, rc ; divisor exponent - subri 31, rc ; shift count = 31 - exp - negi rc, ar0 ; used later as shift count - lsh rc, ar1 ; shift up to line up MSBs -; -; Now MSBs are aligned. Do first SUBC by hand using a plain subtraction. -; Then, shift divisor right rather than shifting dividend left. This leaves -; a 0 in the top bit of the dividend. -; - subi3 ar1, ar2, r1 ; subtract - ldihs r1, ar2 ; if positive, replace dividend - subi 1, rc ; first iteration is done - lsh -1, ar1 ; shift divisor down -; -; Do EXP subtract & shifts. -; - rpts rc - subc ar1, ar2 -; -; Quotient is in EXP+1 LSBs; shift remainder (in MSBs) down. -; - bud ir1 - lsh3 ar0, ar2, r0 ; COUNT contains -(EXP+1) - nop - nop -; -; Return (dividend - divisor). -; -uone: bud ir1 - subi3 r2, ar2, r0 - nop - nop -; -; Return dividend. -; -uzero: bud ir1 - ldi ar2, r0 ; set status from result - nop - nop -#endif - -#ifdef L_modsi3 - .text - .global ___modqi3 - .ref umodqi3n -___modqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - -; -; Determine sign of result. Get absolute value of operands. -; - ldi ar2, ar0 ; sign of result same as dividend - absi ar2, r0 ; make dividend positive - bvd mod_32 ; if still negative, escape - absi r2, r1 ; make divisor positive - ldi r1, ar1 ; save in ar1 - cmpi r0, ar1 ; divisor > dividend ? - - pop ir1 ; return address - bhid return ; if so, return dividend -; -; Normalize operands. Use difference in exponents as shift count -; for divisor, and as repeat count for SUBC. -; - float r1, r1 ; normalize divisor - pushf r1 ; push as float - pop rc ; pop as int - bzd return ; if (float)divisor was zero, return - - float r0, r1 ; normalize dividend - pushf r1 ; push as float - pop r1 ; pop as int - - lsh -24, rc ; get divisor exponent - lsh -24, r1 ; get dividend exponent - subi rc, r1 ; get difference in exponents - lsh r1, ar1 ; align divisor with dividend -; -; Do COUNT+1 subtract & shifts. -; - rpts r1 - subc ar1, r0 -; -; Remainder is in upper bits of R0 -; - addi 1, r1 ; shift count is -(r1+1) - negi r1, r1 - lsh r1, r0 ; shift right -; -; Check sign and negate result if necessary. -; -return: - bud ir1 ; delayed branch to return - negi r0, r1 ; negate result - cmpi 0, ar0 ; check sign - ldin r1, r0 ; if set, use negative result - ; Return occurs here -; -; The following code handles cases of a full 32-bit dividend. This occurs -; when R0 = abs(R0) = 080000000h. Handle this by calling the unsigned mod -; function, then negating the result if necessary. -; -mod_32: - push ar0 ; remember sign - call umodqi3n ; do divide - - brd return ; return - pop ar0 ; restore sign - pop ir1 ; return address - nop -#endif - -#ifdef L_unsfltconst - .section .const - .global ___unsfltconst -___unsfltconst: .float 4294967296.0 -#endif - -#ifdef L_unsfltcompare - .section .const - .global ___unsfltcompare -___unsfltcompare: .float 2147483648.0 -#endif - -; Integer 32-bit signed multiplication -; -; The TMS320C3x MPYI instruction takes two 24-bit signed integers -; and produces a 48-bit signed result which is truncated to 32-bits. -; -; A 32-bit by 32-bit multiplication thus requires a number of steps. -; -; Consider the product of two 32-bit signed integers, -; -; z = x * y -; -; where x = (b << 16) + a, y = (d << 16) + c -; -; This can be expressed as -; -; z = ((b << 16) + a) * ((d << 16) + c) -; -; = ((b * d) << 32) + ((b * c + a * d) << 16) + a * c -; -; Let z = (f << 16) + e where f < (1 << 16). -; -; Since we are only interested in a 32-bit result, we can ignore the -; (b * d) << 32 term, and thus -; -; f = b * c + a * d, e = a * c -; -; We can simplify things if we have some a priori knowledge of the -; operands, for example, if -32768 <= y <= 32767, then y = c and d = 0 and thus -; -; f = b * c, e = a * c -; -; ar2 multiplier, r2 multiplicand, r0 product -; clobbers r1, r2, r3 -#ifdef L_mulsi3 - .text - .global ___mulqi3 -___mulqi3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - - pop ir1 ; return address - ldi ar2, r0 ; - and 0ffffh, r0 ; a - lsh -16, ar2 ; b - ldi r2, r3 ; - and 0ffffh, r3 ; c - mpyi r3, ar2 ; c * b - lsh -16, r2 ; d - mpyi r0, r2 ; a * d - addi ar2, r2 ; c * b + a * d - bd ir1 ; delayed branch to return - lsh 16, r2 ; (c * b + a * d) << 16 - mpyi r3, r0 ; a * c - addi r2, r0 ; a * c + (c * b + a * d) << 16 -; branch occurs here - -#endif - -; -; Integer 64 by 64 multiply -; long1 and long2 on stack -; result in r0,r1 -; -#ifdef L_muldi3 - .text - .global ___mulhi3 -#ifdef _TMS320C4x -___mulhi3: - pop ar0 - ldi sp,ar2 - ldi *-ar2(1),r2 - ldi *-ar2(3),r3 - mpyi3 r2,r3,r0 - mpyuhi3 r2,r3,r1 - mpyi *-ar2(2),r2 - bd ar0 - mpyi *-ar2(0),r3 - addi r2,r1 - addi r3,r1 -#else -___mulhi3: - ldi sp,ar2 - ldi -16,rs - ldi *-ar2(2),ar0 - ldi *-ar2(4),ar1 - ldi ar0,r2 - and 0ffffh,r2 - ldi ar1,r3 - and 0ffffh,r3 - lsh rs,ar0 - lsh rs,ar1 - - mpyi r2,r3,r0 - mpyi ar0,ar1,r1 - mpyi r2,ar1,rc - lsh rs,rc,re - addi re,r1 - lsh 16,rc - addi rc,r0 - addc 0,r1 - mpyi r3,ar0,rc - lsh rs,rc,re - addi re,r1 - lsh 16,rc - addi rc,r0 - addc 0,r1 - - ldi *-ar2(1),ar0 - ldi ar0,r2 - and 0ffffh,r2 - lsh rs,ar0 - mpyi r2,r3,rc - addi rc,r1 - mpyi r2,ar1,rc - mpyi r3,ar0,re - addi re,rc - lsh 16,rc - addi rc,r1 - - ldi *-ar2(2),ar0 - ldi *-ar2(3),ar1 - ldi ar0,r2 - and 0ffffh,r2 - ldi ar1,r3 - and 0ffffh,r3 - lsh rs,ar0 - lsh rs,ar1 - mpyi r2,r3,rc - addi rc,r1 - mpyi r2,ar1,rc - mpyi r3,ar0,re - pop ar0 - bd ar0 - addi re,rc - lsh 16,rc - addi rc,r1 -#endif -#endif - -; -; Integer 32 by 32 multiply highpart unsigned -; src1 in ar2 -; src2 in r2 -; result in r0 -; -#ifdef L_umuldi3_high - .text - .global ___umulhi3_high -___umulhi3_high: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - - ldi -16,rs - ldi r2,r3 - and 0ffffh,r2 - ldi ar2,ar1 - and 0ffffh,ar2 - lsh rs,r3 - lsh rs,ar1 - - mpyi ar2,r2,r1 - mpyi ar1,r3,r0 - mpyi ar2,r3,rc - lsh rs,rc,re - addi re,r0 - lsh 16,rc - addi rc,r1 - addc 0,r0 - mpyi r2,ar1,rc - lsh rs,rc,re - addi re,r0 - pop ar0 - bd ar0 - lsh 16,rc - addi rc,r1 - addc 0,r0 -#endif - -; -; Integer 32 by 32 multiply highpart signed -; src1 in ar2 -; src2 in r2 -; result in r0 -; -#ifdef L_smuldi3_high - .text - .global ___smulhi3_high -___smulhi3_high: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - ldi *-ar0(2), r2 - .endif - - ldi -16,rs - ldi 0,rc - subi3 ar2,rc,r0 - ldi r2,r3 - ldilt r0,rc - subi3 r2,rc,r0 - ldi ar2,ar1 - tstb ar1,ar1 - ldilt r0,rc - and 0ffffh,r2 - and 0ffffh,ar2 - lsh rs,r3 - lsh rs,ar1 - - mpyi ar2,r2,r1 - mpyi ar1,r3,r0 - addi rc,r0 - mpyi ar2,r3,rc - lsh rs,rc,re - addi re,r0 - lsh 16,rc - addi rc,r1 - addc 0,r0 - mpyi r2,ar1,rc - lsh rs,rc,re - addi re,r0 - pop ar0 - bd ar0 - lsh 16,rc - addi rc,r1 - addc 0,r0 -#endif - -; -; Integer 64 by 64 unsigned divide -; long1 and long2 on stack -; divide in r0,r1 -; modulo in r2,r3 -; routine takes a maximum of 64*8+23=535 cycles = 21.4 us @ 50Mhz -; -#ifdef L_udivdi3 - .text - .global ___udivhi3 - .global ___udivide - .global ___umodulo - .ref udivqi3n - .ref umodqi3n -___udivhi3: - ldi sp,ar2 - ldi *-ar2(4),ar0 - ldi *-ar2(3),ar1 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - -___udivide: - or r1,ar1,r2 - bne udiv0 - ldi ar0,r2 - ldi r0,ar2 - call udivqi3n - ldiu 0,r1 - rets - -___umodulo: - or r1,ar1,r2 - bne udiv0 - ldi ar0,r2 - ldi r0,ar2 - call umodqi3n - ldi r0,r2 - ldiu 0,r3 - rets - -udiv0: - tstb ar1,ar1 - bne udiv1 - tstb ar0,ar0 - bn udiv1 - - ldiu 63,rc -#ifdef _TMS320C4x - rptbd udivend0 - ldiu 0,r2 - addi r0,r0 - rolc r1 -#else - ldiu 0,r2 - addi r0,r0 - rolc r1 - rptb udivend0 -#endif - - rolc r2 - subi3 ar0,r2,r3 - ldinc r3,r2 - rolc r0 -udivend0: - rolc r1 - - not r0 - not r1 - ldiu 0,r3 - rets -udiv1: - push r4 - push r5 - ldiu 63,rc - ldiu 0,r2 -#ifdef _TMS320C4x - rptbd udivend1 - ldiu 0,r3 - addi r0,r0 - rolc r1 -#else - ldiu 0,r3 - addi r0,r0 - rolc r1 - rptb udivend1 -#endif - - rolc r2 - rolc r3 - subi3 ar0,r2,r4 - subb3 ar1,r3,r5 - ldinc r4,r2 - ldinc r5,r3 - rolc r0 -udivend1: - rolc r1 - - not r0 - not r1 - pop r5 - pop r4 - rets -#endif - -; -; Integer 64 by 64 unsigned modulo -; long1 and long2 on stack -; result in r0,r1 -; -#ifdef L_umoddi3 - .text - .global ___umodhi3 - .ref ___modulo -___umodhi3: - ldi sp,ar2 - ldi *-ar2(4),ar0 - ldi *-ar2(3),ar1 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - call ___umodulo - pop ar0 - bd ar0 - ldi r2,r0 - ldi r3,r1 - nop -#endif - -; -; Integer 64 by 64 signed divide -; long1 and long2 on stack -; result in r0,r1 -; -#ifdef L_divdi3 - .text - .global ___divhi3 - .ref ___udivide -___divhi3: - ldi 0,ir0 - ldi sp,ar2 - ldi *-ar2(4),r0 - ldi *-ar2(3),r1 - bge div1 - not ir0 - negi r0 - negb r1 -div1: - ldi r0,ar0 - ldi r1,ar1 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - bge div2 - not ir0 - negi r0 - negb r1 -div2: - call ___udivide - tstb ir0,ir0 - bge div3 - negi r0 - negb r1 -div3: - rets -#endif - -; -; Integer 64 by 64 signed modulo -; long1 and long2 on stack -; result in r0,r1 -; -#ifdef L_moddi3 - .text - .global ___modhi3 - .ref ___umodulo -___modhi3: - ldi 0,ir0 - ldi sp,ar2 - ldi *-ar2(4),r0 - ldi *-ar2(3),r1 - bge mod1 - not ir0 - negi r0 - negb r1 -mod1: - ldi r0,ar0 - ldi r1,ar1 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - bge mod2 - not ir0 - negi r0 - negb r1 -mod2: - call ___umodulo - ldi r2,r0 - ldi r3,r1 - tstb ir0,ir0 - bge mod3 - negi r0 - negb r1 -mod3: - rets -#endif - -; -; double to signed long long conversion -; input in r2 -; result in r0,r1 -; -#ifdef L_fix_truncsfdi2 - .text - .global ___fix_truncqfhi2 - .ref ufix_truncqfhi2n -___fix_truncqfhi2: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(1), r2 - .endif - - cmpf 0.0,r2 - bge ufix_truncqfhi2n - negf r2 - call ufix_truncqfhi2n - negi r0 - negb r1 - rets -#endif - -; -; double to unsigned long long conversion -; input in r2 -; result in r0,r1 -; -#ifdef L_ufix_truncsfdi2 - .text - .global ___ufix_truncqfhi2 - .global ufix_truncqfhi2n -___ufix_truncqfhi2: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(1), r2 - .endif - -ufix_truncqfhi2n: - cmpf 0.0,r2 - ble ufix1 - pushf r2 - pop r3 - ash -24,r3 - subi 31,r3 - cmpi 32,r3 - bgt ufix1 - cmpi -32,r3 - ble ufix1 - ldi 1,r0 - ash 31,r0 - or3 r0,r2,r0 - ldi r0,r1 - lsh3 r3,r0,r0 - subi 32,r3 - cmpi -32,r3 - ldile 0,r1 - lsh3 r3,r1,r1 - rets -ufix1: - ldi 0,r0 - ldi 0,r1 - rets -#endif - -; -; signed long long to double conversion -; input on stack -; result in r0 -; -#ifdef L_floatdisf2 - .text - .global ___floathiqf2 - .ref ufloathiqf2n -___floathiqf2: - ldi sp,ar2 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - bge ufloathiqf2n - negi r0 - negb r1 - call ufloathiqf2n - negf r0 - rets -#endif - -; -; unsigned long long to double conversion -; input on stack -; result in r0 -; -#ifdef L_ufloatdisf2 - .text - .global ___ufloathiqf2 - .global ufloathiqf2n - .ref ___unsfltconst -___ufloathiqf2: - ldi sp,ar2 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 -ufloathiqf2n: - .if .BIGMODEL -#ifdef _TMS320C4x - ldpk @___unsfltconst -#else - ldp @___unsfltconst -#endif - .endif - ldf @___unsfltconst,r2 - float r0 - bge uflt1 - addf r2,r0 -uflt1: - float r1 - bge uflt2 - addf r2,r1 -uflt2: -#ifdef _TMS320C4x - pop r3 - bd r3 - mpyf r2,r1 - addf r1,r0 - nop -#else - ldf r1,r3 - and 0ffh,r3 - norm r3,r3 - mpyf r2,r3 - pop ar2 - bd ar2 - addf r3,r0 - mpyf r2,r1 - addf r1,r0 -#endif -#endif - -; -; long double to signed long long conversion -; input in r2 -; result in r0,r1 -; -#ifdef L_fix_truncdfdi2 - .text - .global ___fix_trunchfhi2 - .ref ufix_trunchfhi2n -___fix_trunchfhi2: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(2), r2 - ldi *-ar0(1), r2 - .endif - - cmpf 0.0,r2 - bge ufix_trunchfhi2n - negf r2 - call ufix_trunchfhi2n - negi r0 - negb r1 - rets -#endif - -; -; long double to unsigned long long conversion -; input in r2 -; result in r0,r1 -; -#ifdef L_ufix_truncdfdi2 - .text - .global ___ufix_trunchfhi2 - .global ufix_trunchfhi2n -___ufix_trunchfhi2: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(2), r2 - ldi *-ar0(1), r2 - .endif - -ufix_trunchfhi2n: - cmpf 0.0,r2 - ble ufixh1 - pushf r2 - pop r3 - ash -24,r3 - subi 31,r3 - cmpi 32,r3 - bgt ufixh1 - cmpi -32,r3 - ble ufixh1 - ldi 1,r0 - ash 31,r0 - or3 r0,r2,r0 - ldi r0,r1 - lsh3 r3,r0,r0 - subi 32,r3 - cmpi -32,r3 - ldile 0,r1 - lsh3 r3,r1,r1 - rets -ufixh1: - ldi 0,r0 - ldi 0,r1 - rets -#endif - -; -; signed long long to long double conversion -; input on stack -; result in r0 -; -#ifdef L_floatdidf2 - .text - .global ___floathihf2 - .ref ufloathihf2n -___floathihf2: - ldi sp,ar2 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 - bge ufloathihf2n - negi r0 - negb r1 - call ufloathihf2n - negf r0 - rets -#endif - -; -; unsigned long long to double conversion -; input on stack -; result in r0 -; -#ifdef L_ufloatdidf2 - .text - .global ___ufloathihf2 - .global ufloathihf2n - .ref ___unsfltconst -___ufloathihf2: - ldi sp,ar2 - ldi *-ar2(2),r0 - ldi *-ar2(1),r1 -ufloathihf2n - .if .BIGMODEL -#ifdef _TMS320C4x - ldpk @___unsfltconst -#else - ldp @___unsfltconst -#endif - .endif - ldf @___unsfltconst,r2 - float r0 - bge uflth1 - addf r2,r0 -uflth1: - float r1 - bge uflth2 - addf r2,r1 -uflth2: -#ifdef _TMS320C4x - pop r3 - bd r3 - mpyf r2,r1 - addf r1,r0 - nop -#else - ldf r1,r3 - and 0ffh,r3 - norm r3,r3 - mpyf r2,r3 - pop ar2 - bd ar2 - addf r3,r0 - mpyf r2,r1 - addf r1,r0 -#endif -#endif - -; -; calculate ffs -; input in ar2 -; result in r0 -; -#ifdef L_ffs - .global ___ffs - .ref ___unsfltconst - .text -___ffs: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldi *-ar0(1), ar2 - .endif - - negi ar2,r0 - and ar2,r0 - float r0,r0 - ldfu 0.0,r1 - .if .BIGMODEL -#ifdef _TMS320C4x - ldpk @___unsfltconst -#else - ldp @___unsfltconst -#endif - .endif - ldflt @___unsfltconst,r1 - addf r1,r0 - pushf r0 - pop r0 - pop ar0 - bd ar0 - ash -24,r0 - ldilt -1,r0 - addi 1,r0 -#endif - -; -; calculate long double * long double -; input in r2, r3 -; output in r0 -; -#ifdef L_muldf3 - .global ___mulhf3 - .text -___mulhf3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(2), r2 - ldi *-ar0(1), r2 - ldf *-ar0(4), r3 - ldi *-ar0(3), r3 - .endif - - pop ar2 ; return ad - ldf r2,r0 ; copy lsb0 - ldf r3,r1 ; copy lsb1 - and 0ffh,r0 ; mask lsb0 - and 0ffh,r1 ; mask lsb1 - norm r0,r0 ; correct lsb0 - norm r1,r1 ; correct lsb1 - mpyf r2,r1 ; arg0*lsb1 - mpyf r3,r0 ; arg1*lsb0 - bd ar2 ; return (delayed) - addf r0,r1 ; arg0*lsb1 + arg1*lsb0 - mpyf r2,r3,r0 ; msb0*msb1 - addf r1,r0 ; msb0*msb1 + arg0*lsb1 + arg1*lsb0 -#endif - -; -; calculate long double / long double -; r2 dividend, r3 divisor, r0 quotient -; -#ifdef L_divdf3 - .global ___divhf3 - .text -___divhf3: - .if .REGPARM == 0 -#ifdef _TMS320C4x - lda sp,ar0 -#else - ldiu sp,ar0 -#endif - ldf *-ar0(2), r2 - ldi *-ar0(1), r2 - ldf *-ar0(4), r3 - ldi *-ar0(3), r3 - .endif - -#ifdef _TMS320C4x - pop ar1 - rcpf r3, r0 - mpyf3 r0, r3, r1 - subrf 2.0, r1 - mpyf r1, r0 - mpyf3 r0, r3, r1 - bud ar1 - subrf 2.0, r1 - mpyf r1, r0 - mpyf r2, r0 -#else - pop ar1 - pushf r3 - pop r0 - not r0 - push r0 - popf r0 - ldf -1.0, r1 - xor r1, r0 - - mpyf3 r0, r3, r1 ; r1 = r[0] * v - subrf 2.0, r1 ; r1 = 2.0 - r[0] * v - mpyf r1, r0 ; r0 = r[0] * (2.0 - r[0] * v) = r[1] -; End of 1st iteration - - mpyf3 r0, r3, r1 ; r1 = r[1] * v - subrf 2.0, r1 ; r1 = 2.0 - r[1] * v - mpyf r1, r0 ; r0 = r[1] * (2.0 - r[1] * v) = r[2] -; End of 2nd iteration - - mpyf3 r0, r3, r1 ; r1 = r[2] * v - subrf 2.0, r1 ; r1 = 2.0 - r[2] * v - mpyf r1, r0 ; r0 = r[2] * (2.0 - r[2] * v) = r[3] -; End of 3rd iteration - - or 080h, r0 - rnd r0 - -; mpyf3 r0, r3, r1 ; r1 = r[3] * v - push r4 - pushf r4 - mpyf r0, r3, r1 - - ldf r0, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r3, r4 - addf r4, r1 - - ldf r3, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r0, r4 - addf r4, r1 - - subrf 2.0, r1 ; r1 = 2.0 - r[3] * v - - mpyf r1, r0, r3 ; r3 = r[3] * (2.0 - r[3] * v) = r[5] - - ldf r1, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r0, r4 - addf r4, r3 - - ldf r0, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r1, r4 - addf r4, r3 - - mpyf r2, r3, r0 ; Multiply by the dividend - - ldf r2, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r3, r4 - addf r4, r0 - - ldf r3, r4 - and 0ffh, r4 - norm r4, r4 - mpyf r2, r4 - bd ar1 - addf r4, r0 - - popf r4 - pop r4 -#endif -#endif diff --git a/gcc/config/c4x/predicates.md b/gcc/config/c4x/predicates.md deleted file mode 100644 index a4e04d7a710..00000000000 --- a/gcc/config/c4x/predicates.md +++ /dev/null @@ -1,403 +0,0 @@ -;; Predicate definitions for TMS320C[34]x. -;; Copyright (C) 2005, 2007 Free Software Foundation, Inc. -;; -;; This file is part of GCC. -;; -;; GCC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. -;; -;; GCC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -;; Nonzero if OP is a floating point value with value 0.0. - -(define_predicate "fp_zero_operand" - (match_code "const_double") -{ - REAL_VALUE_TYPE r; - - if (GET_CODE (op) != CONST_DOUBLE) - return 0; - REAL_VALUE_FROM_CONST_DOUBLE (r, op); - return REAL_VALUES_EQUAL (r, dconst0); -}) - -;; TODO: Add a comment here. - -(define_predicate "const_operand" - (match_code "const_int,const_double") -{ - switch (mode) - { - case QFmode: - case HFmode: - if (GET_CODE (op) != CONST_DOUBLE - || GET_MODE (op) != mode - || GET_MODE_CLASS (mode) != MODE_FLOAT) - return 0; - - return c4x_immed_float_p (op); - -#if Pmode != QImode - case Pmode: -#endif - case QImode: - if (GET_CODE (op) != CONST_INT - || (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode) - || GET_MODE_CLASS (mode) != MODE_INT) - return 0; - - return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op)); - - case HImode: - return 0; - - default: - return 0; - } -}) - -;; TODO: Add a comment here. - -(define_predicate "stik_const_operand" - (match_code "const_int") -{ - return c4x_K_constant (op); -}) - -;; TODO: Add a comment here. - -(define_predicate "not_const_operand" - (match_code "const_int") -{ - return c4x_N_constant (op); -}) - -;; TODO: Add a comment here. - -(define_predicate "reg_operand" - (match_code "reg,subreg") -{ - if (GET_CODE (op) == SUBREG - && GET_MODE (op) == QFmode) - return 0; - return register_operand (op, mode); -}) - -;; TODO: Add a comment here. - -(define_predicate "reg_or_const_operand" - (match_code "reg,subreg,const_int,const_double") -{ - return reg_operand (op, mode) || const_operand (op, mode); -}) - -;; Extended precision register R0-R1. - -(define_predicate "r0r1_reg_operand" - (match_code "reg,subreg") -{ - if (! reg_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_R0R1_OR_PSEUDO_REG (op); -}) - -;; Extended precision register R2-R3. - -(define_predicate "r2r3_reg_operand" - (match_code "reg,subreg") -{ - if (! reg_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_R2R3_OR_PSEUDO_REG (op); -}) - -;; Low extended precision register R0-R7. - -(define_predicate "ext_low_reg_operand" - (match_code "reg,subreg") -{ - if (! reg_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REG (op); -}) - -;; Extended precision register. - -(define_predicate "ext_reg_operand" - (match_code "reg,subreg") -{ - if (! reg_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (! REG_P (op)) - return 0; - return IS_EXT_OR_PSEUDO_REG (op); -}) - -;; Standard precision register. - -(define_predicate "std_reg_operand" - (match_code "reg,subreg") -{ - if (! reg_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return REG_P (op) && IS_STD_OR_PSEUDO_REG (op); -}) - -;; Standard precision or normal register. - -(define_predicate "std_or_reg_operand" - (match_code "reg,subreg") -{ - if (reload_in_progress) - return std_reg_operand (op, mode); - return reg_operand (op, mode); -}) - -;; Address register. - -(define_predicate "addr_reg_operand" - (match_code "reg,subreg") -{ - if (! reg_operand (op, mode)) - return 0; - return c4x_a_register (op); -}) - -;; Index register. - -(define_predicate "index_reg_operand" - (match_code "reg,subreg") -{ - if (! reg_operand (op, mode)) - return 0; - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - return c4x_x_register (op); -}) - -;; DP register. - -(define_predicate "dp_reg_operand" - (match_code "reg") -{ - return REG_P (op) && IS_DP_OR_PSEUDO_REG (op); -}) - -;; SP register. - -(define_predicate "sp_reg_operand" - (match_code "reg") -{ - return REG_P (op) && IS_SP_OR_PSEUDO_REG (op); -}) - -;; ST register. - -(define_predicate "st_reg_operand" - (match_code "reg") -{ - return REG_P (op) && IS_ST_OR_PSEUDO_REG (op); -}) - -;; RC register. - -(define_predicate "rc_reg_operand" - (match_code "reg") -{ - return REG_P (op) && IS_RC_OR_PSEUDO_REG (op); -}) - -;; TODO: Add a comment here. - -(define_predicate "call_address_operand" - (match_code "reg,symbol_ref,label_ref,const") -{ - return (REG_P (op) || symbolic_address_operand (op, mode)); -}) - -;; Check dst operand of a move instruction. - -(define_predicate "dst_operand" - (match_code "subreg,reg,mem") -{ - if (GET_CODE (op) == SUBREG - && mixed_subreg_operand (op, mode)) - return 0; - - if (REG_P (op)) - return reg_operand (op, mode); - - return nonimmediate_operand (op, mode); -}) - -;; Check src operand of two operand arithmetic instructions. - -(define_predicate "src_operand" - (match_code "subreg,reg,mem,const_int,const_double") -{ - if (GET_CODE (op) == SUBREG - && mixed_subreg_operand (op, mode)) - return 0; - - if (REG_P (op)) - return reg_operand (op, mode); - - if (mode == VOIDmode) - mode = GET_MODE (op); - - if (GET_CODE (op) == CONST_INT) - return (mode == QImode || mode == Pmode || mode == HImode) - && c4x_I_constant (op); - - /* We don't like CONST_DOUBLE integers. */ - if (GET_CODE (op) == CONST_DOUBLE) - return c4x_H_constant (op); - - /* Disallow symbolic addresses. Only the predicate - symbolic_address_operand will match these. */ - if (GET_CODE (op) == SYMBOL_REF - || GET_CODE (op) == LABEL_REF - || GET_CODE (op) == CONST) - return 0; - - /* If TARGET_LOAD_DIRECT_MEMS is nonzero, disallow direct memory - access to symbolic addresses. These operands will get forced - into a register and the movqi expander will generate a - HIGH/LO_SUM pair if TARGET_EXPOSE_LDP is nonzero. */ - if (GET_CODE (op) == MEM - && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF - || GET_CODE (XEXP (op, 0)) == LABEL_REF - || GET_CODE (XEXP (op, 0)) == CONST))) - return !TARGET_EXPOSE_LDP && - ! TARGET_LOAD_DIRECT_MEMS && GET_MODE (op) == mode; - - return general_operand (op, mode); -}) - -;; TODO: Add a comment here. - -(define_predicate "src_hi_operand" - (match_code "subreg,reg,mem,const_double") -{ - if (c4x_O_constant (op)) - return 1; - return src_operand (op, mode); -}) - -;; Check src operand of two operand logical instructions. - -(define_predicate "lsrc_operand" - (match_code "subreg,reg,mem,const_int,const_double") -{ - if (mode == VOIDmode) - mode = GET_MODE (op); - - if (mode != QImode && mode != Pmode) - fatal_insn ("mode not QImode", op); - - if (GET_CODE (op) == CONST_INT) - return c4x_L_constant (op) || c4x_J_constant (op); - - return src_operand (op, mode); -}) - -;; Check src operand of two operand tricky instructions. - -(define_predicate "tsrc_operand" - (match_code "subreg,reg,mem,const_int,const_double") -{ - if (mode == VOIDmode) - mode = GET_MODE (op); - - if (mode != QImode && mode != Pmode) - fatal_insn ("mode not QImode", op); - - if (GET_CODE (op) == CONST_INT) - return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op); - - return src_operand (op, mode); -}) - -;; Check src operand of two operand non immediate instructions. - -(define_predicate "nonimmediate_src_operand" - (match_code "subreg,reg,mem") -{ - if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE) - return 0; - - return src_operand (op, mode); -}) - -;; Check logical src operand of two operand non immediate instructions. - -(define_predicate "nonimmediate_lsrc_operand" - (match_code "subreg,reg,mem") -{ - if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE) - return 0; - - return lsrc_operand (op, mode); -}) - -;; Match any operand. - -(define_predicate "any_operand" - (match_code "subreg,reg,mem,const_int,const_double") -{ - return 1; -}) - -;; Check for indirect operands allowable in parallel instruction. - -(define_predicate "par_ind_operand" - (match_code "mem") -{ - if (mode != VOIDmode && mode != GET_MODE (op)) - return 0; - - return c4x_S_indirect (op); -}) - -;; Check for operands allowable in parallel instruction. - -(define_predicate "parallel_operand" - (match_code "subreg,reg,mem") -{ - return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode); -}) - -;; Symbolic address operand. - -(define_predicate "symbolic_address_operand" - (match_code "symbol_ref,label_ref,const") -{ - switch (GET_CODE (op)) - { - case CONST: - case SYMBOL_REF: - case LABEL_REF: - return 1; - default: - return 0; - } -}) diff --git a/gcc/config/c4x/rtems.h b/gcc/config/c4x/rtems.h deleted file mode 100644 index ea44707e2f2..00000000000 --- a/gcc/config/c4x/rtems.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Definitions of RTEMS executing on an TMS320C[34]x using coff - Copyright (C) 1996, 1997, 1999, 2002, 2007 Free Software Foundation, Inc. - Contributed by Joel Sherrill (joel@OARcorp.com). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -/* Specify predefined symbols in preprocessor. */ - -#define TARGET_OS_CPP_BUILTINS() \ - do { \ - builtin_define ("__rtems__"); \ - builtin_define ("__USE_INIT_FINI__"); \ - builtin_assert ("system=rtems"); \ - } while (0) diff --git a/gcc/config/c4x/t-c4x b/gcc/config/c4x/t-c4x deleted file mode 100644 index befadccc39e..00000000000 --- a/gcc/config/c4x/t-c4x +++ /dev/null @@ -1,20 +0,0 @@ -LIB1ASMSRC = c4x/libgcc.S -LIB1ASMFUNCS = _divsf3 _divsi3 _udivsi3 _umodsi3 _modsi3 _mulsi3 \ - _muldf3 _divdf3 _unsfltconst _unsfltcompare \ - _muldi3 _umuldi3_high _smuldi3_high _divdi3 _moddi3 _umoddi3 _udivdi3 \ - _fix_truncsfdi2 _ufix_truncsfdi2 _floatdisf2 _ufloatdisf2 \ - _floatdidf2 _ufloatdidf2 _fix_truncdfdi2 _ufix_truncdfdi2 _ffs - -TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit - -c4x-c.o: $(srcdir)/config/c4x/c4x-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - $(TM_H) $(TREE_H) toplev.h $(CPPLIB_H) c-pragma.h $(TM_P_H) - $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/c4x/c4x-c.c - -MULTILIB_OPTIONS = m30 msmall mmemparm -MULTILIB_DIRNAMES = c3x small mem -MULTILIB_MATCHES = m30=mcpu?30 m30=mcpu?31 m30=mcpu?32 m30=mcpu?33 m30=m31 m30=m32 m30=m33 -MULTILIB_EXCEPTIONS = -MULTILIB_EXTRA_OPTS = -LIBGCC = stmp-multilib -INSTALL_LIBGCC = install-multilib diff --git a/gcc/config/c4x/t-rtems b/gcc/config/c4x/t-rtems deleted file mode 100644 index 52dc7eaf3a3..00000000000 --- a/gcc/config/c4x/t-rtems +++ /dev/null @@ -1,10 +0,0 @@ -# Custom RTEMS multilibs - -# We'd actually want to support -msmall, but it trips a bug in gcc -# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14436 -# -# MULTILIB_OPTIONS = m30 msmall mmemparm -# MULTILIB_DIRNAMES = c3x small mem - -MULTILIB_OPTIONS = m30 mmemparm -MULTILIB_DIRNAMES = c3x mem diff --git a/gcc/defaults.h b/gcc/defaults.h index a217276746c..ef2dcb76981 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -1,6 +1,6 @@ /* Definitions of various defaults for tm.h macros. Copyright (C) 1992, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2007 + 2005, 2007, 2008 Free Software Foundation, Inc. Contributed by Ron Guilmette (rfg@monkeys.com) @@ -655,7 +655,6 @@ along with GCC; see the file COPYING3. If not see #define UNKNOWN_FLOAT_FORMAT 0 #define IEEE_FLOAT_FORMAT 1 #define VAX_FLOAT_FORMAT 2 -#define C4X_FLOAT_FORMAT 3 /* Default to IEEE float if not specified. Nearly all machines use it. */ #ifndef TARGET_FLOAT_FORMAT diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 34a5a460eff..73c823fa45c 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1,5 +1,5 @@ -@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, -@c 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001, +@c 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -2336,7 +2336,7 @@ This attribute is ignored for R8C target. @item interrupt @cindex interrupt handler functions -Use this attribute on the ARM, AVR, C4x, CRX, M32C, M32R/D, m68k, MS1, +Use this attribute on the ARM, AVR, CRX, M32C, M32R/D, m68k, MS1, and Xstormy16 ports to indicate that the specified function is an interrupt handler. The compiler will generate function entry and exit sequences suitable for use in an interrupt handler when this attribute @@ -2484,7 +2484,7 @@ defined by shared libraries. @item naked @cindex function without a prologue/epilogue code -Use this attribute on the ARM, AVR, C4x, IP2K and SPU ports to indicate that +Use this attribute on the ARM, AVR, IP2K and SPU ports to indicate that the specified function does not need prologue/epilogue sequences generated by the compiler. It is up to the programmer to provide these sequences. @@ -10892,7 +10892,6 @@ Do not apply the @code{longcall} attribute to subsequent function declarations. @end table -@c Describe c4x pragmas here. @c Describe h8300 pragmas here. @c Describe sh pragmas here. @c Describe v850 pragmas here. diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 7ab605ff9e3..65d203e1950 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -45,7 +45,7 @@ @end ifset @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, -@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +@c 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. @c *** Converted to texinfo by Dean Wakerley, dean@wakerley.com @c IMPORTANT: whenever you modify this file, run `install.texi2html' to @@ -71,7 +71,7 @@ @c Part 2 Summary Description and Copyright @copying Copyright @copyright{} 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, -1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. @sp 1 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or @@ -2492,8 +2492,6 @@ information are. @item @uref{#bfin,,Blackfin} @item -@uref{#c4x,,c4x} -@item @uref{#dos,,DOS} @item @uref{#x-x-freebsd,,*-*-freebsd*} @@ -2824,36 +2822,6 @@ is available at @uref{http://blackfin.uclinux.org} @html <hr /> @end html -@heading @anchor{c4x}c4x - -Texas Instruments TMS320C3x and TMS320C4x Floating Point Digital Signal -Processors. These are used in embedded applications. There are no -standard Unix configurations. -@ifnothtml -@xref{TMS320C3x/C4x Options,, TMS320C3x/C4x Options, gcc, Using the -GNU Compiler Collection (GCC)}, -@end ifnothtml -@ifhtml -See ``TMS320C3x/C4x Options'' in the main manual -@end ifhtml -for the list of supported MCU types. - -GCC can be configured as a cross compiler for both the C3x and C4x -architectures on the same system. Use @samp{configure --target=c4x ---enable-languages="c,c++"} to configure. - - -Further installation notes and other useful information about C4x tools -can also be obtained from: - -@itemize @bullet -@item -@uref{http://www.elec.canterbury.ac.nz/c4x/,,http://www.elec.canterbury.ac.nz/c4x/} -@end itemize - -@html -<hr /> -@end html @heading @anchor{cris}CRIS CRIS is the CPU architecture in Axis Communications ETRAX system-on-a-chip diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 9ed20370ac4..a6bf47d495e 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -772,12 +772,6 @@ See RS/6000 and PowerPC Options. @emph{System V Options} @gccoptlist{-Qy -Qn -YP,@var{paths} -Ym,@var{dir}} -@emph{TMS320C3x/C4x Options} -@gccoptlist{-mcpu=@var{cpu} -mbig -msmall -mregparm -mmemparm @gol --mfast-fix -mmpyi -mbk -mti -mdp-isr-reload @gol --mrpts=@var{count} -mrptb -mdb -mloop-unsigned @gol --mparallel-insns -mparallel-mpy -mpreserve-float} - @emph{V850 Options} @gccoptlist{-mlong-calls -mno-long-calls -mep -mno-ep @gol -mprolog-function -mno-prolog-function -mspace @gol @@ -8257,7 +8251,6 @@ platform. * SPARC Options:: * SPU Options:: * System V Options:: -* TMS320C3x/C4x Options:: * V850 Options:: * VAX Options:: * VxWorks Options:: @@ -14335,158 +14328,6 @@ The assembler uses this option. @c the generic assembler that comes with Solaris takes just -Ym. @end table -@node TMS320C3x/C4x Options -@subsection TMS320C3x/C4x Options -@cindex TMS320C3x/C4x Options - -These @samp{-m} options are defined for TMS320C3x/C4x implementations: - -@table @gcctabopt - -@item -mcpu=@var{cpu_type} -@opindex mcpu -Set the instruction set, register set, and instruction scheduling -parameters for machine type @var{cpu_type}. Supported values for -@var{cpu_type} are @samp{c30}, @samp{c31}, @samp{c32}, @samp{c40}, and -@samp{c44}. The default is @samp{c40} to generate code for the -TMS320C40. - -@item -mbig-memory -@itemx -mbig -@itemx -msmall-memory -@itemx -msmall -@opindex mbig-memory -@opindex mbig -@opindex msmall-memory -@opindex msmall -Generates code for the big or small memory model. The small memory -model assumed that all data fits into one 64K word page. At run-time -the data page (DP) register must be set to point to the 64K page -containing the .bss and .data program sections. The big memory model is -the default and requires reloading of the DP register for every direct -memory access. - -@item -mbk -@itemx -mno-bk -@opindex mbk -@opindex mno-bk -Allow (disallow) allocation of general integer operands into the block -count register BK@. - -@item -mdb -@itemx -mno-db -@opindex mdb -@opindex mno-db -Enable (disable) generation of code using decrement and branch, -DBcond(D), instructions. This is enabled by default for the C4x. To be -on the safe side, this is disabled for the C3x, since the maximum -iteration count on the C3x is @math{2^{23} + 1} (but who iterates loops more than -@math{2^{23}} times on the C3x?). Note that GCC will try to reverse a loop so -that it can utilize the decrement and branch instruction, but will give -up if there is more than one memory reference in the loop. Thus a loop -where the loop counter is decremented can generate slightly more -efficient code, in cases where the RPTB instruction cannot be utilized. - -@item -mdp-isr-reload -@itemx -mparanoid -@opindex mdp-isr-reload -@opindex mparanoid -Force the DP register to be saved on entry to an interrupt service -routine (ISR), reloaded to point to the data section, and restored on -exit from the ISR@. This should not be required unless someone has -violated the small memory model by modifying the DP register, say within -an object library. - -@item -mmpyi -@itemx -mno-mpyi -@opindex mmpyi -@opindex mno-mpyi -For the C3x use the 24-bit MPYI instruction for integer multiplies -instead of a library call to guarantee 32-bit results. Note that if one -of the operands is a constant, then the multiplication will be performed -using shifts and adds. If the @option{-mmpyi} option is not specified for the C3x, -then squaring operations are performed inline instead of a library call. - -@item -mfast-fix -@itemx -mno-fast-fix -@opindex mfast-fix -@opindex mno-fast-fix -The C3x/C4x FIX instruction to convert a floating point value to an -integer value chooses the nearest integer less than or equal to the -floating point value rather than to the nearest integer. Thus if the -floating point number is negative, the result will be incorrectly -truncated an additional code is necessary to detect and correct this -case. This option can be used to disable generation of the additional -code required to correct the result. - -@item -mrptb -@itemx -mno-rptb -@opindex mrptb -@opindex mno-rptb -Enable (disable) generation of repeat block sequences using the RPTB -instruction for zero overhead looping. The RPTB construct is only used -for innermost loops that do not call functions or jump across the loop -boundaries. There is no advantage having nested RPTB loops due to the -overhead required to save and restore the RC, RS, and RE registers. -This is enabled by default with @option{-O2}. - -@item -mrpts=@var{count} -@itemx -mno-rpts -@opindex mrpts -@opindex mno-rpts -Enable (disable) the use of the single instruction repeat instruction -RPTS@. If a repeat block contains a single instruction, and the loop -count can be guaranteed to be less than the value @var{count}, GCC will -emit a RPTS instruction instead of a RPTB@. If no value is specified, -then a RPTS will be emitted even if the loop count cannot be determined -at compile time. Note that the repeated instruction following RPTS does -not have to be reloaded from memory each iteration, thus freeing up the -CPU buses for operands. However, since interrupts are blocked by this -instruction, it is disabled by default. - -@item -mloop-unsigned -@itemx -mno-loop-unsigned -@opindex mloop-unsigned -@opindex mno-loop-unsigned -The maximum iteration count when using RPTS and RPTB (and DB on the C40) -is @math{2^{31} + 1} since these instructions test if the iteration count is -negative to terminate the loop. If the iteration count is unsigned -there is a possibility than the @math{2^{31} + 1} maximum iteration count may be -exceeded. This switch allows an unsigned iteration count. - -@item -mti -@opindex mti -Try to emit an assembler syntax that the TI assembler (asm30) is happy -with. This also enforces compatibility with the API employed by the TI -C3x C compiler. For example, long doubles are passed as structures -rather than in floating point registers. - -@item -mregparm -@itemx -mmemparm -@opindex mregparm -@opindex mmemparm -Generate code that uses registers (stack) for passing arguments to functions. -By default, arguments are passed in registers where possible rather -than by pushing arguments on to the stack. - -@item -mparallel-insns -@itemx -mno-parallel-insns -@opindex mparallel-insns -@opindex mno-parallel-insns -Allow the generation of parallel instructions. This is enabled by -default with @option{-O2}. - -@item -mparallel-mpy -@itemx -mno-parallel-mpy -@opindex mparallel-mpy -@opindex mno-parallel-mpy -Allow the generation of MPY||ADD and MPY||SUB parallel instructions, -provided @option{-mparallel-insns} is also specified. These instructions have -tight register constraints which can pessimize the code generation -of large functions. - -@end table - @node V850 Options @subsection V850 Options @cindex V850 Options diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index e79444c5496..fba9f9448fb 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -1,5 +1,5 @@ @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001, -@c 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +@c 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -2847,88 +2847,6 @@ An immediate for the @code{iohl} instruction. const_int is sign extended to 128 @end table -@item TMS320C3x/C4x---@file{config/c4x/c4x.h} -@table @code -@item a -Auxiliary (address) register (ar0-ar7) - -@item b -Stack pointer register (sp) - -@item c -Standard (32-bit) precision integer register - -@item f -Extended (40-bit) precision register (r0-r11) - -@item k -Block count register (bk) - -@item q -Extended (40-bit) precision low register (r0-r7) - -@item t -Extended (40-bit) precision register (r0-r1) - -@item u -Extended (40-bit) precision register (r2-r3) - -@item v -Repeat count register (rc) - -@item x -Index register (ir0-ir1) - -@item y -Status (condition code) register (st) - -@item z -Data page register (dp) - -@item G -Floating-point zero - -@item H -Immediate 16-bit floating-point constant - -@item I -Signed 16-bit constant - -@item J -Signed 8-bit constant - -@item K -Signed 5-bit constant - -@item L -Unsigned 16-bit constant - -@item M -Unsigned 8-bit constant - -@item N -Ones complement of unsigned 16-bit constant - -@item O -High 16-bit constant (32-bit constant with 16 LSBs zero) - -@item Q -Indirect memory reference with signed 8-bit or index register displacement - -@item R -Indirect memory reference with unsigned 5-bit displacement - -@item S -Indirect memory reference with 1 bit or index register displacement - -@item T -Direct memory reference - -@item U -Symbolic address - -@end table - @item S/390 and zSeries---@file{config/s390/s390.h} @table @code @item a diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 89d43026f89..e6449225e82 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1,5 +1,5 @@ @c Copyright (C) 1988,1989,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001, -@c 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +@c 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -1288,9 +1288,7 @@ mode, otherwise @var{mode} is VOIDmode. @var{mode} is provided in the case where structures of one field would require the structure's mode to retain the field's mode. -Normally, this is not needed. See the file @file{c4x.h} for an example -of how to use this macro to prevent a structure having a floating point -field from being accessed in an integer mode. +Normally, this is not needed. @end defmac @defmac ROUND_TYPE_ALIGN (@var{type}, @var{computed}, @var{specified}) @@ -1351,7 +1349,7 @@ targets. @defmac TARGET_FLOAT_FORMAT A code distinguishing the floating point format of the target machine. -There are four defined values: +There are two defined values: @ftable @code @item IEEE_FLOAT_FORMAT @@ -1361,9 +1359,6 @@ need to define @code{TARGET_FLOAT_FORMAT} when the format is IEEE@. @item VAX_FLOAT_FORMAT This code indicates the ``F float'' (for @code{float}) and ``D float'' or ``G float'' formats (for @code{double}) used on the VAX and PDP-11@. - -@item C4X_FLOAT_FORMAT -This code indicates the format used on the TMS320C3x/C4x. @end ftable If your target uses a floating point format other than these, you must @@ -9807,9 +9802,6 @@ arguments of pragmas registered with @code{c_register_pragma_with_expansion} but not on the arguments of pragmas registered with @code{c_register_pragma}. -For an example use of this routine, see @file{c4x.h} and the callback -routines defined in @file{c4x-c.c}. - Note that the use of @code{pragma_lex} is specific to the C and C++ compilers. It will not work in the Java or Fortran compilers, or any other language compilers for that matter. Thus if @code{pragma_lex} is going diff --git a/gcc/real.c b/gcc/real.c index ec7d56b7b10..38f18a8462a 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -1,6 +1,6 @@ /* real.c - software floating point emulation. Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. + 2000, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. Contributed by Stephen L. Moshier (moshier@world.std.com). Re-written by Richard Henderson <rth@redhat.com> @@ -4278,235 +4278,6 @@ const struct real_format decimal_quad_format = false }; -/* The "twos-complement" c4x format is officially defined as - - x = s(~s).f * 2**e - - This is rather misleading. One must remember that F is signed. - A better description would be - - x = -1**s * ((s + 1 + .f) * 2**e - - So if we have a (4 bit) fraction of .1000 with a sign bit of 1, - that's -1 * (1+1+(-.5)) == -1.5. I think. - - The constructions here are taken from Tables 5-1 and 5-2 of the - TMS320C4x User's Guide wherein step-by-step instructions for - conversion from IEEE are presented. That's close enough to our - internal representation so as to make things easy. - - See http://www-s.ti.com/sc/psheets/spru063c/spru063c.pdf */ - -static void encode_c4x_single (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_c4x_single (const struct real_format *, - REAL_VALUE_TYPE *, const long *); -static void encode_c4x_extended (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_c4x_extended (const struct real_format *, - REAL_VALUE_TYPE *, const long *); - -static void -encode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf, const REAL_VALUE_TYPE *r) -{ - unsigned long image, exp, sig; - - switch (r->cl) - { - case rvc_zero: - exp = -128; - sig = 0; - break; - - case rvc_inf: - case rvc_nan: - exp = 127; - sig = 0x800000 - r->sign; - break; - - case rvc_normal: - exp = REAL_EXP (r) - 1; - sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff; - if (r->sign) - { - if (sig) - sig = -sig; - else - exp--; - sig |= 0x800000; - } - break; - - default: - gcc_unreachable (); - } - - image = ((exp & 0xff) << 24) | (sig & 0xffffff); - buf[0] = image; -} - -static void -decode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - unsigned long image = buf[0]; - unsigned long sig; - int exp, sf; - - exp = (((image >> 24) & 0xff) ^ 0x80) - 0x80; - sf = ((image & 0xffffff) ^ 0x800000) - 0x800000; - - memset (r, 0, sizeof (*r)); - - if (exp != -128) - { - r->cl = rvc_normal; - - sig = sf & 0x7fffff; - if (sf < 0) - { - r->sign = 1; - if (sig) - sig = -sig; - else - exp++; - } - sig = (sig << (HOST_BITS_PER_LONG - 24)) | SIG_MSB; - - SET_REAL_EXP (r, exp + 1); - r->sig[SIGSZ-1] = sig; - } -} - -static void -encode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf, const REAL_VALUE_TYPE *r) -{ - unsigned long exp, sig; - - switch (r->cl) - { - case rvc_zero: - exp = -128; - sig = 0; - break; - - case rvc_inf: - case rvc_nan: - exp = 127; - sig = 0x80000000 - r->sign; - break; - - case rvc_normal: - exp = REAL_EXP (r) - 1; - - sig = r->sig[SIGSZ-1]; - if (HOST_BITS_PER_LONG == 64) - sig = sig >> 1 >> 31; - sig &= 0x7fffffff; - - if (r->sign) - { - if (sig) - sig = -sig; - else - exp--; - sig |= 0x80000000; - } - break; - - default: - gcc_unreachable (); - } - - exp = (exp & 0xff) << 24; - sig &= 0xffffffff; - - if (FLOAT_WORDS_BIG_ENDIAN) - buf[0] = exp, buf[1] = sig; - else - buf[0] = sig, buf[0] = exp; -} - -static void -decode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - unsigned long sig; - int exp, sf; - - if (FLOAT_WORDS_BIG_ENDIAN) - exp = buf[0], sf = buf[1]; - else - sf = buf[0], exp = buf[1]; - - exp = (((exp >> 24) & 0xff) & 0x80) - 0x80; - sf = ((sf & 0xffffffff) ^ 0x80000000) - 0x80000000; - - memset (r, 0, sizeof (*r)); - - if (exp != -128) - { - r->cl = rvc_normal; - - sig = sf & 0x7fffffff; - if (sf < 0) - { - r->sign = 1; - if (sig) - sig = -sig; - else - exp++; - } - if (HOST_BITS_PER_LONG == 64) - sig = sig << 1 << 31; - sig |= SIG_MSB; - - SET_REAL_EXP (r, exp + 1); - r->sig[SIGSZ-1] = sig; - } -} - -const struct real_format c4x_single_format = - { - encode_c4x_single, - decode_c4x_single, - 2, - 24, - 24, - -126, - 128, - 23, - -1, - false, - false, - false, - false, - false, - false - }; - -const struct real_format c4x_extended_format = - { - encode_c4x_extended, - decode_c4x_extended, - 2, - 32, - 32, - -126, - 128, - 31, - -1, - false, - false, - false, - false, - false, - false - }; - - /* A synthetic "format" for internal arithmetic. It's the size of the internal significand minus the two bits needed for proper rounding. The encode and decode routines exist only to satisfy our paranoia diff --git a/gcc/real.h b/gcc/real.h index 1eaabed28c0..e482c888f34 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -1,6 +1,6 @@ /* Definitions of floating-point access for GNU compiler. Copyright (C) 1989, 1991, 1994, 1996, 1997, 1998, 1999, - 2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. + 2000, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. This file is part of GCC. @@ -271,8 +271,6 @@ extern const struct real_format mips_quad_format; extern const struct real_format vax_f_format; extern const struct real_format vax_d_format; extern const struct real_format vax_g_format; -extern const struct real_format c4x_single_format; -extern const struct real_format c4x_extended_format; extern const struct real_format real_internal_format; extern const struct real_format decimal_single_format; extern const struct real_format decimal_double_format; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9fbd03a432e..9c7af4ee89d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-01-25 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/builtin-inf-1.c, gcc.dg/compare6.c, gcc.dg/sibcall-3.c, + gcc.dg/sibcall-4.c, gcc.dg/torture/builtin-attr-1.c: Don't handle + c4x-*-* targets. + 2008-01-25 Richard Guenther <rguenther@suse.de> PR middle-end/32244 diff --git a/gcc/testsuite/gcc.dg/builtin-inf-1.c b/gcc/testsuite/gcc.dg/builtin-inf-1.c index d2d28415899..fdb4612274c 100644 --- a/gcc/testsuite/gcc.dg/builtin-inf-1.c +++ b/gcc/testsuite/gcc.dg/builtin-inf-1.c @@ -8,6 +8,6 @@ float fh = __builtin_huge_valf(); double dh = __builtin_huge_val(); long double lh = __builtin_huge_vall(); -/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* c4x-*-* } 3 } */ -/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* c4x-*-* } 4 } */ -/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* c4x-*-* } 5 } */ +/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* } 3 } */ +/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* } 4 } */ +/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* } 5 } */ diff --git a/gcc/testsuite/gcc.dg/compare6.c b/gcc/testsuite/gcc.dg/compare6.c index b6aee8f062c..945d2823955 100644 --- a/gcc/testsuite/gcc.dg/compare6.c +++ b/gcc/testsuite/gcc.dg/compare6.c @@ -1,7 +1,6 @@ /* PR c/2098 */ /* Test for a warning on comparison on out-of-range data. */ /* { dg-do compile } */ -/* { dg-xfail-if "" { c4x-*-* } { "*" } { "" } } */ /* { dg-options "-Wtype-limits" } */ signed char sc; diff --git a/gcc/testsuite/gcc.dg/sibcall-3.c b/gcc/testsuite/gcc.dg/sibcall-3.c index d351d4f74d1..38f3e37622d 100644 --- a/gcc/testsuite/gcc.dg/sibcall-3.c +++ b/gcc/testsuite/gcc.dg/sibcall-3.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson <hp@bitrange.com> */ -/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ +/* { dg-do run { xfail arc-*-* avr-*-* cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ /* -mlongcall disables sibcall patterns. */ /* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */ /* { dg-options "-O2 -foptimize-sibling-calls" } */ diff --git a/gcc/testsuite/gcc.dg/sibcall-4.c b/gcc/testsuite/gcc.dg/sibcall-4.c index daba88b76cc..535efb64504 100644 --- a/gcc/testsuite/gcc.dg/sibcall-4.c +++ b/gcc/testsuite/gcc.dg/sibcall-4.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson <hp@bitrange.com> */ -/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ +/* { dg-do run { xfail arc-*-* avr-*-* cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ /* -mlongcall disables sibcall patterns. */ /* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */ /* { dg-options "-O2 -foptimize-sibling-calls" } */ diff --git a/gcc/testsuite/gcc.dg/torture/builtin-attr-1.c b/gcc/testsuite/gcc.dg/torture/builtin-attr-1.c index 5b9012e51fc..bd383a2b34b 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-attr-1.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-attr-1.c @@ -339,7 +339,7 @@ FPTEST2 (fmod) BUILTIN_FPTEST0 (huge_val) FPTEST2 (hypot) FPTEST1T (ilogb, int) -BUILTIN_FPTEST0 (inf) /* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* c4x-*-* pdp11-*-* spu-*-* } } */ +BUILTIN_FPTEST0 (inf) /* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* pdp11-*-* spu-*-* } } */ FPTEST1 (j0) FPTEST1 (j1) FPTEST2ARG1 (jn, int) diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 68f4c508933..e418769c4a5 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,9 @@ +2008-01-25 Joseph Myers <joseph@codesourcery.com> + + * config.host (tic4x-*-*, c4x-*-rtems*, tic4x-*-rtems*, c4x-*, + tic4x-*, h8300-*-rtemscoff*, ns32k-*-netbsdelf*, ns32k-*-netbsd*, + sh-*-rtemscoff*): Remove cases. + 2007-12-27 Richard Sandiford <rsandifo@nildram.co.uk> * Makefile.in (all): Use install-leaf rather than install. diff --git a/libgcc/config.host b/libgcc/config.host index 5374455aa11..9496842f9bb 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -1,6 +1,6 @@ # libgcc host-specific configuration file. -# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 -# Free Software Foundation, Inc. +# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +# 2008 Free Software Foundation, Inc. #This file is part of GCC. @@ -137,9 +137,6 @@ s390*-*-*) sh[123456789lbe]*-*-*) cpu_type=sh ;; -tic4x-*-*) - cpu_type=c4x - ;; esac # Common parts for widely ported systems. @@ -258,10 +255,6 @@ bfin*-linux-uclibc*) ;; bfin*-*) ;; -c4x-*-rtems* | tic4x-*-rtems*) - ;; -c4x-* | tic4x-*) - ;; cris-*-aout) ;; crisv32-*-elf | crisv32-*-none | cris-*-elf | cris-*-none) @@ -279,8 +272,6 @@ frv-*-elf) ;; frv-*-*linux*) ;; -h8300-*-rtemscoff*) - ;; h8300-*-rtems*) ;; h8300-*-elf*) @@ -473,11 +464,6 @@ mn10300-*-*) ;; mt-*-elf) ;; -ns32k-*-netbsdelf*) - echo "GCC does not yet support the ${host} target"; exit 1 - ;; -ns32k-*-netbsd*) - ;; pdp11-*-bsd) ;; pdp11-*-*) @@ -574,8 +560,6 @@ sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \ ;; esac ;; -sh-*-rtemscoff*) - ;; sh-*-rtems*) ;; sh-wrs-vxworks) |