* libfuncs.h (LTI_extendsfdf2, LTI_extendsfxf2, LTI_extendsftf2)
authorZack Weinberg <zack@gcc.gnu.org>
Tue, 7 Oct 2003 02:23:42 +0000 (02:23 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Tue, 7 Oct 2003 02:23:42 +0000 (02:23 +0000)
(LTI_extenddfxf2, LTI_extenddftf2, LTI_truncdfsf2, LTI_truncxfsf2)
(LTI_trunctfsf2, LTI_truncxfdf2, LTI_trunctfdf2, LTI_floatsisf)
(LTI_floatdisf, LTI_floattisf, LTI_floatsidf, LTI_floatdidf)
(LTI_floattidf, LTI_floatsixf, LTI_floatdixf, LTI_floattixf)
(LTI_floatsitf, LTI_floatditf, LTI_floattitf, LTI_fixsfsi, LTI_fixsfdi)
(LTI_fixsfti, LTI_fixdfsi, LTI_fixdfdi, LTI_fixdfti, LTI_fixxfsi)
(LTI_fixxfdi, LTI_fixxfti, LTI_fixtfsi, LTI_fixtfdi, LTI_fixtfti)
(LTI_fixunssfsi, LTI_fixunssfdi, LTI_fixunssfti, LTI_fixunsdfsi)
(LTI_fixunsdfdi, LTI_fixunsdfti, LTI_fixunsxfsi, LTI_fixunsxfdi)
(LTI_fixunsxfti, LTI_fixunstfsi, LTI_fixunstfdi, LTI_fixunstfti)
(extendsfdf2_libfunc, extendsfxf2_libfunc, extendsftf2_libfunc)
(extenddfxf2_libfunc, extenddftf2_libfunc, truncdfsf2_libfunc)
(truncxfsf2_libfunc, trunctfsf2_libfunc, truncxfdf2_libfunc)
(trunctfdf2_libfunc, floatsisf_libfunc, floatdisf_libfunc)
(floattisf_libfunc, floatsidf_libfunc, floatdidf_libfunc)
(floattidf_libfunc, floatsixf_libfunc, floatdixf_libfunc)
(floattixf_libfunc, floatsitf_libfunc, floatditf_libfunc)
(floattitf_libfunc, fixsfsi_libfunc, fixsfdi_libfunc, fixsfti_libfunc)
(fixdfsi_libfunc, fixdfdi_libfunc, fixdfti_libfunc, fixxfsi_libfunc)
(fixxfdi_libfunc, fixxfti_libfunc, fixtfsi_libfunc, fixtfdi_libfunc)
(fixtfti_libfunc, fixunssfsi_libfunc, fixunssfdi_libfunc)
(fixunssfti_libfunc, fixunsdfsi_libfunc, fixunsdfdi_libfunc)
(fixunsdfti_libfunc, fixunsxfsi_libfunc, fixunsxfdi_libfunc)
(fixunsxfti_libfunc, fixunstfsi_libfunc, fixunstfdi_libfunc)
(fixunstfti_libfunc): Delete.
* optabs.h (struct optab_handlers): Break out of struct optab.
(struct convert_optab, convert_optab, enum convert_optab_index,
convert_optab_table, sext_optab, zext_optab, trunc_optab,
sfix_optab, ufix_optab, sfixtrunc_optab, ufixtrunc_optab,
sfloat_optab, ufloat_optab): New.
(set_conv_libfunc): Prototype.
(GEN_FCN): Use C90 indirect call syntax, remove unnecessary cast.
(trunc_optab): Renamed btrunc_optab.
* builtins.c (expand_builtin_mathfn): Update to match.
* optabs.c (extendtab, fixtab, fixtrunctab, floattab): Delete.
(convert_optab_table, new_convert_optab, init_convert_optab)
(init_interclass_conv_libfuncs, init_intraclass_conv_libfuncs)
(set_conv_libfunc): New.
(can_extend_p, gen_extend_insn, can_fix_p, can_float_p)
(expand_float, expand_fix): Use new conversion optabs,
not old insn code tables or long chains of ifs.
(init_optabs): No need to clear old insn code tables.
Initialize the new optabs, not the old libfunc array entries.
Don't handle FIXUNS_TRUNC_LIKE_FIX_TRUNC here.
* genopinit.c: Initialize conversion optabs, not the
former insn code tables.  Remove unnecessary casts.
Handle FIXUNS_TRUNC_LIKE_FIX_TRUNC here.
* expr.c (convert_move): Remove redundant check that
to_real==from_real.  Use the conversion optabs instead
of long chains of tests of modes.  Move partial-integer-mode
interconversion above all integer conversion.  Do not recurse
on a value forced into a register in the original mode.

* config/gofast.h, config/frv/frv.c, config/ia64/ia64.c
* config/mips/mips.c, config/pa/pa.c, config/rs6000/rs6000.c
* config/sparc/sparc.c: Use set_conv_libfunc to adjust entries
in new conversion optabs; do not reference the old libfunc
array entries.  No need to include libfuncs.h.

From-SVN: r72178

14 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/config/frv/frv.c
gcc/config/gofast.h
gcc/config/ia64/ia64.c
gcc/config/mips/mips.c
gcc/config/pa/pa.c
gcc/config/rs6000/rs6000.c
gcc/config/sparc/sparc.c
gcc/expr.c
gcc/genopinit.c
gcc/libfuncs.h
gcc/optabs.c
gcc/optabs.h

index cbd783f..a7a3b0c 100644 (file)
@@ -1,3 +1,65 @@
+2003-10-06  Zack Weinberg  <zack@codesourcery.com>
+
+       * libfuncs.h (LTI_extendsfdf2, LTI_extendsfxf2, LTI_extendsftf2)
+       (LTI_extenddfxf2, LTI_extenddftf2, LTI_truncdfsf2, LTI_truncxfsf2)
+       (LTI_trunctfsf2, LTI_truncxfdf2, LTI_trunctfdf2, LTI_floatsisf)
+       (LTI_floatdisf, LTI_floattisf, LTI_floatsidf, LTI_floatdidf)
+       (LTI_floattidf, LTI_floatsixf, LTI_floatdixf, LTI_floattixf)
+       (LTI_floatsitf, LTI_floatditf, LTI_floattitf, LTI_fixsfsi, LTI_fixsfdi)
+       (LTI_fixsfti, LTI_fixdfsi, LTI_fixdfdi, LTI_fixdfti, LTI_fixxfsi)
+       (LTI_fixxfdi, LTI_fixxfti, LTI_fixtfsi, LTI_fixtfdi, LTI_fixtfti)
+       (LTI_fixunssfsi, LTI_fixunssfdi, LTI_fixunssfti, LTI_fixunsdfsi)
+       (LTI_fixunsdfdi, LTI_fixunsdfti, LTI_fixunsxfsi, LTI_fixunsxfdi)
+       (LTI_fixunsxfti, LTI_fixunstfsi, LTI_fixunstfdi, LTI_fixunstfti)
+       (extendsfdf2_libfunc, extendsfxf2_libfunc, extendsftf2_libfunc)
+       (extenddfxf2_libfunc, extenddftf2_libfunc, truncdfsf2_libfunc)
+       (truncxfsf2_libfunc, trunctfsf2_libfunc, truncxfdf2_libfunc)
+       (trunctfdf2_libfunc, floatsisf_libfunc, floatdisf_libfunc)
+       (floattisf_libfunc, floatsidf_libfunc, floatdidf_libfunc)
+       (floattidf_libfunc, floatsixf_libfunc, floatdixf_libfunc)
+       (floattixf_libfunc, floatsitf_libfunc, floatditf_libfunc)
+       (floattitf_libfunc, fixsfsi_libfunc, fixsfdi_libfunc, fixsfti_libfunc)
+       (fixdfsi_libfunc, fixdfdi_libfunc, fixdfti_libfunc, fixxfsi_libfunc)
+       (fixxfdi_libfunc, fixxfti_libfunc, fixtfsi_libfunc, fixtfdi_libfunc)
+       (fixtfti_libfunc, fixunssfsi_libfunc, fixunssfdi_libfunc)
+       (fixunssfti_libfunc, fixunsdfsi_libfunc, fixunsdfdi_libfunc)
+       (fixunsdfti_libfunc, fixunsxfsi_libfunc, fixunsxfdi_libfunc)
+       (fixunsxfti_libfunc, fixunstfsi_libfunc, fixunstfdi_libfunc)
+       (fixunstfti_libfunc): Delete.
+       * optabs.h (struct optab_handlers): Break out of struct optab.
+       (struct convert_optab, convert_optab, enum convert_optab_index,
+       convert_optab_table, sext_optab, zext_optab, trunc_optab,
+       sfix_optab, ufix_optab, sfixtrunc_optab, ufixtrunc_optab,
+       sfloat_optab, ufloat_optab): New.
+       (set_conv_libfunc): Prototype.
+       (GEN_FCN): Use C90 indirect call syntax, remove unnecessary cast.
+       (trunc_optab): Renamed btrunc_optab.
+       * builtins.c (expand_builtin_mathfn): Update to match.
+       * optabs.c (extendtab, fixtab, fixtrunctab, floattab): Delete.
+       (convert_optab_table, new_convert_optab, init_convert_optab)
+       (init_interclass_conv_libfuncs, init_intraclass_conv_libfuncs)
+       (set_conv_libfunc): New.
+       (can_extend_p, gen_extend_insn, can_fix_p, can_float_p)
+       (expand_float, expand_fix): Use new conversion optabs,
+       not old insn code tables or long chains of ifs.
+       (init_optabs): No need to clear old insn code tables.
+       Initialize the new optabs, not the old libfunc array entries.
+       Don't handle FIXUNS_TRUNC_LIKE_FIX_TRUNC here.
+       * genopinit.c: Initialize conversion optabs, not the
+       former insn code tables.  Remove unnecessary casts.
+       Handle FIXUNS_TRUNC_LIKE_FIX_TRUNC here.
+       * expr.c (convert_move): Remove redundant check that
+       to_real==from_real.  Use the conversion optabs instead
+       of long chains of tests of modes.  Move partial-integer-mode
+       interconversion above all integer conversion.  Do not recurse
+       on a value forced into a register in the original mode.
+
+       * config/gofast.h, config/frv/frv.c, config/ia64/ia64.c
+       * config/mips/mips.c, config/pa/pa.c, config/rs6000/rs6000.c
+       * config/sparc/sparc.c: Use set_conv_libfunc to adjust entries
+       in new conversion optabs; do not reference the old libfunc
+       array entries.  No need to include libfuncs.h.
+
 2003-10-06  Roger Sayle  <roger@eyesopen.com>
 
        * config/i386/i386.c (ix86_expand_setcc): Annotate the floating
@@ -18,9 +80,9 @@
 
 2003-10-06  Falk Hueffner  <falk.hueffner@student.uni-tuebingen.de>
 
-        PR optimization/11974
-        * optabs.c (expand_unop): Promote libcall outmode according to
-        hard_libcall_value.
+       PR optimization/11974
+       * optabs.c (expand_unop): Promote libcall outmode according to
+       hard_libcall_value.
 
 2003-10-06  Zack Weinberg  <zack@codesourcery.com>
 
index d7d7604..8aabaa7 100644 (file)
@@ -1652,7 +1652,7 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
     case BUILT_IN_TRUNC:
     case BUILT_IN_TRUNCF:
     case BUILT_IN_TRUNCL:
-      builtin_optab = trunc_optab; break;
+      builtin_optab = btrunc_optab; break;
     case BUILT_IN_ROUND:
     case BUILT_IN_ROUNDF:
     case BUILT_IN_ROUNDL:
index 0d83982..c9eab11 100644 (file)
@@ -40,7 +40,6 @@ Boston, MA 02111-1307, USA.  */
 #include "except.h"
 #include "function.h"
 #include "optabs.h"
-#include "libfuncs.h"
 #include "toplev.h"
 #include "basic-block.h"
 #include "tm_p.h"
@@ -9145,20 +9144,23 @@ frv_init_libfuncs (void)
   set_optab_libfunc (smul_optab,     DFmode, "__muld");
   set_optab_libfunc (sdiv_optab,     DFmode, "__divd");
 
-  fixsfsi_libfunc     = init_one_libfunc ("__ftoi");
-  fixunssfsi_libfunc  = init_one_libfunc ("__ftoui");
-  fixsfdi_libfunc     = init_one_libfunc ("__ftoll");
-  fixunssfdi_libfunc  = init_one_libfunc ("__ftoull");
-  fixdfsi_libfunc     = init_one_libfunc ("__dtoi");
-  fixunsdfsi_libfunc  = init_one_libfunc ("__dtoui");
-  fixdfdi_libfunc     = init_one_libfunc ("__dtoll");
-  fixunsdfdi_libfunc  = init_one_libfunc ("__dtoull");
-  floatsisf_libfunc   = init_one_libfunc ("__itof");
-  floatdisf_libfunc   = init_one_libfunc ("__lltof");
-  floatsidf_libfunc   = init_one_libfunc ("__itod");
-  floatdidf_libfunc   = init_one_libfunc ("__lltod");
-  extendsfdf2_libfunc = init_one_libfunc ("__ftod");
-  truncdfsf2_libfunc  = init_one_libfunc ("__dtof");
+  set_conv_libfunc (sext_optab,   DFmode, SFmode, "__ftod");
+  set_conv_libfunc (trunc_optab,  SFmode, DFmode, "__dtof");
+
+  set_conv_libfunc (sfix_optab,   SImode, SFmode, "__ftoi");
+  set_conv_libfunc (sfix_optab,   DImode, SFmode, "__ftoll");
+  set_conv_libfunc (sfix_optab,   SImode, DFmode, "__dtoi");
+  set_conv_libfunc (sfix_optab,   DImode, DFmode, "__dtoll");
+
+  set_conv_libfunc (ufix_optab,   SImode, SFmode, "__ftoui");
+  set_conv_libfunc (ufix_optab,   SImode, SFmode, "__ftoull");
+  set_conv_libfunc (ufix_optab,   SImode, SFmode, "__dtoui");
+  set_conv_libfunc (ufix_optab,   SImode, SFmode, "__dtoull");
+
+  set_conv_libfunc (sfloat_optab, SFmode, SImode, "__itof");
+  set_conv_libfunc (sfloat_optab, SFmode, DImode, "__lltof");
+  set_conv_libfunc (sfloat_optab, DFmode, SImode, "__itod");
+  set_conv_libfunc (sfloat_optab, DFmode, DImode, "__lltod");
 }
 
 /* Convert an integer constant to an accumulator register.  ICODE is the
index 3b3efb9..91b0a65 100644 (file)
@@ -66,14 +66,15 @@ gofast_maybe_init_libfuncs (void)
   set_optab_libfunc (lt_optab, DFmode, "dpcmp");
   set_optab_libfunc (le_optab, DFmode, "dpcmp");
 
-  extendsfdf2_libfunc = init_one_libfunc ("fptodp");
-  truncdfsf2_libfunc = init_one_libfunc ("dptofp");
+  set_conv_libfunc (sext_optab,   DFmode, SFmode, "fptodp");
+  set_conv_libfunc (trunc_optab,  SFmode, DFmode, "dptofp");
 
-  floatsisf_libfunc = init_one_libfunc ("sitofp");
-  floatsidf_libfunc = init_one_libfunc ("litodp");
-  fixsfsi_libfunc = init_one_libfunc ("fptosi");
-  fixdfsi_libfunc = init_one_libfunc ("dptoli");
-  fixunssfsi_libfunc = init_one_libfunc ("fptoui");
-  fixunsdfsi_libfunc = init_one_libfunc ("dptoul");
+  set_conv_libfunc (sfix_optab,   SImode, SFmode, "fptosi");
+  set_conv_libfunc (sfix_optab,   SImode, DFmode, "dptoli");
+  set_conv_libfunc (ufix_optab,   SImode, SFmode, "fptoui");
+  set_conv_libfunc (ufix_optab,   SImode, DFmode, "dptoul");
+
+  set_conv_libfunc (sfloat_optab, SFmode, SImode, "sitofp");
+  set_conv_libfunc (sfloat_optab, DFmode, DImode, "litodp");
 #endif
 }
index b632d8b..75a2cb6 100644 (file)
@@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA.  */
 #include "recog.h"
 #include "expr.h"
 #include "optabs.h"
