| /* Subroutines needed by GCC output code on some machines. */ |
| /* Compile this file with the Unix C compiler! */ |
| /* Copyright (C) 1987, 1988, 1992, 1994, 1995 Free Software Foundation, Inc. |
| |
| This file is free software; you can redistribute it and/or modify it |
| under the terms of the GNU General Public License as published by the |
| Free Software Foundation; either version 2, or (at your option) any |
| later version. |
| |
| In addition to the permissions in the GNU General Public License, the |
| Free Software Foundation gives you unlimited permission to link the |
| compiled version of this file with other programs, and to distribute |
| those programs without any restriction coming from the use of this |
| file. (The General Public License restrictions do apply in other |
| respects; for example, they cover modification of the file, and |
| distribution when not linked into another program.) |
| |
| This file is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; see the file COPYING. If not, write to |
| the Free Software Foundation, 59 Temple Place - Suite 330, |
| Boston, MA 02111-1307, USA. */ |
| |
| /* As a special exception, if you link this library with other files, |
| some of which are compiled with GCC, to produce an executable, |
| this library does not by itself cause the resulting executable |
| to be covered by the GNU General Public License. |
| This exception does not however invalidate any other reasons why |
| the executable file might be covered by the GNU General Public License. */ |
| |
| #include "config.h" |
| |
| /* Don't use `fancy_abort' here even if config.h says to use it. */ |
| #ifdef abort |
| #undef abort |
| #endif |
| |
| /* On some machines, cc is really GCC. For these machines, we can't |
| expect these functions to be properly compiled unless GCC open codes |
| the operation (which is precisely when the function won't be used). |
| So allow tm.h to specify ways of accomplishing the operations |
| by defining the macros perform_*. |
| |
| On a machine where cc is some other compiler, there is usually no |
| reason to define perform_*. The other compiler normally has other ways |
| of implementing all of these operations. |
| |
| In some cases a certain machine may come with GCC installed as cc |
| or may have some other compiler. Then it may make sense for tm.h |
| to define perform_* only if __GNUC__ is defined. */ |
| |
| #ifndef perform_mulsi3 |
| #define perform_mulsi3(a, b) return a * b |
| #endif |
| |
| #ifndef perform_divsi3 |
| #define perform_divsi3(a, b) return a / b |
| #endif |
| |
| #ifndef perform_udivsi3 |
| #define perform_udivsi3(a, b) return a / b |
| #endif |
| |
| #ifndef perform_modsi3 |
| #define perform_modsi3(a, b) return a % b |
| #endif |
| |
| #ifndef perform_umodsi3 |
| #define perform_umodsi3(a, b) return a % b |
| #endif |
| |
| #ifndef perform_lshrsi3 |
| #define perform_lshrsi3(a, b) return a >> b |
| #endif |
| |
| #ifndef perform_ashrsi3 |
| #define perform_ashrsi3(a, b) return a >> b |
| #endif |
| |
| #ifndef perform_ashlsi3 |
| #define perform_ashlsi3(a, b) return a << b |
| #endif |
| |
| #ifndef perform_adddf3 |
| #define perform_adddf3(a, b) return a + b |
| #endif |
| |
| #ifndef perform_subdf3 |
| #define perform_subdf3(a, b) return a - b |
| #endif |
| |
| #ifndef perform_muldf3 |
| #define perform_muldf3(a, b) return a * b |
| #endif |
| |
| #ifndef perform_divdf3 |
| #define perform_divdf3(a, b) return a / b |
| #endif |
| |
| #ifndef perform_addsf3 |
| #define perform_addsf3(a, b) return INTIFY (a + b) |
| #endif |
| |
| #ifndef perform_subsf3 |
| #define perform_subsf3(a, b) return INTIFY (a - b) |
| #endif |
| |
| #ifndef perform_mulsf3 |
| #define perform_mulsf3(a, b) return INTIFY (a * b) |
| #endif |
| |
| #ifndef perform_divsf3 |
| #define perform_divsf3(a, b) return INTIFY (a / b) |
| #endif |
| |
| #ifndef perform_negdf2 |
| #define perform_negdf2(a) return -a |
| #endif |
| |
| #ifndef perform_negsf2 |
| #define perform_negsf2(a) return INTIFY (-a) |
| #endif |
| |
| #ifndef perform_fixdfsi |
| #define perform_fixdfsi(a) return (nongcc_SI_type) a; |
| #endif |
| |
| #ifndef perform_fixsfsi |
| #define perform_fixsfsi(a) return (nongcc_SI_type) a |
| #endif |
| |
| #ifndef perform_floatsidf |
| #define perform_floatsidf(a) return (double) a |
| #endif |
| |
| #ifndef perform_floatsisf |
| #define perform_floatsisf(a) return INTIFY ((float) a) |
| #endif |
| |
| #ifndef perform_extendsfdf2 |
| #define perform_extendsfdf2(a) return a |
| #endif |
| |
| #ifndef perform_truncdfsf2 |
| #define perform_truncdfsf2(a) return INTIFY (a) |
| #endif |
| |
| /* Note that eqdf2 returns a value for "true" that is == 0, |
| nedf2 returns a value for "true" that is != 0, |
| gtdf2 returns a value for "true" that is > 0, |
| and so on. */ |
| |
| #ifndef perform_eqdf2 |
| #define perform_eqdf2(a, b) return !(a == b) |
| #endif |
| |
| #ifndef perform_nedf2 |
| #define perform_nedf2(a, b) return a != b |
| #endif |
| |
| #ifndef perform_gtdf2 |
| #define perform_gtdf2(a, b) return a > b |
| #endif |
| |
| #ifndef perform_gedf2 |
| #define perform_gedf2(a, b) return (a >= b) - 1 |
| #endif |
| |
| #ifndef perform_ltdf2 |
| #define perform_ltdf2(a, b) return -(a < b) |
| #endif |
| |
| #ifndef perform_ledf2 |
| #define perform_ledf2(a, b) return 1 - (a <= b) |
| #endif |
| |
| #ifndef perform_eqsf2 |
| #define perform_eqsf2(a, b) return !(a == b) |
| #endif |
| |
| #ifndef perform_nesf2 |
| #define perform_nesf2(a, b) return a != b |
| #endif |
| |
| #ifndef perform_gtsf2 |
| #define perform_gtsf2(a, b) return a > b |
| #endif |
| |
| #ifndef perform_gesf2 |
| #define perform_gesf2(a, b) return (a >= b) - 1 |
| #endif |
| |
| #ifndef perform_ltsf2 |
| #define perform_ltsf2(a, b) return -(a < b) |
| #endif |
| |
| #ifndef perform_lesf2 |
| #define perform_lesf2(a, b) return 1 - (a <= b); |
| #endif |
| |
| /* Define the C data type to use for an SImode value. */ |
| |
| #ifndef nongcc_SI_type |
| #define nongcc_SI_type long int |
| #endif |
| |
| /* Define the C data type to use for a value of word size */ |
| #ifndef nongcc_word_type |
| #define nongcc_word_type nongcc_SI_type |
| #endif |
| |
| /* Define the type to be used for returning an SF mode value |
| and the method for turning a float into that type. |
| These definitions work for machines where an SF value is |
| returned in the same register as an int. */ |
| |
| #ifndef FLOAT_VALUE_TYPE |
| #define FLOAT_VALUE_TYPE int |
| #endif |
| |
| #ifndef INTIFY |
| #define INTIFY(FLOATVAL) (intify.f = (FLOATVAL), intify.i) |
| #endif |
| |
| #ifndef FLOATIFY |
| #define FLOATIFY(INTVAL) ((INTVAL).f) |
| #endif |
| |
| #ifndef FLOAT_ARG_TYPE |
| #define FLOAT_ARG_TYPE union flt_or_int |
| #endif |
| |
| union flt_or_value { FLOAT_VALUE_TYPE i; float f; }; |
| |
| union flt_or_int { int i; float f; }; |
| |
| |
| #ifdef L_mulsi3 |
| nongcc_SI_type |
| __mulsi3 (a, b) |
| nongcc_SI_type a, b; |
| { |
| perform_mulsi3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_udivsi3 |
| nongcc_SI_type |
| __udivsi3 (a, b) |
| unsigned nongcc_SI_type a, b; |
| { |
| perform_udivsi3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_divsi3 |
| nongcc_SI_type |
| __divsi3 (a, b) |
| nongcc_SI_type a, b; |
| { |
| perform_divsi3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_umodsi3 |
| nongcc_SI_type |
| __umodsi3 (a, b) |
| unsigned nongcc_SI_type a, b; |
| { |
| perform_umodsi3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_modsi3 |
| nongcc_SI_type |
| __modsi3 (a, b) |
| nongcc_SI_type a, b; |
| { |
| perform_modsi3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_lshrsi3 |
| nongcc_SI_type |
| __lshrsi3 (a, b) |
| unsigned nongcc_SI_type a, b; |
| { |
| perform_lshrsi3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_ashrsi3 |
| nongcc_SI_type |
| __ashrsi3 (a, b) |
| nongcc_SI_type a, b; |
| { |
| perform_ashrsi3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_ashlsi3 |
| nongcc_SI_type |
| __ashlsi3 (a, b) |
| nongcc_SI_type a, b; |
| { |
| perform_ashlsi3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_divdf3 |
| double |
| __divdf3 (a, b) |
| double a, b; |
| { |
| perform_divdf3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_muldf3 |
| double |
| __muldf3 (a, b) |
| double a, b; |
| { |
| perform_muldf3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_negdf2 |
| double |
| __negdf2 (a) |
| double a; |
| { |
| perform_negdf2 (a); |
| } |
| #endif |
| |
| #ifdef L_adddf3 |
| double |
| __adddf3 (a, b) |
| double a, b; |
| { |
| perform_adddf3 (a, b); |
| } |
| #endif |
| |
| #ifdef L_subdf3 |
| double |
| __subdf3 (a, b) |
| double a, b; |
| { |
| perform_subdf3 (a, b); |
| } |
| #endif |
| |
| /* Note that eqdf2 returns a value for "true" that is == 0, |
| nedf2 returns a value for "true" that is != 0, |
| gtdf2 returns a value for "true" that is > 0, |
| and so on. */ |
| |
| #ifdef L_eqdf2 |
| nongcc_word_type |
| __eqdf2 (a, b) |
| double a, b; |
| { |
| /* Value == 0 iff a == b. */ |
| perform_eqdf2 (a, b); |
| } |
| #endif |
| |
| #ifdef L_nedf2 |
| nongcc_word_type |
| __nedf2 (a, b) |
| double a, b; |
| { |
| /* Value != 0 iff a != b. */ |
| perform_nedf2 (a, b); |
| } |
| #endif |
| |
| #ifdef L_gtdf2 |
| nongcc_word_type |
| __gtdf2 (a, b) |
| double a, b; |
| { |
| /* Value > 0 iff a > b. */ |
| perform_gtdf2 (a, b); |
| } |
| #endif |
| |
| #ifdef L_gedf2 |
| nongcc_word_type |
| __gedf2 (a, b) |
| double a, b; |
| { |
| /* Value >= 0 iff a >= b. */ |
| perform_gedf2 (a, b); |
| } |
| #endif |
| |
| #ifdef L_ltdf2 |
| nongcc_word_type |
| __ltdf2 (a, b) |
| double a, b; |
| { |
| /* Value < 0 iff a < b. */ |
| perform_ltdf2 (a, b); |
| } |
| #endif |
| |
| #ifdef L_ledf2 |
| nongcc_word_type |
| __ledf2 (a, b) |
| double a, b; |
| { |
| /* Value <= 0 iff a <= b. */ |
| perform_ledf2 (a, b); |
| } |
| #endif |
| |
| #ifdef L_fixdfsi |
| nongcc_SI_type |
| __fixdfsi (a) |
| double a; |
| { |
| perform_fixdfsi (a); |
| } |
| #endif |
| |
| #ifdef L_fixsfsi |
| nongcc_SI_type |
| __fixsfsi (a) |
| FLOAT_ARG_TYPE a; |
| { |
| union flt_or_value intify; |
| perform_fixsfsi (FLOATIFY (a)); |
| } |
| #endif |
| |
| #ifdef L_floatsidf |
| double |
| __floatsidf (a) |
| nongcc_SI_type a; |
| { |
| perform_floatsidf (a); |
| } |
| #endif |
| |
| #ifdef L_floatsisf |
| FLOAT_VALUE_TYPE |
| __floatsisf (a) |
| nongcc_SI_type a; |
| { |
| union flt_or_value intify; |
| perform_floatsisf (a); |
| } |
| #endif |
| |
| #ifdef L_addsf3 |
| FLOAT_VALUE_TYPE |
| __addsf3 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_value intify; |
| perform_addsf3 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_negsf2 |
| FLOAT_VALUE_TYPE |
| __negsf2 (a) |
| FLOAT_ARG_TYPE a; |
| { |
| union flt_or_value intify; |
| perform_negsf2 (FLOATIFY (a)); |
| } |
| #endif |
| |
| #ifdef L_subsf3 |
| FLOAT_VALUE_TYPE |
| __subsf3 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_value intify; |
| perform_subsf3 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_eqsf2 |
| nongcc_word_type |
| __eqsf2 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_int intify; |
| /* Value == 0 iff a == b. */ |
| perform_eqsf2 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_nesf2 |
| nongcc_word_type |
| __nesf2 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_int intify; |
| /* Value != 0 iff a != b. */ |
| perform_nesf2 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_gtsf2 |
| nongcc_word_type |
| __gtsf2 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_int intify; |
| /* Value > 0 iff a > b. */ |
| perform_gtsf2 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_gesf2 |
| nongcc_word_type |
| __gesf2 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_int intify; |
| /* Value >= 0 iff a >= b. */ |
| perform_gesf2 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_ltsf2 |
| nongcc_word_type |
| __ltsf2 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_int intify; |
| /* Value < 0 iff a < b. */ |
| perform_ltsf2 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_lesf2 |
| nongcc_word_type |
| __lesf2 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_int intify; |
| /* Value <= 0 iff a <= b. */ |
| perform_lesf2 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_mulsf3 |
| FLOAT_VALUE_TYPE |
| __mulsf3 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_value intify; |
| perform_mulsf3 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_divsf3 |
| FLOAT_VALUE_TYPE |
| __divsf3 (a, b) |
| FLOAT_ARG_TYPE a, b; |
| { |
| union flt_or_value intify; |
| perform_divsf3 (FLOATIFY (a), FLOATIFY (b)); |
| } |
| #endif |
| |
| #ifdef L_truncdfsf2 |
| FLOAT_VALUE_TYPE |
| __truncdfsf2 (a) |
| double a; |
| { |
| union flt_or_value intify; |
| perform_truncdfsf2 (a); |
| } |
| #endif |
| |
| #ifdef L_extendsfdf2 |
| double |
| __extendsfdf2 (a) |
| FLOAT_ARG_TYPE a; |
| { |
| union flt_or_value intify; |
| perform_extendsfdf2 (FLOATIFY (a)); |
| } |
| #endif |