#include "iropt_t.h"
#include "lower_dw.h"
#include "lower_calls.h"
+#include "lower_softfloat.h"
#include "../beabi.h"
#include "../beirg.h"
NULL, /* types */
NULL, /* tv_ents */
NULL, /* abstract machine */
+ IA32_FPU_ARCH_X87, /* FPU architecture */
};
static void init_asm_constraints(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();
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);
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;
}
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 */
};
/**
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;
};
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[] = {
/* 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
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 */
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);