-#include "libfuncs.h"
 #include "except.h"
 #include "function.h"
 #include "ggc.h"
@@ -8327,16 +8326,18 @@ ia64_hpux_init_libfuncs (void)
   set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
   set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
 
-  extendsftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_sgl_to_quad");
-  extenddftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_dbl_to_quad");
-  trunctfsf2_libfunc = init_one_libfunc ("_U_Qfcnvff_quad_to_sgl");
-  trunctfdf2_libfunc = init_one_libfunc ("_U_Qfcnvff_quad_to_dbl");
-  floatsitf_libfunc = init_one_libfunc ("_U_Qfcnvxf_sgl_to_quad");
-  floatditf_libfunc = init_one_libfunc ("_U_Qfcnvxf_dbl_to_quad");
-  fixtfsi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_sgl");
-  fixtfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_dbl");
-  fixunstfsi_libfunc = init_one_libfunc ("_U_Qfcnvfxut_quad_to_sgl");
-  fixunstfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxut_quad_to_dbl");
+  set_conv_libfunc (sext_optab,   TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
+  set_conv_libfunc (sext_optab,   TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
+  set_conv_libfunc (trunc_optab,  SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
+  set_conv_libfunc (trunc_optab,  DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
+
+  set_conv_libfunc (sfix_optab,   SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
+  set_conv_libfunc (sfix_optab,   DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
+  set_conv_libfunc (ufix_optab,   SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
+  set_conv_libfunc (ufix_optab,   DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
+
+  set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
+  set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
 }
 \f
 /* Switch to the section to which we should output X.  The only thing
index 9478ec1..773d6a1 100644 (file)
@@ -42,7 +42,6 @@ Boston, MA 02111-1307, USA.  */
 #include "function.h"
 #include "expr.h"
 #include "optabs.h"
-#include "libfuncs.h"
 #include "flags.h"
 #include "reload.h"
 #include "tm_p.h"
@@ -9043,8 +9042,8 @@ mips_init_libfuncs (void)
       set_optab_libfunc (lt_optab, SFmode, "__mips16_ltsf2");
       set_optab_libfunc (le_optab, SFmode, "__mips16_lesf2");
 
-      floatsisf_libfunc = init_one_libfunc ("__mips16_floatsisf");
-      fixsfsi_libfunc   = init_one_libfunc ("__mips16_fixsfsi");
+      set_conv_libfunc (sfix_optab, SImode, SFmode, "__mips16_fixsfsi");
+      set_conv_libfunc (sfloat_optab, SFmode, SImode, "__mips16_floatsisf");
 
       if (TARGET_DOUBLE_FLOAT)
        {
@@ -9060,11 +9059,11 @@ mips_init_libfuncs (void)
          set_optab_libfunc (lt_optab, DFmode, "__mips16_ltdf2");
          set_optab_libfunc (le_optab, DFmode, "__mips16_ledf2");
 
-         floatsidf_libfunc   = init_one_libfunc ("__mips16_floatsidf");
-         fixdfsi_libfunc     = init_one_libfunc ("__mips16_fixdfsi");
+         set_conv_libfunc (sext_optab, DFmode, SFmode, "__mips16_extendsfdf2");
+         set_conv_libfunc (trunc_optab, SFmode, DFmode, "__mips16_truncdfsf2");
 
-         extendsfdf2_libfunc = init_one_libfunc ("__mips16_extendsfdf2");
-         truncdfsf2_libfunc  = init_one_libfunc ("__mips16_truncdfsf2");
+         set_conv_libfunc (sfix_optab, SImode, DFmode, "__mips16_fixdfsi");
+         set_conv_libfunc (sfloat_optab, DFmode, SImode, "__mips16_floatsidf");
        }
     }
   else
index a5b9a4d..a438ac4 100644 (file)
@@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA.  */
 #include "except.h"
 #include "expr.h"
 #include "optabs.h"
-#include "libfuncs.h"
 #include "reload.h"
 #include "integrate.h"
 #include "function.h"
@@ -4980,18 +4979,20 @@ pa_hpux_init_libfuncs (void)
   set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
   set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
 
-  extendsftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_sgl_to_quad");
-  extenddftf2_libfunc = init_one_libfunc ("_U_Qfcnvff_dbl_to_quad");
-  trunctfsf2_libfunc = init_one_libfunc ("_U_Qfcnvff_quad_to_sgl");
-  trunctfdf2_libfunc = init_one_libfunc ("_U_Qfcnvff_quad_to_dbl");
-  floatsitf_libfunc = init_one_libfunc ("_U_Qfcnvxf_sgl_to_quad");
-  floatditf_libfunc = init_one_libfunc ("_U_Qfcnvxf_dbl_to_quad");
-  fixtfsi_libfunc = init_one_libfunc (TARGET_64BIT
-                                     ? "__U_Qfcnvfxt_quad_to_sgl"
-                                     : "_U_Qfcnvfxt_quad_to_sgl");
-  fixtfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_dbl");
-  fixunstfsi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_usgl");
-  fixunstfdi_libfunc = init_one_libfunc ("_U_Qfcnvfxt_quad_to_udbl");
+  set_conv_libfunc (sext_optab,   TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
+  set_conv_libfunc (sext_optab,   TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
+  set_conv_libfunc (trunc_optab,  SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
+  set_conv_libfunc (trunc_optab,  DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
+
+  set_conv_libfunc (sfix_optab,   SImode, TFmode, TARGET_64BIT
+                                                 ? "__U_Qfcnvfxt_quad_to_sgl"
+                                                 : "_U_Qfcnvfxt_quad_to_sgl");
+  set_conv_libfunc (sfix_optab,   DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
+  set_conv_libfunc (ufix_optab,   SImode, TFmode, "_U_Qfcnvfxt_quad_to_usgl");
+  set_conv_libfunc (ufix_optab,   DImode, TFmode, "_U_Qfcnvfxt_quad_to_udbl");
+
+  set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
+  set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
 }
 #endif
 
index 4316b23..be79acc 100644 (file)
@@ -37,7 +37,6 @@
 #include "tree.h"
 #include "expr.h"
 #include "optabs.h"
-#include "libfuncs.h"
 #include "except.h"
 #include "function.h"
 #include "output.h"
@@ -6784,8 +6783,8 @@ rs6000_init_libfuncs (void)
       if (TARGET_XCOFF && ! TARGET_POWER2 && ! TARGET_POWERPC)
        {
          /* AIX library routines for float->int conversion.  */
-         fixdfsi_libfunc = init_one_libfunc ("__itrunc");
-         fixunsdfsi_libfunc = init_one_libfunc ("__uitrunc");
+         set_conv_libfunc (sfix_optab, SImode, DFmode, "__itrunc");
+         set_conv_libfunc (ufix_optab, SImode, DFmode, "__uitrunc");
        }
 
       /* Standard AIX/Darwin/64-bit SVR4 quad floating point routines.  */
@@ -6813,17 +6812,15 @@ rs6000_init_libfuncs (void)
       set_optab_libfunc (lt_optab, TFmode, "_q_flt");
       set_optab_libfunc (le_optab, TFmode, "_q_fle");
 
-      trunctfsf2_libfunc = init_one_libfunc ("_q_qtos");
-      trunctfdf2_libfunc = init_one_libfunc ("_q_qtod");
-      extendsftf2_libfunc = init_one_libfunc ("_q_stoq");
-      extenddftf2_libfunc = init_one_libfunc ("_q_dtoq");
-      floatsitf_libfunc = init_one_libfunc ("_q_itoq");
-      fixtfsi_libfunc = init_one_libfunc ("_q_qtoi");
-      fixunstfsi_libfunc = init_one_libfunc ("_q_qtou");
+      set_conv_libfunc (sext_optab, TFmode, SFmode, "_q_stoq");
+      set_conv_libfunc (sext_optab, TFmode, DFmode, "_q_dtoq");
+      set_conv_libfunc (trunc_optab, SFmode, TFmode, "_q_qtos");
+      set_conv_libfunc (trunc_optab, DFmode, TFmode, "_q_qtod");
+      set_conv_libfunc (sfix_optab, SImode, TFmode, "_q_qtoi");
+      set_conv_libfunc (ufix_optab, SImode, TFmode, "_q_qtou");
+      set_conv_libfunc (sfloat_optab, TFmode, SImode, "_q_itoq");
     }
 }
-
-
 \f
 /* Expand a block move operation, and return 1 if successful.  Return 0
    if we should let the compiler generate normal code.
index adea22f..96335c9 100644 (file)
@@ -39,7 +39,6 @@ Boston, MA 02111-1307, USA.  */
 #include "function.h"
 #include "expr.h"
 #include "optabs.h"
-#include "libfuncs.h"
 #include "recog.h"
 #include "toplev.h"
 #include "ggc.h"
@@ -8431,20 +8430,21 @@ sparc_init_libfuncs (void)
       set_optab_libfunc (lt_optab, TFmode, "_Q_flt");
       set_optab_libfunc (le_optab, TFmode, "_Q_fle");
 
-      trunctfsf2_libfunc = init_one_libfunc ("_Q_qtos");
-      trunctfdf2_libfunc = init_one_libfunc ("_Q_qtod");
-      extendsftf2_libfunc = init_one_libfunc ("_Q_stoq");
-      extenddftf2_libfunc = init_one_libfunc ("_Q_dtoq");
-      floatsitf_libfunc = init_one_libfunc ("_Q_itoq");
-      fixtfsi_libfunc = init_one_libfunc ("_Q_qtoi");
-      fixunstfsi_libfunc = init_one_libfunc ("_Q_qtou");
+      set_conv_libfunc (sext_optab,   TFmode, SFmode, "_Q_stoq");
+      set_conv_libfunc (sext_optab,   TFmode, DFmode, "_Q_dtoq");
+      set_conv_libfunc (trunc_optab,  SFmode, TFmode, "_Q_qtos");
+      set_conv_libfunc (trunc_optab,  DFmode, TFmode, "_Q_qtod");
+
+      set_conv_libfunc (sfix_optab,   SImode, TFmode, "_Q_qtoi");
+      set_conv_libfunc (ufix_optab,   SImode, TFmode, "_Q_qtou");
+      set_conv_libfunc (sfloat_optab, TFmode, SImode, "_Q_itoq");
 
       if (SUN_CONVERSION_LIBFUNCS)
        {
-         fixsfdi_libfunc = init_one_libfunc ("__ftoll");
-         fixunssfdi_libfunc = init_one_libfunc ("__ftoull");
-         fixdfdi_libfunc = init_one_libfunc ("__dtoll");
-         fixunsdfdi_libfunc = init_one_libfunc ("__dtoull");
+         set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftoll");
+         set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoull");
+         set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtoll");
+         set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoull");
        }
     }
   if (TARGET_ARCH64)
@@ -8470,10 +8470,10 @@ sparc_init_libfuncs (void)
 
       if (SUN_CONVERSION_LIBFUNCS)
        {
-         fixsfdi_libfunc = init_one_libfunc ("__ftol");
-         fixunssfdi_libfunc = init_one_libfunc ("__ftoul");
-         fixdfdi_libfunc = init_one_libfunc ("__dtol");
-         fixunsdfdi_libfunc = init_one_libfunc ("__dtoul");
+         set_conv_libfunc (sfix_optab, DImode, SFmode, "__ftol");
+         set_conv_libfunc (ufix_optab, DImode, SFmode, "__ftoul");
+         set_conv_libfunc (sfix_optab, DImode, DFmode, "__dtol");
+         set_conv_libfunc (ufix_optab, DImode, DFmode, "__dtoul");
        }
     }
 
index edc4290..015faaf 100644 (file)
@@ -595,248 +595,32 @@ convert_move (rtx to, rtx from, int unsignedp)
       return;
     }
 
-  if (to_real != from_real)
-    abort ();
-
   if (to_real)
     {
       rtx value, insns;
+      convert_optab tab;
 
       if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode))
-       {
-         /* Try converting directly if the insn is supported.  */
-         if ((code = can_extend_p (to_mode, from_mode, 0))
-             != CODE_FOR_nothing)
-           {
-             emit_unop_insn (code, to, from, UNKNOWN);
-             return;
-           }
-       }
+       tab = sext_optab;
+      else if (GET_MODE_BITSIZE (from_mode) > GET_MODE_BITSIZE (to_mode))
+       tab = trunc_optab;
+      else
+       abort ();
 
-#ifdef HAVE_trunchfqf2
-      if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode)
-       {
-         emit_unop_insn (CODE_FOR_trunchfqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_trunctqfqf2
-      if (HAVE_trunctqfqf2 && from_mode == TQFmode && to_mode == QFmode)
-       {
-         emit_unop_insn (CODE_FOR_trunctqfqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncsfqf2
-      if (HAVE_truncsfqf2 && from_mode == SFmode && to_mode == QFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncsfqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncdfqf2
-      if (HAVE_truncdfqf2 && from_mode == DFmode && to_mode == QFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncdfqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncxfqf2
-      if (HAVE_truncxfqf2 && from_mode == XFmode && to_mode == QFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncxfqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_trunctfqf2
-      if (HAVE_trunctfqf2 && from_mode == TFmode && to_mode == QFmode)
-       {
-         emit_unop_insn (CODE_FOR_trunctfqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
+      /* Try converting directly if the insn is supported.  */
 
-#ifdef HAVE_trunctqfhf2
-      if (HAVE_trunctqfhf2 && from_mode == TQFmode && to_mode == HFmode)
-       {
-         emit_unop_insn (CODE_FOR_trunctqfhf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncsfhf2
-      if (HAVE_truncsfhf2 && from_mode == SFmode && to_mode == HFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncsfhf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncdfhf2
-      if (HAVE_truncdfhf2 && from_mode == DFmode && to_mode == HFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncdfhf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncxfhf2
-      if (HAVE_truncxfhf2 && from_mode == XFmode && to_mode == HFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncxfhf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_trunctfhf2
-      if (HAVE_trunctfhf2 && from_mode == TFmode && to_mode == HFmode)
+      code = tab->handlers[to_mode][from_mode].insn_code;
+      if (code != CODE_FOR_nothing)
        {
-         emit_unop_insn (CODE_FOR_trunctfhf2, to, from, UNKNOWN);
+         emit_unop_insn (code, to, from,
+                         tab == sext_optab ? FLOAT_EXTEND : FLOAT_TRUNCATE);
          return;
        }
-#endif
 
-#ifdef HAVE_truncsftqf2
-      if (HAVE_truncsftqf2 && from_mode == SFmode && to_mode == TQFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncsftqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncdftqf2
-      if (HAVE_truncdftqf2 && from_mode == DFmode && to_mode == TQFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncdftqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncxftqf2
-      if (HAVE_truncxftqf2 && from_mode == XFmode && to_mode == TQFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncxftqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_trunctftqf2
-      if (HAVE_trunctftqf2 && from_mode == TFmode && to_mode == TQFmode)
-       {
-         emit_unop_insn (CODE_FOR_trunctftqf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
+      /* Otherwise use a libcall.  */
+      libcall = tab->handlers[to_mode][from_mode].libfunc;
 
-#ifdef HAVE_truncdfsf2
-      if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncxfsf2
-      if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_trunctfsf2
-      if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode)
-       {
-         emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_truncxfdf2
-      if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode)
-       {
-         emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-#ifdef HAVE_trunctfdf2
-      if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode)
-       {
-         emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-
-      libcall = (rtx) 0;
-      switch (from_mode)
-       {
-       case SFmode:
-         switch (to_mode)
-           {
-           case DFmode:
-             libcall = extendsfdf2_libfunc;
-             break;
-
-           case XFmode:
-             libcall = extendsfxf2_libfunc;
-             break;
-
-           case TFmode:
-             libcall = extendsftf2_libfunc;
-             break;
-
-           default:
-             break;
-           }
-         break;
-
-       case DFmode:
-         switch (to_mode)
-           {
-           case SFmode:
-             libcall = truncdfsf2_libfunc;
-             break;
-
-           case XFmode:
-             libcall = extenddfxf2_libfunc;
-             break;
-
-           case TFmode:
-             libcall = extenddftf2_libfunc;
-             break;
-
-           default:
-             break;
-           }
-         break;
-
-       case XFmode:
-         switch (to_mode)
-           {
-           case SFmode:
-             libcall = truncxfsf2_libfunc;
-             break;
-
-           case DFmode:
-             libcall = truncxfdf2_libfunc;
-             break;
-
-           default:
-             break;
-           }
-         break;
-
-       case TFmode:
-         switch (to_mode)
-           {
-           case SFmode:
-             libcall = trunctfsf2_libfunc;
-             break;
-
-           case DFmode:
-             libcall = trunctfdf2_libfunc;
-             break;
-
-           default:
-             break;
-           }
-         break;
-
-       default:
-         break;
-       }
-
-      if (libcall == (rtx) 0)
+      if (!libcall)
        /* This conversion is not implemented yet.  */
        abort ();
 
@@ -850,6 +634,42 @@ convert_move (rtx to, rtx from, int unsignedp)
       return;
     }
 
+  /* Handle pointer conversion.  */                    /* SPEE 900220.  */
+  /* Targets are expected to provide conversion insns between PxImode and
+     xImode for all MODE_PARTIAL_INT modes they use, but no others.  */
+  if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT)
+    {
+      enum machine_mode full_mode
+       = smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);
+
+      if (trunc_optab->handlers[to_mode][full_mode].insn_code
+         == CODE_FOR_nothing)
+       abort ();
+
+      if (full_mode != from_mode)
+       from = convert_to_mode (full_mode, from, unsignedp);
+      emit_unop_insn (trunc_optab->handlers[to_mode][full_mode].insn_code,
+                     to, from, UNKNOWN);
+      return;
+    }
+  if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT)
+    {
+      enum machine_mode full_mode
+       = smallest_mode_for_size (GET_MODE_BITSIZE (from_mode), MODE_INT);
+
+      if (sext_optab->handlers[full_mode][from_mode].insn_code
+         == CODE_FOR_nothing)
+       abort ();
+
+      emit_unop_insn (sext_optab->handlers[full_mode][from_mode].insn_code,
+                     to, from, UNKNOWN);
+      if (to_mode == full_mode)
+       return;
+
+      /* else proceed to integer conversions below */
+      from_mode = full_mode;
+    }
+
   /* Now both modes are integers.  */
 
   /* Handle expanding beyond a word.  */
@@ -972,119 +792,6 @@ convert_move (rtx to, rtx from, int unsignedp)
       return;
     }
 
-  /* Handle pointer conversion.  */                    /* SPEE 900220.  */
-  if (to_mode == PQImode)
-    {
-      if (from_mode != QImode)
-       from = convert_to_mode (QImode, from, unsignedp);
-
-#ifdef HAVE_truncqipqi2
-      if (HAVE_truncqipqi2)
-       {
-         emit_unop_insn (CODE_FOR_truncqipqi2, to, from, UNKNOWN);
-         return;
-       }
-#endif /* HAVE_truncqipqi2 */
-      abort ();
-    }
-
-  if (from_mode == PQImode)
-    {
-      if (to_mode != QImode)
-       {
-         from = convert_to_mode (QImode, from, unsignedp);
-         from_mode = QImode;
-       }
-      else
-       {
-#ifdef HAVE_extendpqiqi2
-         if (HAVE_extendpqiqi2)
-           {
-             emit_unop_insn (CODE_FOR_extendpqiqi2, to, from, UNKNOWN);
-             return;
-           }
-#endif /* HAVE_extendpqiqi2 */
-         abort ();
-       }
-    }
-
-  if (to_mode == PSImode)
-    {
-      if (from_mode != SImode)
-       from = convert_to_mode (SImode, from, unsignedp);
-
-#ifdef HAVE_truncsipsi2
-      if (HAVE_truncsipsi2)
-       {
-         emit_unop_insn (CODE_FOR_truncsipsi2, to, from, UNKNOWN);
-         return;
-       }
-#endif /* HAVE_truncsipsi2 */
-      abort ();
-    }
-
-  if (from_mode == PSImode)
-    {
-      if (to_mode != SImode)
-       {
-         from = convert_to_mode (SImode, from, unsignedp);
-         from_mode = SImode;
-       }
-      else
-       {
-#ifdef HAVE_extendpsisi2
-         if (! unsignedp && HAVE_extendpsisi2)
-           {
-             emit_unop_insn (CODE_FOR_extendpsisi2, to, from, UNKNOWN);
-             return;
-           }
-#endif /* HAVE_extendpsisi2 */
-#ifdef HAVE_zero_extendpsisi2
-         if (unsignedp && HAVE_zero_extendpsisi2)
-           {
-             emit_unop_insn (CODE_FOR_zero_extendpsisi2, to, from, UNKNOWN);
-             return;
-           }
-#endif /* HAVE_zero_extendpsisi2 */
-         abort ();
-       }
-    }
-
-  if (to_mode == PDImode)
-    {
-      if (from_mode != DImode)
-       from = convert_to_mode (DImode, from, unsignedp);
-
-#ifdef HAVE_truncdipdi2
-      if (HAVE_truncdipdi2)
-       {
-         emit_unop_insn (CODE_FOR_truncdipdi2, to, from, UNKNOWN);
-         return;
-       }
-#endif /* HAVE_truncdipdi2 */
-      abort ();
-    }
-
-  if (from_mode == PDImode)
-    {
-      if (to_mode != DImode)
-       {
-         from = convert_to_mode (DImode, from, unsignedp);
-         from_mode = DImode;
-       }
-      else
-       {
-#ifdef HAVE_extendpdidi2
-         if (HAVE_extendpdidi2)
-           {
-             emit_unop_insn (CODE_FOR_extendpdidi2, to, from, UNKNOWN);
-             return;
-           }
-#endif /* HAVE_extendpdidi2 */
-         abort ();
-       }
-    }
-
   /* Now follow all the conversions between integers
      no more than a word long.  */
 
@@ -1158,140 +865,20 @@ convert_move (rtx to, rtx from, int unsignedp)
     }
 
   /* Support special truncate insns for certain modes.  */
-
-  if (from_mode == DImode && to_mode == SImode)
+  if (trunc_optab->handlers[to_mode][from_mode].insn_code != CODE_FOR_nothing)
     {
-#ifdef HAVE_truncdisi2
-      if (HAVE_truncdisi2)
-       {
-         emit_unop_insn (CODE_FOR_truncdisi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
-      return;
-    }
-
-  if (from_mode == DImode && to_mode == HImode)
-    {
-#ifdef HAVE_truncdihi2
-      if (HAVE_truncdihi2)
-       {
-         emit_unop_insn (CODE_FOR_truncdihi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
-      return;
-    }
-
-  if (from_mode == DImode && to_mode == QImode)
-    {
-#ifdef HAVE_truncdiqi2
-      if (HAVE_truncdiqi2)
-       {
-         emit_unop_insn (CODE_FOR_truncdiqi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
-      return;
-    }
-
-  if (from_mode == SImode && to_mode == HImode)
-    {
-#ifdef HAVE_truncsihi2
-      if (HAVE_truncsihi2)
-       {
-         emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
-      return;
-    }
-
-  if (from_mode == SImode && to_mode == QImode)
-    {
-#ifdef HAVE_truncsiqi2
-      if (HAVE_truncsiqi2)
-       {
-         emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
-      return;
-    }
-
-  if (from_mode == HImode && to_mode == QImode)
-    {
-#ifdef HAVE_trunchiqi2
-      if (HAVE_trunchiqi2)
-       {
-         emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
-      return;
-    }
-
-  if (from_mode == TImode && to_mode == DImode)
-    {
-#ifdef HAVE_trunctidi2
-      if (HAVE_trunctidi2)
-       {
-         emit_unop_insn (CODE_FOR_trunctidi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
-      return;
-    }
-
-  if (from_mode == TImode && to_mode == SImode)
-    {
-#ifdef HAVE_trunctisi2
-      if (HAVE_trunctisi2)
-       {
-         emit_unop_insn (CODE_FOR_trunctisi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
-      return;
-    }
-
-  if (from_mode == TImode && to_mode == HImode)
-    {
-#ifdef HAVE_trunctihi2
-      if (HAVE_trunctihi2)
-       {
-         emit_unop_insn (CODE_FOR_trunctihi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
-      return;
-    }
-
-  if (from_mode == TImode && to_mode == QImode)
-    {
-#ifdef HAVE_trunctiqi2
-      if (HAVE_trunctiqi2)
-       {
-         emit_unop_insn (CODE_FOR_trunctiqi2, to, from, UNKNOWN);
-         return;
-       }
-#endif
-      convert_move (to, force_reg (from_mode, from), unsignedp);
+      emit_unop_insn (trunc_optab->handlers[to_mode][from_mode].insn_code,
+                     to, from, UNKNOWN);
       return;
     }
 
   /* Handle truncation of volatile memrefs, and so on;
      the things that couldn't be truncated directly,
-     and for which there was no special instruction.  */
+     and for which there was no special instruction.
+
+     ??? Code above formerly short-circuited this, for most integer
+     mode pairs, with a force_reg in from_mode followed by a recursive
+     call to this routine.  Appears always to have been wrong.  */
   if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode))
     {
       rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from));
index a0728fa..cded6e3 100644 (file)
@@ -59,32 +59,33 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    upper-case forms of the comparison, respectively.  */
 
 static const char * const optabs[] =
-{ "extendtab[$B][$A][0] = CODE_FOR_$(extend$a$b2$)",
-  "extendtab[$B][$A][1] = CODE_FOR_$(zero_extend$a$b2$)",
-  "fixtab[$A][$B][0] = CODE_FOR_$(fix$F$a$I$b2$)",
-  "fixtab[$A][$B][1] = CODE_FOR_$(fixuns$F$a$b2$)",
-  "fixtrunctab[$A][$B][0] = CODE_FOR_$(fix_trunc$F$a$I$b2$)",
-  "fixtrunctab[$A][$B][1] = CODE_FOR_$(fixuns_trunc$F$a$I$b2$)",
-  "floattab[$B][$A][0] = CODE_FOR_$(float$I$a$F$b2$)",
-  "floattab[$B][$A][1] = CODE_FOR_$(floatuns$I$a$F$b2$)",
+{ "sext_optab->handlers[$B][$A].insn_code = CODE_FOR_$(extend$a$b2$)",
+  "zext_optab->handlers[$B][$A].insn_code = CODE_FOR_$(zero_extend$a$b2$)",
+  "sfix_optab->handlers[$B][$A].insn_code = CODE_FOR_$(fix$F$a$I$b2$)",
+  "ufix_optab->handlers[$B][$A].insn_code = CODE_FOR_$(fixuns$F$a$b2$)",
+  "sfixtrunc_optab->handlers[$B][$A].insn_code = CODE_FOR_$(fix_trunc$F$a$I$b2$)",
+  "ufixtrunc_optab->handlers[$B][$A].insn_code = CODE_FOR_$(fixuns_trunc$F$a$I$b2$)",
+  "sfloat_optab->handlers[$B][$A].insn_code = CODE_FOR_$(float$I$a$F$b2$)",
+  "ufloat_optab->handlers[$B][$A].insn_code = CODE_FOR_$(floatuns$I$a$F$b2$)",
+  "trunc_optab->handlers[$B][$A].insn_code = CODE_FOR_$(trunc$a$b2$)",
   "add_optab->handlers[$A].insn_code = CODE_FOR_$(add$P$a3$)",
-  "addv_optab->handlers[(int) $A].insn_code =\n\
-    add_optab->handlers[(int) $A].insn_code = CODE_FOR_$(add$F$a3$)",
-  "addv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(addv$I$a3$)",
+  "addv_optab->handlers[$A].insn_code =\n\
+    add_optab->handlers[$A].insn_code = CODE_FOR_$(add$F$a3$)",
+  "addv_optab->handlers[$A].insn_code = CODE_FOR_$(addv$I$a3$)",
   "sub_optab->handlers[$A].insn_code = CODE_FOR_$(sub$P$a3$)",
-  "subv_optab->handlers[(int) $A].insn_code =\n\
-    sub_optab->handlers[(int) $A].insn_code = CODE_FOR_$(sub$F$a3$)",
-  "subv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(subv$I$a3$)",
+  "subv_optab->handlers[$A].insn_code =\n\
+    sub_optab->handlers[$A].insn_code = CODE_FOR_$(sub$F$a3$)",
+  "subv_optab->handlers[$A].insn_code = CODE_FOR_$(subv$I$a3$)",
   "smul_optab->handlers[$A].insn_code = CODE_FOR_$(mul$P$a3$)",
-  "smulv_optab->handlers[(int) $A].insn_code =\n\
-    smul_optab->handlers[(int) $A].insn_code = CODE_FOR_$(mul$F$a3$)",
-  "smulv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(mulv$I$a3$)",
+  "smulv_optab->handlers[$A].insn_code =\n\
+    smul_optab->handlers[$A].insn_code = CODE_FOR_$(mul$F$a3$)",
+  "smulv_optab->handlers[$A].insn_code = CODE_FOR_$(mulv$I$a3$)",
   "umul_highpart_optab->handlers[$A].insn_code = CODE_FOR_$(umul$a3_highpart$)",
   "smul_highpart_optab->handlers[$A].insn_code = CODE_FOR_$(smul$a3_highpart$)",
   "smul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(mul$a$b3$)$N",
   "umul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umul$a$b3$)$N",
   "sdiv_optab->handlers[$A].insn_code = CODE_FOR_$(div$a3$)",
-  "sdivv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(div$V$I$a3$)",
+  "sdivv_optab->handlers[$A].insn_code = CODE_FOR_$(div$V$I$a3$)",
   "udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)",
   "sdivmod_optab->handlers[$A].insn_code = CODE_FOR_$(divmod$a4$)",
   "udivmod_optab->handlers[$A].insn_code = CODE_FOR_$(udivmod$a4$)",
@@ -108,13 +109,13 @@ static const char * const optabs[] =
   "pow_optab->handlers[$A].insn_code = CODE_FOR_$(pow$a3$)",
   "atan2_optab->handlers[$A].insn_code = CODE_FOR_$(atan2$a3$)",
   "neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$P$a2$)",
-  "negv_optab->handlers[(int) $A].insn_code =\n\
-    neg_optab->handlers[(int) $A].insn_code = CODE_FOR_$(neg$F$a2$)",
-  "negv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(negv$I$a2$)",
+  "negv_optab->handlers[$A].insn_code =\n\
+    neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$F$a2$)",
+  "negv_optab->handlers[$A].insn_code = CODE_FOR_$(negv$I$a2$)",
   "abs_optab->handlers[$A].insn_code = CODE_FOR_$(abs$P$a2$)",
-  "absv_optab->handlers[(int) $A].insn_code =\n\
-    abs_optab->handlers[(int) $A].insn_code = CODE_FOR_$(abs$F$a2$)",
-  "absv_optab->handlers[(int) $A].insn_code = CODE_FOR_$(absv$I$a2$)",
+  "absv_optab->handlers[$A].insn_code =\n\
+    abs_optab->handlers[$A].insn_code = CODE_FOR_$(abs$F$a2$)",
+  "absv_optab->handlers[$A].insn_code = CODE_FOR_$(absv$I$a2$)",
   "sqrt_optab->handlers[$A].insn_code = CODE_FOR_$(sqrt$a2$)",
   "floor_optab->handlers[$A].insn_code = CODE_FOR_$(floor$a2$)",
   "ceil_optab->handlers[$A].insn_code = CODE_FOR_$(ceil$a2$)",
@@ -229,7 +230,7 @@ gen_insn (rtx insn)
                    look through the modes in reverse order, in case
                    EXTRA_CC_MODES was used and CC is a prefix of the
                    CC modes (as it should be).  */
-               for (i = ((int) MAX_MACHINE_MODE) - 1; i >= 0; i--)
+               for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
                  {
                    for (p = GET_MODE_NAME(i), q = np; *p; p++, q++)
                      if (TOLOWER (*p) != *q)
@@ -303,16 +304,15 @@ gen_insn (rtx insn)
              putchar (TOLOWER (*np));
            break;
          case 'A':
-           printf ("(int) %smode", GET_MODE_NAME(m1));
+           printf ("%smode", GET_MODE_NAME(m1));
            break;
          case 'B':
-           printf ("(int) %smode", GET_MODE_NAME(m2));
+           printf ("%smode", GET_MODE_NAME(m2));
            break;
          case 'c':
            printf ("%s", GET_RTX_NAME(op));
            break;
          case 'C':
-           printf ("(int) ");
            for (np = GET_RTX_NAME(op); *np; np++)
              putchar (TOUPPER (*np));
            break;
@@ -368,7 +368,17 @@ from the machine description file `md'.  */\n\n");
        gen_insn (desc);
     }
 
-  printf ("}\n");
+  puts ("\
+\n\
+#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC\n\
+  /* This flag says the same insns that convert to a signed fixnum\n\
+     also convert validly to an unsigned one.  */\n\
+  for (i = 0; i < NUM_MACHINE_MODES; i++)\n\
+    for (j = 0; j < NUM_MACHINE_MODES; j++)\n\
+      ufixtrunc_optab->handlers[i][j].insn_code\n\
+      = sfixtrunc_optab->handlers[i][j].insn_code;\n\
+#endif\n\
+}");
 
   fflush (stdout);
   return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
index d919ddf..d4bd644 100644 (file)
@@ -24,18 +24,6 @@ Boston, MA 02111-1307, USA.  */
 /* Enumeration of indexes into libfunc_table.  */
 enum libfunc_index
 {
-  LTI_extendsfdf2,
-  LTI_extendsfxf2,
-  LTI_extendsftf2,
-  LTI_extenddfxf2,
-  LTI_extenddftf2,
-
-  LTI_truncdfsf2,
-  LTI_truncxfsf2,
-  LTI_trunctfsf2,
-  LTI_truncxfdf2,
-  LTI_trunctfdf2,
-
   LTI_abort,
   LTI_memcpy,
   LTI_memmove,
@@ -53,54 +41,6 @@ enum libfunc_index
   LTI_unwind_sjlj_register,
   LTI_unwind_sjlj_unregister,
 
-  LTI_floatsisf,
-  LTI_floatdisf,
-  LTI_floattisf,
-
-  LTI_floatsidf,
-  LTI_floatdidf,
-  LTI_floattidf,
-
-  LTI_floatsixf,
-  LTI_floatdixf,
-  LTI_floattixf,
-
-  LTI_floatsitf,
-  LTI_floatditf,
-  LTI_floattitf,
-
-  LTI_fixsfsi,
-  LTI_fixsfdi,
-  LTI_fixsfti,
-
-  LTI_fixdfsi,
-  LTI_fixdfdi,
-  LTI_fixdfti,
-
-  LTI_fixxfsi,
-  LTI_fixxfdi,
-  LTI_fixxfti,
-
-  LTI_fixtfsi,
-  LTI_fixtfdi,
-  LTI_fixtfti,
-
-  LTI_fixunssfsi,
-  LTI_fixunssfdi,
-  LTI_fixunssfti,
-
-  LTI_fixunsdfsi,
-  LTI_fixunsdfdi,
-  LTI_fixunsdfti,
-
-  LTI_fixunsxfsi,
-  LTI_fixunsxfdi,
-  LTI_fixunsxfti,
-
-  LTI_fixunstfsi,
-  LTI_fixunstfdi,
-  LTI_fixunstfti,
-
   LTI_profile_function_entry,
   LTI_profile_function_exit,
 
@@ -115,17 +55,6 @@ enum libfunc_index
 extern GTY(()) rtx libfunc_table[LTI_MAX];
 
 /* Accessor macros for libfunc_table.  */
-#define extendsfdf2_libfunc    (libfunc_table[LTI_extendsfdf2])
-#define extendsfxf2_libfunc    (libfunc_table[LTI_extendsfxf2])
-#define extendsftf2_libfunc    (libfunc_table[LTI_extendsftf2])
-#define extenddfxf2_libfunc    (libfunc_table[LTI_extenddfxf2])
-#define extenddftf2_libfunc    (libfunc_table[LTI_extenddftf2])
-
-#define truncdfsf2_libfunc     (libfunc_table[LTI_truncdfsf2])
-#define truncxfsf2_libfunc     (libfunc_table[LTI_truncxfsf2])
-#define trunctfsf2_libfunc     (libfunc_table[LTI_trunctfsf2])
-#define truncxfdf2_libfunc     (libfunc_table[LTI_truncxfdf2])
-#define trunctfdf2_libfunc     (libfunc_table[LTI_trunctfdf2])
 
 #define abort_libfunc  (libfunc_table[LTI_abort])
 #define memcpy_libfunc (libfunc_table[LTI_memcpy])
@@ -145,54 +74,6 @@ extern GTY(()) rtx libfunc_table[LTI_MAX];
 #define unwind_sjlj_unregister_libfunc \
   (libfunc_table[LTI_unwind_sjlj_unregister])
 
-#define floatsisf_libfunc      (libfunc_table[LTI_floatsisf])
-#define floatdisf_libfunc      (libfunc_table[LTI_floatdisf])
-#define floattisf_libfunc      (libfunc_table[LTI_floattisf])
-
-#define floatsidf_libfunc      (libfunc_table[LTI_floatsidf])
-#define floatdidf_libfunc      (libfunc_table[LTI_floatdidf])
-#define floattidf_libfunc      (libfunc_table[LTI_floattidf])
-
-#define floatsixf_libfunc      (libfunc_table[LTI_floatsixf])
-#define floatdixf_libfunc      (libfunc_table[LTI_floatdixf])
-#define floattixf_libfunc      (libfunc_table[LTI_floattixf])
-
-#define floatsitf_libfunc      (libfunc_table[LTI_floatsitf])
-#define floatditf_libfunc      (libfunc_table[LTI_floatditf])
-#define floattitf_libfunc      (libfunc_table[LTI_floattitf])
-
-#define fixsfsi_libfunc        (libfunc_table[LTI_fixsfsi])
-#define fixsfdi_libfunc        (libfunc_table[LTI_fixsfdi])
-#define fixsfti_libfunc        (libfunc_table[LTI_fixsfti])
-
-#define fixdfsi_libfunc        (libfunc_table[LTI_fixdfsi])
-#define fixdfdi_libfunc        (libfunc_table[LTI_fixdfdi])
-#define fixdfti_libfunc        (libfunc_table[LTI_fixdfti])
-
-#define fixxfsi_libfunc        (libfunc_table[LTI_fixxfsi])
-#define fixxfdi_libfunc        (libfunc_table[LTI_fixxfdi])
-#define fixxfti_libfunc        (libfunc_table[LTI_fixxfti])
-
-#define fixtfsi_libfunc        (libfunc_table[LTI_fixtfsi])
-#define fixtfdi_libfunc        (libfunc_table[LTI_fixtfdi])
-#define fixtfti_libfunc        (libfunc_table[LTI_fixtfti])
-
-#define fixunssfsi_libfunc     (libfunc_table[LTI_fixunssfsi])
-#define fixunssfdi_libfunc     (libfunc_table[LTI_fixunssfdi])
-#define fixunssfti_libfunc     (libfunc_table[LTI_fixunssfti])
-
-#define fixunsdfsi_libfunc     (libfunc_table[LTI_fixunsdfsi])
-#define fixunsdfdi_libfunc     (libfunc_table[LTI_fixunsdfdi])
-#define fixunsdfti_libfunc     (libfunc_table[LTI_fixunsdfti])
-
-#define fixunsxfsi_libfunc     (libfunc_table[LTI_fixunsxfsi])
-#define fixunsxfdi_libfunc     (libfunc_table[LTI_fixunsxfdi])
-#define fixunsxfti_libfunc     (libfunc_table[LTI_fixunsxfti])
-
-#define fixunstfsi_libfunc     (libfunc_table[LTI_fixunstfsi])
-#define fixunstfdi_libfunc     (libfunc_table[LTI_fixunstfdi])
-#define fixunstfti_libfunc     (libfunc_table[LTI_fixunstfti])
-
 #define profile_function_entry_libfunc (libfunc_table[LTI_profile_function_entry])
 #define profile_function_exit_libfunc  (libfunc_table[LTI_profile_function_exit])
 
index b0953eb..bd1bf39 100644 (file)
@@ -58,13 +58,8 @@ optab optab_table[OTI_MAX];
 
 rtx libfunc_table[LTI_MAX];
 
-/* Tables of patterns for extending one integer mode to another.  */
-enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
-
-/* Tables of patterns for converting between fixed and floating point.  */
-enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
-enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
-enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
+/* Tables of patterns for converting one mode to another.  */
+convert_optab convert_optab_table[CTI_MAX];
 
 /* Contains the optab used for each rtx code.  */
 optab code_to_optab[NUM_RTX_CODE + 1];
@@ -112,11 +107,17 @@ static enum insn_code can_fix_p (enum machine_mode, enum machine_mode, int,
 static enum insn_code can_float_p (enum machine_mode, enum machine_mode, int);
 static rtx ftruncify (rtx);
 static optab new_optab (void);
+static convert_optab new_convert_optab (void);
 static inline optab init_optab (enum rtx_code);
 static inline optab init_optabv (enum rtx_code);
+static inline convert_optab init_convert_optab (enum rtx_code);
 static void init_libfuncs (optab, int, int, const char *, int);
 static void init_integral_libfuncs (optab, const char *, int);
 static void init_floating_libfuncs (optab, const char *, int);
+static void init_interclass_conv_libfuncs (convert_optab, const char *,
+                                          enum mode_class, enum mode_class);
+static void init_intraclass_conv_libfuncs (convert_optab, const char *,
+                                          enum mode_class, bool);
 static void emit_cmp_and_jump_insn_1 (rtx, rtx, enum machine_mode,
                                      enum rtx_code, int, rtx);
 static void prepare_float_lib_cmp (rtx *, rtx *, enum rtx_code *,
@@ -4421,12 +4422,14 @@ enum insn_code
 can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode,
              int unsignedp)
 {
+  convert_optab tab;
 #ifdef HAVE_ptr_extend
   if (unsignedp < 0)
     return CODE_FOR_ptr_extend;
-  else
 #endif
-    return extendtab[(int) to_mode][(int) from_mode][unsignedp != 0];
+
+  tab = unsignedp ? zext_optab : sext_optab;
+  return tab->handlers[to_mode][from_mode].insn_code;
 }
 
 /* Generate the body of an insn to extend Y (with mode MFROM)
@@ -4436,7 +4439,8 @@ rtx
 gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
                 enum machine_mode mfrom, int unsignedp)
 {
-  return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp != 0]) (x, y));
+  enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
+  return GEN_FCN (icode) (x, y);
 }
 \f
 /* can_fix_p and can_float_p say whether the target machine
@@ -4452,16 +4456,27 @@ static enum insn_code
 can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
           int unsignedp, int *truncp_ptr)
 {
-  *truncp_ptr = 0;
-  if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0]
-      != CODE_FOR_nothing)
-    return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0];
+  convert_optab tab;
+  enum insn_code icode;
+
+  tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
+  icode = tab->handlers[fixmode][fltmode].insn_code;
+  if (icode != CODE_FOR_nothing)
+    {
+      *truncp_ptr = 0;
+      return icode;
+    }
 
-  if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
+  tab = unsignedp ? ufix_optab : sfix_optab;
+  icode = tab->handlers[fixmode][fltmode].insn_code;
+  if (icode != CODE_FOR_nothing
+      && ftrunc_optab->handlers[fltmode].insn_code != CODE_FOR_nothing)
     {
       *truncp_ptr = 1;
-      return fixtab[(int) fltmode][(int) fixmode][unsignedp != 0];
+      return icode;
     }
+
+  *truncp_ptr = 0;
   return CODE_FOR_nothing;
 }
 
@@ -4469,7 +4484,10 @@ static enum insn_code
 can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
             int unsignedp)
 {
-  return floattab[(int) fltmode][(int) fixmode][unsignedp != 0];
+  convert_optab tab;
+
+  tab = unsignedp ? ufloat_optab : sfloat_optab;
+  return tab->handlers[fltmode][fixmode].insn_code;
 }
 \f
 /* Generate code to convert FROM to floating point
@@ -4642,12 +4660,12 @@ expand_float (rtx to, rtx from, int unsignedp)
       goto done;
     }
 
-  /* No hardware instruction available; call a library routine to convert from
-     SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode.  */
+  /* No hardware instruction available; call a library routine.  */
     {
-      rtx libfcn;
+      rtx libfunc;
       rtx insns;
       rtx value;
+      convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
 
       to = protect_from_queue (to, 1);
       from = protect_from_queue (from, 0);
@@ -4658,56 +4676,13 @@ expand_float (rtx to, rtx from, int unsignedp)
       if (flag_force_mem)
        from = force_not_mem (from);
 
-      if (GET_MODE (to) == SFmode)
-       {
-         if (GET_MODE (from) == SImode)
-           libfcn = floatsisf_libfunc;
-         else if (GET_MODE (from) == DImode)
-           libfcn = floatdisf_libfunc;
-         else if (GET_MODE (from) == TImode)
-           libfcn = floattisf_libfunc;
-         else
-           abort ();
-       }
-      else if (GET_MODE (to) == DFmode)
-       {
-         if (GET_MODE (from) == SImode)
-           libfcn = floatsidf_libfunc;
-         else if (GET_MODE (from) == DImode)
-           libfcn = floatdidf_libfunc;
-         else if (GET_MODE (from) == TImode)
-           libfcn = floattidf_libfunc;
-         else
-           abort ();
-       }
-      else if (GET_MODE (to) == XFmode)
-       {
-         if (GET_MODE (from) == SImode)
-           libfcn = floatsixf_libfunc;
-         else if (GET_MODE (from) == DImode)
-           libfcn = floatdixf_libfunc;
-         else if (GET_MODE (from) == TImode)
-           libfcn = floattixf_libfunc;
-         else
-           abort ();
-       }
-      else if (GET_MODE (to) == TFmode)
-       {
-         if (GET_MODE (from) == SImode)
-           libfcn = floatsitf_libfunc;
-         else if (GET_MODE (from) == DImode)
-           libfcn = floatditf_libfunc;
-         else if (GET_MODE (from) == TImode)
-           libfcn = floattitf_libfunc;
-         else
-           abort ();
-       }
-      else
+      libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
+      if (!libfunc)
        abort ();
 
       start_sequence ();
 
-      value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
+      value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
                                       GET_MODE (to), 1, from,
                                       GET_MODE (from));
       insns = get_insns ();
@@ -4748,7 +4723,6 @@ expand_fix (rtx to, rtx from, int unsignedp)
   rtx target = to;
   enum machine_mode fmode, imode;
   int must_trunc = 0;
-  rtx libfcn = 0;
 
   /* We first try to find a pair of modes, one real and one integer, at
      least as wide as FROM and TO, respectively, in which we can open-code
@@ -4889,57 +4863,16 @@ expand_fix (rtx to, rtx from, int unsignedp)
 
       expand_fix (target, from, unsignedp);
     }
-  else if (GET_MODE (from) == SFmode)
-    {
-      if (GET_MODE (to) == SImode)
-       libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
-      else if (GET_MODE (to) == DImode)
-       libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
-      else if (GET_MODE (to) == TImode)
-       libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
-      else
-       abort ();
-    }
-  else if (GET_MODE (from) == DFmode)
-    {
-      if (GET_MODE (to) == SImode)
-       libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
-      else if (GET_MODE (to) == DImode)
-       libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
-      else if (GET_MODE (to) == TImode)
-       libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
-      else
-       abort ();
-    }
-  else if (GET_MODE (from) == XFmode)
-    {
-      if (GET_MODE (to) == SImode)
-       libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
-      else if (GET_MODE (to) == DImode)
-       libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
-      else if (GET_MODE (to) == TImode)
-       libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
-      else
-       abort ();
-    }
-  else if (GET_MODE (from) == TFmode)
-    {
-      if (GET_MODE (to) == SImode)
-       libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
-      else if (GET_MODE (to) == DImode)
-       libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
-      else if (GET_MODE (to) == TImode)
-       libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
-      else
-       abort ();
-    }
   else
-    abort ();
-
-  if (libfcn)
     {
       rtx insns;
       rtx value;
+      rtx libfunc;
+      
+      convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
+      libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
+      if (!libfunc)
+       abort ();
 
       to = protect_from_queue (to, 1);
       from = protect_from_queue (from, 0);
@@ -4949,7 +4882,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
 
       start_sequence ();
 
-      value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
+      value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
                                       GET_MODE (to), 1, from,
                                       GET_MODE (from));
       insns = get_insns ();
@@ -4994,6 +4927,20 @@ new_optab (void)
   return op;
 }
 
+static convert_optab
+new_convert_optab (void)
+{
+  int i, j;
+  convert_optab op = ggc_alloc (sizeof (struct convert_optab));
+  for (i = 0; i < NUM_MACHINE_MODES; i++)
+    for (j = 0; j < NUM_MACHINE_MODES; j++)
+      {
+       op->handlers[i][j].insn_code = CODE_FOR_nothing;
+       op->handlers[i][j].libfunc = 0;
+      }
+  return op;
+}
+
 /* Same, but fill in its code as CODE, and write it into the
    code_to_optab table.  */
 static inline optab
@@ -5015,6 +4962,15 @@ init_optabv (enum rtx_code code)
   return op;
 }
 
+/* Conversion optabs never go in the code_to_optab table.  */
+static inline convert_optab
+init_convert_optab (enum rtx_code code)
+{
+  convert_optab op = new_convert_optab ();
+  op->code = code;
+  return op;
+}
+
 /* Initialize the libfunc fields of an entire group of entries in some
    optab.  Each entry is set equal to a string consisting of a leading
    pair of underscores followed by a generic operation name followed by
@@ -5101,6 +5057,119 @@ init_floating_libfuncs (optab optable, const char *opname, int suffix)
     init_libfuncs (optable, lmode, lmode, opname, suffix);
 }
 
+/* Initialize the libfunc fields of an entire group of entries of an
+   inter-mode-class conversion optab.  The string formation rules are
+   similar to the ones for init_libfuncs, above, but instead of having
+   a mode name and an operand count these functions have two mode names
+   and no operand count.  */
+static void
+init_interclass_conv_libfuncs (convert_optab tab, const char *opname,
+                              enum mode_class from_class,
+                              enum mode_class to_class)
+{
+  enum machine_mode first_from_mode = GET_CLASS_NARROWEST_MODE (from_class);
+  enum machine_mode first_to_mode = GET_CLASS_NARROWEST_MODE (to_class);
+  size_t opname_len = strlen (opname);
+  size_t max_mname_len = 0;
+
+  enum machine_mode fmode, tmode;
+  const char *fname, *tname;
+  const char *q;
+  char *libfunc_name, *suffix;
+  char *p;
+
+  for (fmode = first_from_mode;
+       fmode != VOIDmode;
+       fmode = GET_MODE_WIDER_MODE (fmode))
+    max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (fmode)));
+
+  for (tmode = first_to_mode;
+       tmode != VOIDmode;
+       tmode = GET_MODE_WIDER_MODE (tmode))
+    max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (tmode)));
+
+  libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1);
+  libfunc_name[0] = '_';
+  libfunc_name[1] = '_';
+  memcpy (&libfunc_name[2], opname, opname_len);
+  suffix = libfunc_name + opname_len + 2;
+
+  for (fmode = first_from_mode; fmode != VOIDmode;
+       fmode = GET_MODE_WIDER_MODE (fmode))
+    for (tmode = first_to_mode; tmode != VOIDmode;
+        tmode = GET_MODE_WIDER_MODE (tmode))
+      {
+       fname = GET_MODE_NAME (fmode);
+       tname = GET_MODE_NAME (tmode);
+
+       p = suffix;
+       for (q = fname; *q; p++, q++)
+         *p = TOLOWER (*q);
+       for (q = tname; *q; p++, q++)
+         *p = TOLOWER (*q);
+
+       *p = '\0';
+
+       tab->handlers[tmode][fmode].libfunc
+         = init_one_libfunc (ggc_alloc_string (libfunc_name,
+                                               p - libfunc_name));
+      }
+}
+
+/* Initialize the libfunc fields of an entire group of entries of an
+   intra-mode-class conversion optab.  The string formation rules are
+   similar to the ones for init_libfunc, above.  WIDENING says whether
+   the optab goes from narrow to wide modes or vice versa.  These functions
+   have two mode names _and_ an operand count.  */
+static void
+init_intraclass_conv_libfuncs (convert_optab tab, const char *opname,
+                              enum mode_class class, bool widening)
+{
+  enum machine_mode first_mode = GET_CLASS_NARROWEST_MODE (class);
+  size_t opname_len = strlen (opname);
+  size_t max_mname_len = 0;
+
+  enum machine_mode nmode, wmode;
+  const char *nname, *wname;
+  const char *q;
+  char *libfunc_name, *suffix;
+  char *p;
+
+  for (nmode = first_mode; nmode != VOIDmode;
+       nmode = GET_MODE_WIDER_MODE (nmode))
+    max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (nmode)));
+
+  libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1);
+  libfunc_name[0] = '_';
+  libfunc_name[1] = '_';
+  memcpy (&libfunc_name[2], opname, opname_len);
+  suffix = libfunc_name + opname_len + 2;
+
+  for (nmode = first_mode; nmode != VOIDmode;
+       nmode = GET_MODE_WIDER_MODE (nmode))
+    for (wmode = GET_MODE_WIDER_MODE (nmode); wmode != VOIDmode;
+        wmode = GET_MODE_WIDER_MODE (wmode))
+      {
+       nname = GET_MODE_NAME (nmode);
+       wname = GET_MODE_NAME (wmode);
+
+       p = suffix;
+       for (q = widening ? nname : wname; *q; p++, q++)
+         *p = TOLOWER (*q);
+       for (q = widening ? wname : nname; *q; p++, q++)
+         *p = TOLOWER (*q);
+
+       *p++ = '2';
+       *p = '\0';
+
+       tab->handlers[widening ? nmode : wmode]
+                    [widening ? wmode : nmode].libfunc
+         = init_one_libfunc (ggc_alloc_string (libfunc_name,
+                                               p - libfunc_name));
+      }
+}
+
+
 rtx
 init_one_libfunc (const char *name)
 {
@@ -5136,36 +5205,29 @@ set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
     optable->handlers[mode].libfunc = 0;
 }
 
+/* Call this to reset the function entry for one conversion optab
+   (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
+   either 0 or a string constant.  */
+void
+set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
+                 enum machine_mode fmode, const char *name)
+{
+  if (name)
+    optable->handlers[tmode][fmode].libfunc = init_one_libfunc (name);
+  else
+    optable->handlers[tmode][fmode].libfunc = 0;
+}
+
 /* Call this once to initialize the contents of the optabs
    appropriately for the current target machine.  */
 
 void
 init_optabs (void)
 {
-  unsigned int i, j, k;
+  unsigned int i;
 
   /* Start by initializing all tables to contain CODE_FOR_nothing.  */
 
-  for (i = 0; i < ARRAY_SIZE (fixtab); i++)
-    for (j = 0; j < ARRAY_SIZE (fixtab[0]); j++)
-      for (k = 0; k < ARRAY_SIZE (fixtab[0][0]); k++)
-       fixtab[i][j][k] = CODE_FOR_nothing;
-
-  for (i = 0; i < ARRAY_SIZE (fixtrunctab); i++)
-    for (j = 0; j < ARRAY_SIZE (fixtrunctab[0]); j++)
-      for (k = 0; k < ARRAY_SIZE (fixtrunctab[0][0]); k++)
-       fixtrunctab[i][j][k] = CODE_FOR_nothing;
-
-  for (i = 0; i < ARRAY_SIZE (floattab); i++)
-    for (j = 0; j < ARRAY_SIZE (floattab[0]); j++)
-      for (k = 0; k < ARRAY_SIZE (floattab[0][0]); k++)
-       floattab[i][j][k] = CODE_FOR_nothing;
-
-  for (i = 0; i < ARRAY_SIZE (extendtab); i++)
-    for (j = 0; j < ARRAY_SIZE (extendtab[0]); j++)
-      for (k = 0; k < ARRAY_SIZE (extendtab[0][0]); k++)
-       extendtab[i][j][k] = CODE_FOR_nothing;
-
   for (i = 0; i < NUM_RTX_CODE; i++)
     setcc_gen_code[i] = CODE_FOR_nothing;
 
@@ -5239,7 +5301,7 @@ init_optabs (void)
   floor_optab = init_optab (UNKNOWN);
   ceil_optab = init_optab (UNKNOWN);
   round_optab = init_optab (UNKNOWN);
-  trunc_optab = init_optab (UNKNOWN);
+  btrunc_optab = init_optab (UNKNOWN);
   nearbyint_optab = init_optab (UNKNOWN);
   sin_optab = init_optab (UNKNOWN);
   cos_optab = init_optab (UNKNOWN);
@@ -5253,6 +5315,17 @@ init_optabs (void)
   cstore_optab = init_optab (UNKNOWN);
   push_optab = init_optab (UNKNOWN);
 
+  /* Conversions.  */
+  sext_optab = init_convert_optab (SIGN_EXTEND);
+  zext_optab = init_convert_optab (ZERO_EXTEND);
+  trunc_optab = init_convert_optab (TRUNCATE);
+  sfix_optab = init_convert_optab (FIX);
+  ufix_optab = init_convert_optab (UNSIGNED_FIX);
+  sfixtrunc_optab = init_convert_optab (UNKNOWN);
+  ufixtrunc_optab = init_convert_optab (UNKNOWN);
+  sfloat_optab = init_convert_optab (FLOAT);
+  ufloat_optab = init_convert_optab (UNSIGNED_FLOAT);
+
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
       movstr_optab[i] = CODE_FOR_nothing;
@@ -5266,14 +5339,6 @@ init_optabs (void)
   /* Fill in the optabs with the insns we support.  */
   init_all_optabs ();
 
-#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
-  /* This flag says the same insns that convert to a signed fixnum
-     also convert validly to an unsigned one.  */
-  for (i = 0; i < NUM_MACHINE_MODES; i++)
-    for (j = 0; j < NUM_MACHINE_MODES; j++)
-      fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
-#endif
-
   /* Initialize the optabs with the names of the library functions.  */
   init_integral_libfuncs (add_optab, "add", '3');
   init_floating_libfuncs (add_optab, "add", '3');
@@ -5333,26 +5398,24 @@ init_optabs (void)
   init_floating_libfuncs (le_optab, "le", '2');
   init_floating_libfuncs (unord_optab, "unord", '2');
 
-  /* Use cabs for DC complex abs, since systems generally have cabs.
-     Don't define any libcall for SCmode, so that cabs will be used.  */
-  abs_optab->handlers[(int) DCmode].libfunc
-    = init_one_libfunc ("cabs");
+  /* Conversions.  */
+  init_interclass_conv_libfuncs (sfloat_optab, "float", MODE_INT, MODE_FLOAT);
+  init_interclass_conv_libfuncs (sfix_optab, "fix",     MODE_FLOAT, MODE_INT);
+  init_interclass_conv_libfuncs (ufix_optab, "fixuns",  MODE_FLOAT, MODE_INT);
 
-  /* The ffs function operates on `int'.  */
-  ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc
-    = init_one_libfunc ("ffs");
+  /* sext_optab is also used for FLOAT_EXTEND.  */
+  init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true);
+  init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, false);
 
-  extendsfdf2_libfunc = init_one_libfunc ("__extendsfdf2");
-  extendsfxf2_libfunc = init_one_libfunc ("__extendsfxf2");
-  extendsftf2_libfunc = init_one_libfunc ("__extendsftf2");
-  extenddfxf2_libfunc = init_one_libfunc ("__extenddfxf2");
-  extenddftf2_libfunc = init_one_libfunc ("__extenddftf2");
+  /* Use cabs for double complex abs, since systems generally have cabs.
+     Don't define any libcall for float complex, so that cabs will be used.  */
+  if (complex_double_type_node)
+    abs_optab->handlers[TYPE_MODE (complex_double_type_node)].libfunc
+      = init_one_libfunc ("cabs");
 
-  truncdfsf2_libfunc = init_one_libfunc ("__truncdfsf2");
-  truncxfsf2_libfunc = init_one_libfunc ("__truncxfsf2");
-  trunctfsf2_libfunc = init_one_libfunc ("__trunctfsf2");
-  truncxfdf2_libfunc = init_one_libfunc ("__truncxfdf2");
-  trunctfdf2_libfunc = init_one_libfunc ("__trunctfdf2");
+  /* The ffs function op[1erates on `int'.  */
+  ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc
+    = init_one_libfunc ("ffs");
 
   abort_libfunc = init_one_libfunc ("abort");
   memcpy_libfunc = init_one_libfunc ("memcpy");
@@ -5378,54 +5441,6 @@ init_optabs (void)
   unwind_sjlj_unregister_libfunc
     = init_one_libfunc ("_Unwind_SjLj_Unregister");
 
-  floatsisf_libfunc = init_one_libfunc ("__floatsisf");
-  floatdisf_libfunc = init_one_libfunc ("__floatdisf");
-  floattisf_libfunc = init_one_libfunc ("__floattisf");
-
-  floatsidf_libfunc = init_one_libfunc ("__floatsidf");
-  floatdidf_libfunc = init_one_libfunc ("__floatdidf");
-  floattidf_libfunc = init_one_libfunc ("__floattidf");
-
-  floatsixf_libfunc = init_one_libfunc ("__floatsixf");
-  floatdixf_libfunc = init_one_libfunc ("__floatdixf");
-  floattixf_libfunc = init_one_libfunc ("__floattixf");
-
-  floatsitf_libfunc = init_one_libfunc ("__floatsitf");
-  floatditf_libfunc = init_one_libfunc ("__floatditf");
-  floattitf_libfunc = init_one_libfunc ("__floattitf");
-
-  fixsfsi_libfunc = init_one_libfunc ("__fixsfsi");
-  fixsfdi_libfunc = init_one_libfunc ("__fixsfdi");
-  fixsfti_libfunc = init_one_libfunc ("__fixsfti");
-
-  fixdfsi_libfunc = init_one_libfunc ("__fixdfsi");
-  fixdfdi_libfunc = init_one_libfunc ("__fixdfdi");
-  fixdfti_libfunc = init_one_libfunc ("__fixdfti");
-
-  fixxfsi_libfunc = init_one_libfunc ("__fixxfsi");
-  fixxfdi_libfunc = init_one_libfunc ("__fixxfdi");
-  fixxfti_libfunc = init_one_libfunc ("__fixxfti");
-
-  fixtfsi_libfunc = init_one_libfunc ("__fixtfsi");
-  fixtfdi_libfunc = init_one_libfunc ("__fixtfdi");
-  fixtfti_libfunc = init_one_libfunc ("__fixtfti");
-
-  fixunssfsi_libfunc = init_one_libfunc ("__fixunssfsi");
-  fixunssfdi_libfunc = init_one_libfunc ("__fixunssfdi");
-  fixunssfti_libfunc = init_one_libfunc ("__fixunssfti");
-
-  fixunsdfsi_libfunc = init_one_libfunc ("__fixunsdfsi");
-  fixunsdfdi_libfunc = init_one_libfunc ("__fixunsdfdi");
-  fixunsdfti_libfunc = init_one_libfunc ("__fixunsdfti");
-
-  fixunsxfsi_libfunc = init_one_libfunc ("__fixunsxfsi");
-  fixunsxfdi_libfunc = init_one_libfunc ("__fixunsxfdi");
-  fixunsxfti_libfunc = init_one_libfunc ("__fixunsxfti");
-
-  fixunstfsi_libfunc = init_one_libfunc ("__fixunstfsi");
-  fixunstfdi_libfunc = init_one_libfunc ("__fixunstfdi");
-  fixunstfti_libfunc = init_one_libfunc ("__fixunstfti");
-
   /* For function entry/exit instrumentation.  */
   profile_function_entry_libfunc
     = init_one_libfunc ("__cyg_profile_func_enter");
index 02c0af5..d8448af 100644 (file)
@@ -38,19 +38,32 @@ Boston, MA 02111-1307, USA.  */
    A few optabs, such as move_optab and cmp_optab, are used
    by special code.  */
 
+struct optab_handlers GTY(())
+{
+  enum insn_code insn_code;
+  rtx libfunc;
+};
+
 struct optab GTY(())
 {
   enum rtx_code code;
-  struct optab_handlers {
-    enum insn_code insn_code;
-    rtx libfunc;
-  } handlers [NUM_MACHINE_MODES];
+  struct optab_handlers handlers[NUM_MACHINE_MODES];
 };
 typedef struct optab * optab;
 
+/* A convert_optab is for some sort of conversion operation between
+   modes.  The first array index is the destination mode, the second
+   is the source mode.  */
+struct convert_optab GTY(())
+{
+  enum rtx_code code;
+  struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
+};
+typedef struct convert_optab *convert_optab;
+
 /* Given an enum insn_code, access the function to construct
    the body of that kind of insn.  */
-#define GEN_FCN(CODE) (*insn_data[(int) (CODE)].genfun)
+#define GEN_FCN(CODE) (insn_data[CODE].genfun)
 
 /* Enumeration of valid indexes into optab_table.  */
 enum optab_index
@@ -242,7 +255,7 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define log_optab (optab_table[OTI_log])
 #define floor_optab (optab_table[OTI_floor])
 #define ceil_optab (optab_table[OTI_ceil])
-#define trunc_optab (optab_table[OTI_trunc])
+#define btrunc_optab (optab_table[OTI_trunc])
 #define round_optab (optab_table[OTI_round])
 #define nearbyint_optab (optab_table[OTI_nearbyint])
 #define tan_optab (optab_table[OTI_tan])
@@ -268,13 +281,36 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define push_optab (optab_table[OTI_push])
 #define addcc_optab (optab_table[OTI_addcc])
 
-/* Tables of patterns for extending one integer mode to another.  */
-extern enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
+/* Conversion optabs have their own table and indexes.  */
+enum convert_optab_index
+{
+  CTI_sext,
+  CTI_zext,
+  CTI_trunc,
+
+  CTI_sfix,
+  CTI_ufix,
+
+  CTI_sfixtrunc,
+  CTI_ufixtrunc,
+
+  CTI_sfloat,
+  CTI_ufloat,
+
+  CTI_MAX
+};
+
+extern GTY(()) convert_optab convert_optab_table[CTI_MAX];
 
-/* Tables of patterns for converting between fixed and floating point.  */
-extern enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
-extern enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
-extern enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
+#define sext_optab (convert_optab_table[CTI_sext])
+#define zext_optab (convert_optab_table[CTI_zext])
+#define trunc_optab (convert_optab_table[CTI_trunc])
+#define sfix_optab (convert_optab_table[CTI_sfix])
+#define ufix_optab (convert_optab_table[CTI_ufix])
+#define sfixtrunc_optab (convert_optab_table[CTI_sfixtrunc])
+#define ufixtrunc_optab (convert_optab_table[CTI_ufixtrunc])
+#define sfloat_optab (convert_optab_table[CTI_sfloat])
+#define ufloat_optab (convert_optab_table[CTI_ufloat])
 
 /* These arrays record the insn_code of insns that may be needed to
    perform input and output reloads of special objects.  They provide a
@@ -385,6 +421,8 @@ extern void init_floattab (void);
 
 /* Call this to reset the function entry for one optab.  */
 extern void set_optab_libfunc (optab, enum machine_mode, const char *);
+extern void set_conv_libfunc (convert_optab, enum machine_mode,
+                             enum machine_mode, const char *);
 
 /* Generate code for a FLOAT_EXPR.  */
 extern void expand_float (rtx, rtx, int);