Added soft float support for IA32 backend.
authorSebastian Buchwald <Sebastian.Buchwald@kit.edu>
Thu, 11 Aug 2011 13:26:39 +0000 (15:26 +0200)
committerSebastian Buchwald <Sebastian.Buchwald@kit.edu>
Fri, 12 Aug 2011 12:40:31 +0000 (14:40 +0200)
ir/be/ia32/bearch_ia32.c
ir/be/ia32/bearch_ia32_t.h
ir/be/ia32/ia32_architecture.c
ir/be/ia32/ia32_architecture.h

index b2c07d4..534c4b6 100644 (file)
@@ -53,6 +53,7 @@
 #include "iropt_t.h"
 #include "lower_dw.h"
 #include "lower_calls.h"
+#include "lower_softfloat.h"
 
 #include "../beabi.h"
 #include "../beirg.h"
@@ -1455,6 +1456,7 @@ static ia32_isa_t ia32_isa_template = {
        NULL,                    /* types */
        NULL,                    /* tv_ents */
        NULL,                    /* abstract machine */
+       IA32_FPU_ARCH_X87,       /* FPU architecture */
 };
 
 static void init_asm_constraints(void)
@@ -2024,6 +2026,11 @@ static void ia32_lower_for_target(void)
        /* lower compound param handling */
        lower_calls_with_compounds(LF_RETURN_HIDDEN);
 
+       /* replace floating point operations by function calls */
+       if (ia32_cg_config.use_softfloat) {
+               lower_floating_point();
+       }
+
        ir_prepare_dw_lowering(&lower_dw_params);
        ir_lower_dw_ops();
 
@@ -2116,7 +2123,10 @@ static const backend_params *ia32_get_libfirm_params(void)
        p.type_long_long          = type_long_long;
        p.type_unsigned_long_long = type_unsigned_long_long;
 
-       if (! ia32_cg_config.use_sse2) {
+       if (ia32_cg_config.use_sse2 || ia32_cg_config.use_softfloat) {
+               p.mode_float_arithmetic = NULL;
+               p.type_long_double = NULL;
+       } else {
                p.mode_float_arithmetic = mode_E;
                ir_mode *mode = new_ir_mode("long double", irms_float_number, 80, 1,
                                            irma_ieee754, 0);
@@ -2124,9 +2134,6 @@ static const backend_params *ia32_get_libfirm_params(void)
                set_type_size_bytes(type, 12);
                set_type_alignment_bytes(type, 4);
                p.type_long_double = type;
-       } else {
-               p.mode_float_arithmetic = NULL;
-               p.type_long_double = NULL;
        }
        return &p;
 }
index 91514bb..4fa7c08 100644 (file)
@@ -68,6 +68,7 @@ struct ia32_isa_t {
        pmap                  *types;           /**< A map of modes to primitivetypes */
        pmap                  *tv_ent;          /**< A map of entities that store const tarvals */
        const be_machine_t    *cpu;             /**< the abstract machine */
+       int                    fpu_arch;        /**< FPU architecture */
 };
 
 /**
index 798a88d..0e93077 100644 (file)
@@ -150,7 +150,7 @@ static int         opt_size             = 0;
 static int         emit_machcode        = 0;
 static cpu_support arch                 = cpu_generic;
 static cpu_support opt_arch             = cpu_generic;
-static int         use_sse2             = 0;
+static int         fpu_arch             = 0;
 static int         opt_cc               = 1;
 static int         opt_unsafe_floatconv = 0;
 
@@ -222,13 +222,14 @@ static lc_opt_enum_int_var_t opt_arch_var = {
 };
 
 static const lc_opt_enum_int_items_t fp_unit_items[] = {
-       { "x87" ,    0 },
-       { "sse2",    1 },
-       { NULL,      0 }
+       { "x87" ,      IA32_FPU_ARCH_X87 },
+       { "sse2",      IA32_FPU_ARCH_SSE2 },
+       { "softfloat", IA32_FPU_ARCH_SOFTFLOAT },
+       { NULL,        IA32_FPU_ARCH_NONE }
 };
 
 static lc_opt_enum_int_var_t fp_unit_var = {
-       &use_sse2, fp_unit_items
+       &fpu_arch, fp_unit_items
 };
 
 static const lc_opt_table_entry_t ia32_architecture_options[] = {
@@ -881,7 +882,8 @@ void ia32_setup_cg_config(void)
        /* P4s don't like inc/decs because they only partially write the flags
         * register which produces false dependencies */
        c->use_incdec           = !FLAGS(opt_arch, arch_netburst | arch_nocona | arch_core2 | arch_geode) || opt_size;
-       c->use_sse2             = use_sse2 && FLAGS(arch, arch_feature_sse2);
+       c->use_softfloat        = FLAGS(fpu_arch, IA32_FPU_ARCH_SOFTFLOAT);
+       c->use_sse2             = FLAGS(fpu_arch, IA32_FPU_ARCH_SSE2) && FLAGS(arch, arch_feature_sse2);
        c->use_ffreep           = FLAGS(opt_arch, arch_athlon_plus);
        c->use_ftst             = !FLAGS(arch, arch_feature_p6_insn);
        /* valgrind can't cope with femms yet and the usefulness of the optimization
index 84c0938..2b65043 100644 (file)
@@ -33,6 +33,8 @@ typedef struct {
        unsigned use_leave:1;
        /** use inc, dec instead of add $1, reg and add $-1, reg */
        unsigned use_incdec:1;
+       /** use soft float library */
+       unsigned use_softfloat:1;
        /** use sse2 instructions (instead of x87) */
        unsigned use_sse2:1;
        /** use ffreep instead of fpop */
@@ -104,6 +106,14 @@ typedef struct {
 
 extern ia32_code_gen_config_t  ia32_cg_config;
 
+typedef enum ia32_fp_architectures {
+       IA32_FPU_ARCH_NONE      = 0,
+       IA32_FPU_ARCH_X87       = 0x00000001,
+       IA32_FPU_ARCH_SSE2      = 0x00000002,
+       IA32_FPU_ARCH_SOFTFLOAT = 0x00000004,
+}
+ia32_fp_architectures;
+
 /** Initialize the ia32 architecture module. */
 void ia32_init_architecture(void);