From: Matthias Braun Date: Tue, 25 Oct 2011 12:47:25 +0000 (+0200) Subject: ir_mode: simplify interface, improve float-mode handling X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=e3b765fcef0e337f4fe2e17d57d2fbaf1912ec79;p=libfirm ir_mode: simplify interface, improve float-mode handling The main change here is splitting new_ir_mode into new_int_mode, new_reference_mode and new_float_mode. You can now specify mantissa+exponent size in new_float_mode. This also changes: - x86 80bit-FP mode is NOT a ieee754 don't put "ieee754" into functions names that can also handle x86 80bit fps - Move ieee_descriptor_t from tarval module into ir_mode struct (and rename to float_descriptor_t) - Introduce mode_Q which represents binary128 from ieee754 - You can ask float modes for mantissa/exponent sizes now - Fix endianess when emitting big float values in begnuas - A bunch of long double fixes in ia32: the mode there has 10bytes (80bit) but the variables typically are 12 or 16 byte big - This fixes some problems of sparc binary128 handling --- diff --git a/include/libfirm/irhooks.h b/include/libfirm/irhooks.h index c981f6318..914ec5c86 100644 --- a/include/libfirm/irhooks.h +++ b/include/libfirm/irhooks.h @@ -163,7 +163,7 @@ typedef struct hook_entry { void (*_hook_arch_dep_replace_division_by_const)(void *context, ir_node *irn); /** This hook is called after a new mode was registered. */ - void (*_hook_new_mode)(void *context, const ir_mode *tmpl, ir_mode *mode); + void (*_hook_new_mode)(void *context, ir_mode *mode); /** This hook is called after a new entity was created. */ void (*_hook_new_entity)(void *context, ir_entity *ent); @@ -281,7 +281,7 @@ FIRM_API hook_entry_t *hooks[hook_last]; hook_exec(hook_arch_dep_replace_mul_with_shifts, (hook_ctx_, irn)) #define hook_arch_dep_replace_division_by_const(irn) \ hook_exec(hook_arch_dep_replace_division_by_const, (hook_ctx_, irn)) -#define hook_new_mode(tmpl, mode) hook_exec(hook_new_mode, (hook_ctx_, tmpl, mode)) +#define hook_new_mode(mode) hook_exec(hook_new_mode, (hook_ctx_, mode)) #define hook_new_entity(ent) hook_exec(hook_new_entity, (hook_ctx_, ent)) #define hook_new_type(tp) hook_exec(hook_new_type, (hook_ctx_, tp)) #define hook_node_info(F, node) hook_exec(hook_node_info, (hook_ctx_, F, node)) diff --git a/include/libfirm/irmode.h b/include/libfirm/irmode.h index c07e4cdaf..e6d4af821 100644 --- a/include/libfirm/irmode.h +++ b/include/libfirm/irmode.h @@ -38,39 +38,6 @@ #include "firm_types.h" #include "begin.h" -/** Helper values for ir_mode_sort. */ -enum ir_mode_sort_helper { - irmsh_is_num = 0x10, /**< mode represents a number */ - irmsh_is_data = 0x20, /**< mode represents data (can be carried in registers) */ - irmsh_is_datab = 0x40, /**< mode represents data or is internal boolean */ - irmsh_is_dataM = 0x80, /**< mode represents data or is memory */ -}; - -/** - * These values represent the different mode classes of value representations. - * Beware: do not change the order of these values without checking - * the mode_is - */ -typedef enum ir_mode_sort { - irms_auxiliary = 0, /**< Only for Firm use. Not extensible. (irm_T) */ - irms_control_flow = 1, /**< Marks all control flow modes. Not extensible. (irm_BB, irm_X) */ - irms_memory = 2 | irmsh_is_dataM, /**< Marks the memory mode. Not extensible. (irm_M) */ - - /** Internal boolean representation. - Storing to memory impossible, convert first. (irm_b) */ - irms_internal_boolean = 3 | irmsh_is_datab, - - /** A mode to represent entities. - Restricted int computations can be performed */ - irms_reference = 4 | irmsh_is_data | irmsh_is_datab | irmsh_is_dataM, - /** A mode to represent int numbers. - Integer computations can be performed. */ - irms_int_number = 5 | irmsh_is_data | irmsh_is_datab | irmsh_is_dataM | irmsh_is_num, - /** A mode to represent float numbers. - Floating point computations can be performed. */ - irms_float_number = 6 | irmsh_is_data | irmsh_is_datab | irmsh_is_dataM | irmsh_is_num, -} ir_mode_sort; - /** * These values represent the different arithmetic operations possible with a * mode. @@ -86,6 +53,7 @@ typedef enum ir_mode_arithmetic { irma_ieee754 = 256, /**< Values of the mode are represented according to ieee754 floating point standard. Only legal for modes of sort float_number. */ + irma_x86_extended_float, /**< x86 extended floatingpoint values */ irma_max } ir_mode_arithmetic; @@ -105,21 +73,38 @@ FIRM_API const char *get_mode_arithmetic_name(ir_mode_arithmetic ari); * This function constructs a new mode given by the parameters. * If the parameters match an already defined mode, this mode is returned * (including the default modes). - * If the mode is newly allocated, a new unique mode_code is chosen. - * Also, special value tarvals will be calculated such as null, - * min, max and can be retrieved using the get_mode_* functions * * @return * The new mode or NULL on error. + */ +FIRM_API ir_mode *new_int_mode(const char *name, + ir_mode_arithmetic arithmetic, + unsigned bit_size, int sign, + unsigned modulo_shift); + +/** + * Create a new reference mode. + * + * Reference modes are always unsigned. + */ +FIRM_API ir_mode *new_reference_mode(const char *name, + ir_mode_arithmetic arithmetic, + unsigned bit_size, + unsigned modulo_shift); + +/** + * Create a new ieee754 float mode. * - * @note - * It is allowed to construct the default modes. So, a call - * new_ir_mode("Is", irms_int_number, 32, 1, irma_twos_complement, 32) will - * return mode_Is. + * float-modes are always signed and have no modulo shift. + * @param name the name of the mode to be created + * @param arithmetic arithmetic/representation of the mode + * @param exponent_size size of exponent in bits + * @param mantissa_size size of mantissa in bits */ -FIRM_API ir_mode *new_ir_mode(const char *name, ir_mode_sort sort, int bit_size, - int sign, ir_mode_arithmetic arithmetic, - unsigned int modulo_shift); +FIRM_API ir_mode *new_float_mode(const char *name, + ir_mode_arithmetic arithmetic, + unsigned exponent_size, + unsigned mantissa_size); /** * Checks whether a pointer points to a mode. @@ -137,9 +122,6 @@ FIRM_API ident *get_mode_ident(const ir_mode *mode); /** Returns the null-terminated name of this mode. */ FIRM_API const char *get_mode_name(const ir_mode *mode); -/** Returns a coarse classification of the mode. */ -FIRM_API ir_mode_sort get_mode_sort(const ir_mode *mode); - /** Returns the size of values of the mode in bits. */ FIRM_API unsigned get_mode_size_bits(const ir_mode *mode); @@ -237,9 +219,9 @@ FIRM_API ir_tarval *get_mode_NAN(ir_mode *mode); FIRM_API ir_mode *mode_M; /**< memory */ -FIRM_API ir_mode *mode_F; /**< float (32) */ -FIRM_API ir_mode *mode_D; /**< double (64) */ -FIRM_API ir_mode *mode_E; /**< long double (80/128/...) */ +FIRM_API ir_mode *mode_F; /**< ieee754 binary32 float (single precision) */ +FIRM_API ir_mode *mode_D; /**< ieee754 binary64 float (double precision) */ +FIRM_API ir_mode *mode_Q; /**< ieee754 binary128 float (quadruple precision)*/ FIRM_API ir_mode *mode_Bs; /**< int8 */ FIRM_API ir_mode *mode_Bu; /**< uint8 */ FIRM_API ir_mode *mode_Hs; /**< int16 */ @@ -270,7 +252,7 @@ FIRM_API ir_mode *mode_BAD;/**< bad mode */ FIRM_API ir_mode *get_modeF(void); FIRM_API ir_mode *get_modeD(void); -FIRM_API ir_mode *get_modeE(void); +FIRM_API ir_mode *get_modeQ(void); FIRM_API ir_mode *get_modeBs(void); FIRM_API ir_mode *get_modeBu(void); FIRM_API ir_mode *get_modeHs(void); @@ -424,6 +406,16 @@ FIRM_API ir_mode *get_reference_mode_unsigned_eq(ir_mode *mode); */ FIRM_API void set_reference_mode_unsigned_eq(ir_mode *ref_mode, ir_mode *int_mode); +/** + * Return size of mantissa in bits (for float modes) + */ +FIRM_API unsigned get_mode_mantissa_size(const ir_mode *mode); + +/** + * Return size of exponent in bits (for float modes) + */ +FIRM_API unsigned get_mode_exponent_size(const ir_mode *mode); + /** * Returns non-zero if the cast from mode src to mode dst is a * reinterpret cast (ie. only the bit pattern is reinterpreted, diff --git a/include/libfirm/tv.h b/include/libfirm/tv.h index f5c877e86..10693fb44 100644 --- a/include/libfirm/tv.h +++ b/include/libfirm/tv.h @@ -753,12 +753,12 @@ FIRM_API int tarval_snprintf(char *buf, size_t buflen, ir_tarval *tv); FIRM_API int tarval_printf(ir_tarval *tv); /** - * Returns non-zero if the mantissa of a floating point IEEE-754 - * tarval is zero (i.e. 1.0Exxx) + * Returns non-zero if the mantissa of a floating point tarval is zero + * (i.e. 1.0Exxx) * * @param tv the tarval */ -FIRM_API int tarval_ieee754_zero_mantissa(ir_tarval *tv); +FIRM_API int tarval_zero_mantissa(ir_tarval *tv); /** * Returns the exponent of a floating point IEEE-754 @@ -766,7 +766,7 @@ FIRM_API int tarval_ieee754_zero_mantissa(ir_tarval *tv); * * @param tv the tarval */ -FIRM_API int tarval_ieee754_get_exponent(ir_tarval *tv); +FIRM_API int tarval_get_exponent(ir_tarval *tv); /** * Check if the tarval can be converted to the given mode without @@ -778,16 +778,10 @@ FIRM_API int tarval_ieee754_get_exponent(ir_tarval *tv); FIRM_API int tarval_ieee754_can_conv_lossless(ir_tarval *tv, ir_mode *mode); /** - * Returns non-zero if the result of the last IEEE-754 operation was exact. + * Returns non-zero if the result of the last IEEE-754 operation was exact. */ FIRM_API unsigned tarval_ieee754_get_exact(void); -/** - * Return the size of the mantissa in bits (including possible - * implicit bits) for the given mode. - */ -FIRM_API unsigned tarval_ieee754_get_mantissa_size(const ir_mode *mode); - /** * Enable/Disable floating point constant folding. */ diff --git a/ir/ana/irmemory.c b/ir/ana/irmemory.c index f1f587016..bbf1a6f50 100644 --- a/ir/ana/irmemory.c +++ b/ir/ana/irmemory.c @@ -820,7 +820,6 @@ static int is_hidden_cast(const ir_mode *mode, const ir_mode *ent_mode) if (ent_mode != mode) { if (ent_mode == NULL || get_mode_size_bits(ent_mode) != get_mode_size_bits(mode) || - get_mode_sort(ent_mode) != get_mode_sort(mode) || get_mode_arithmetic(ent_mode) != irma_twos_complement || get_mode_arithmetic(mode) != irma_twos_complement) return true; diff --git a/ir/be/TEMPLATE/TEMPLATE_spec.pl b/ir/be/TEMPLATE/TEMPLATE_spec.pl index 63ed2059e..0a63c5b99 100644 --- a/ir/be/TEMPLATE/TEMPLATE_spec.pl +++ b/ir/be/TEMPLATE/TEMPLATE_spec.pl @@ -9,7 +9,7 @@ $arch = "TEMPLATE"; # Modes # $mode_gp = "mode_Iu"; # mode used by general purpose registers -$mode_fp = "mode_E"; # mode used by floatingpoint registers +$mode_fp = "mode_F"; # mode used by floatingpoint registers # The node description is done as a perl hash initializer with the # following structure: diff --git a/ir/be/arm/arm_spec.pl b/ir/be/arm/arm_spec.pl index 306770e5c..39419ff52 100644 --- a/ir/be/arm/arm_spec.pl +++ b/ir/be/arm/arm_spec.pl @@ -10,7 +10,7 @@ $arch = "arm"; # $mode_gp = "mode_Iu"; $mode_flags = "mode_Bu"; -$mode_fp = "mode_E"; +$mode_fp = "mode_F"; # NOTE: Last entry of each class is the largest Firm-Mode a register can hold %reg_classes = ( diff --git a/ir/be/arm/arm_transform.c b/ir/be/arm/arm_transform.c index 3cc07d88e..7e7377751 100644 --- a/ir/be/arm/arm_transform.c +++ b/ir/be/arm/arm_transform.c @@ -539,7 +539,6 @@ static ir_node *gen_Add(ir_node *node) if (USE_FPA(isa)) { return new_bd_arm_Adf(dbgi, block, new_op1, new_op2, mode); } else if (USE_VFP(isa)) { - assert(mode != mode_E && "IEEE Extended FP not supported"); panic("VFP not supported yet"); } else { panic("Softfloat not supported yet"); @@ -586,7 +585,6 @@ static ir_node *gen_Mul(ir_node *node) if (USE_FPA(isa)) { return new_bd_arm_Muf(dbg, block, new_op1, new_op2, mode); } else if (USE_VFP(isa)) { - assert(mode != mode_E && "IEEE Extended FP not supported"); panic("VFP not supported yet"); } else { panic("Softfloat not supported yet"); @@ -606,14 +604,12 @@ static ir_node *gen_Div(ir_node *node) ir_mode *mode = get_Div_resmode(node); dbg_info *dbg = get_irn_dbg_info(node); - assert(mode != mode_E && "IEEE Extended FP not supported"); /* integer division should be replaced by builtin call */ assert(mode_is_float(mode)); if (USE_FPA(isa)) { return new_bd_arm_Dvf(dbg, block, new_op1, new_op2, mode); } else if (USE_VFP(isa)) { - assert(mode != mode_E && "IEEE Extended FP not supported"); panic("VFP not supported yet"); } else { panic("Softfloat not supported yet"); @@ -700,7 +696,6 @@ static ir_node *gen_Sub(ir_node *node) if (USE_FPA(isa)) { return new_bd_arm_Suf(dbgi, block, new_op1, new_op2, mode); } else if (USE_VFP(isa)) { - assert(mode != mode_E && "IEEE Extended FP not supported"); panic("VFP not supported yet"); } else { panic("Softfloat not supported yet"); @@ -926,7 +921,6 @@ static ir_node *gen_Minus(ir_node *node) if (USE_FPA(isa)) { return new_bd_arm_Mvf(dbgi, block, op, mode); } else if (USE_VFP(isa)) { - assert(mode != mode_E && "IEEE Extended FP not supported"); panic("VFP not supported yet"); } else { panic("Softfloat not supported yet"); @@ -955,7 +949,6 @@ static ir_node *gen_Load(ir_node *node) new_load = new_bd_arm_Ldf(dbgi, block, new_ptr, new_mem, mode, NULL, 0, 0, false); } else if (USE_VFP(isa)) { - assert(mode != mode_E && "IEEE Extended FP not supported"); panic("VFP not supported yet"); } else { panic("Softfloat not supported yet"); @@ -998,7 +991,6 @@ static ir_node *gen_Store(ir_node *node) new_store = new_bd_arm_Stf(dbgi, block, new_ptr, new_val, new_mem, mode, NULL, 0, 0, false); } else if (USE_VFP(isa)) { - assert(mode != mode_E && "IEEE Extended FP not supported"); panic("VFP not supported yet"); } else { panic("Softfloat not supported yet"); @@ -1119,8 +1111,7 @@ static ir_node *gen_Cond(ir_node *node) enum fpa_imm_mode { FPA_IMM_FLOAT = 0, FPA_IMM_DOUBLE = 1, - FPA_IMM_EXTENDED = 2, - FPA_IMM_MAX = FPA_IMM_EXTENDED + FPA_IMM_MAX = FPA_IMM_DOUBLE }; static ir_tarval *fpa_imm[FPA_IMM_MAX + 1][fpa_max]; @@ -1142,8 +1133,6 @@ static int is_fpa_immediate(tarval *tv) case 64: i = FPA_IMM_DOUBLE; break; - default: - i = FPA_IMM_EXTENDED; } if (tarval_is_negative(tv)) { @@ -1171,7 +1160,6 @@ static ir_node *gen_Const(ir_node *node) node = new_bd_arm_fConst(dbg, block, tv); return node; } else if (USE_VFP(isa)) { - assert(mode != mode_E && "IEEE Extended FP not supported"); panic("VFP not supported yet"); } else { panic("Softfloat not supported yet"); @@ -2142,15 +2130,6 @@ static void arm_init_fpa_immediate(void) fpa_imm[FPA_IMM_DOUBLE][fpa_five] = new_tarval_from_str("5", 1, mode_D); fpa_imm[FPA_IMM_DOUBLE][fpa_ten] = new_tarval_from_str("10", 2, mode_D); fpa_imm[FPA_IMM_DOUBLE][fpa_half] = new_tarval_from_str("0.5", 3, mode_D); - - fpa_imm[FPA_IMM_EXTENDED][fpa_null] = get_mode_null(mode_E); - fpa_imm[FPA_IMM_EXTENDED][fpa_one] = get_mode_one(mode_E); - fpa_imm[FPA_IMM_EXTENDED][fpa_two] = new_tarval_from_str("2", 1, mode_E); - fpa_imm[FPA_IMM_EXTENDED][fpa_three] = new_tarval_from_str("3", 1, mode_E); - fpa_imm[FPA_IMM_EXTENDED][fpa_four] = new_tarval_from_str("4", 1, mode_E); - fpa_imm[FPA_IMM_EXTENDED][fpa_five] = new_tarval_from_str("5", 1, mode_E); - fpa_imm[FPA_IMM_EXTENDED][fpa_ten] = new_tarval_from_str("10", 2, mode_E); - fpa_imm[FPA_IMM_EXTENDED][fpa_half] = new_tarval_from_str("0.5", 3, mode_E); } /** @@ -2164,7 +2143,7 @@ void arm_transform_graph(ir_graph *irg) ir_type *frame_type; mode_gp = mode_Iu; - mode_fp = mode_E; + mode_fp = mode_F; if (! imm_initialized) { arm_init_fpa_immediate(); diff --git a/ir/be/begnuas.c b/ir/be/begnuas.c index b89f43b74..0946e506f 100644 --- a/ir/be/begnuas.c +++ b/ir/be/begnuas.c @@ -577,7 +577,7 @@ void be_gas_emit_function_epilog(const ir_entity *entity) * @param tv the tarval * @param bytes the width of the tarvals value in bytes */ -static void emit_arith_tarval(ir_tarval *tv, int bytes) +static void emit_arith_tarval(ir_tarval *tv, unsigned bytes) { switch (bytes) { case 1: @@ -585,53 +585,22 @@ static void emit_arith_tarval(ir_tarval *tv, int bytes) return; case 2: - be_emit_irprintf("0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0)); + be_emit_irprintf("0x%02x%02x", + get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0)); return; case 4: be_emit_irprintf("0x%02x%02x%02x%02x", - get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0)); + get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), + get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0)); return; case 8: be_emit_irprintf("0x%02x%02x%02x%02x%02x%02x%02x%02x", - get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4), - get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0)); - return; - - case 12: - /* Beware: Mixed endian output! One little endian number emitted as - * three longs. Each long initializer is written in big endian. */ - be_emit_irprintf( - "\t.long\t0x%02x%02x%02x%02x\n" - "\t.long\t0x%02x%02x%02x%02x\n" - "\t.long\t0x%02x%02x%02x%02x", - get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), - get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0), - get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), - get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4), - get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10), - get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8) - ); - return; - - case 16: - /* Beware: Mixed endian output! One little endian number emitted as - * three longs. Each long initializer is written in big endian. */ - be_emit_irprintf( - "\t.long\t0x%02x%02x%02x%02x\n" - "\t.long\t0x%02x%02x%02x%02x\n" - "\t.long\t0x%02x%02x%02x%02x\n" - "\t.long\t0x%02x%02x%02x%02x", - get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), - get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0), - get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), - get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4), - get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10), - get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8), - get_tarval_sub_bits(tv, 15), get_tarval_sub_bits(tv, 14), - get_tarval_sub_bits(tv, 13), get_tarval_sub_bits(tv, 12) - ); + get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), + get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4), + get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), + get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0)); return; } @@ -701,7 +670,7 @@ static ir_tarval *get_atomic_init_tv(ir_node *init) * @param env the gas output environment * @param init a node representing the atomic value (on the const code irg) */ -static void do_emit_atomic_init(be_gas_decl_env_t *env, ir_node *init) +static void emit_init_expression(be_gas_decl_env_t *env, ir_node *init) { ir_mode *mode = get_irn_mode(init); int bytes = get_mode_size_bytes(mode); @@ -712,11 +681,11 @@ static void do_emit_atomic_init(be_gas_decl_env_t *env, ir_node *init) switch (get_irn_opcode(init)) { case iro_Cast: - do_emit_atomic_init(env, get_Cast_op(init)); + emit_init_expression(env, get_Cast_op(init)); return; case iro_Conv: - do_emit_atomic_init(env, get_Conv_op(init)); + emit_init_expression(env, get_Conv_op(init)); return; case iro_Const: @@ -760,27 +729,27 @@ static void do_emit_atomic_init(be_gas_decl_env_t *env, ir_node *init) if (!mode_is_int(mode) && !mode_is_reference(mode)) { panic("Constant must be int or pointer for '+' to work"); } - do_emit_atomic_init(env, get_Add_left(init)); + emit_init_expression(env, get_Add_left(init)); be_emit_cstring(" + "); - do_emit_atomic_init(env, get_Add_right(init)); + emit_init_expression(env, get_Add_right(init)); return; case iro_Sub: if (!mode_is_int(mode) && !mode_is_reference(mode)) { panic("Constant must be int or pointer for '-' to work"); } - do_emit_atomic_init(env, get_Sub_left(init)); + emit_init_expression(env, get_Sub_left(init)); be_emit_cstring(" - "); - do_emit_atomic_init(env, get_Sub_right(init)); + emit_init_expression(env, get_Sub_right(init)); return; case iro_Mul: if (!mode_is_int(mode) && !mode_is_reference(mode)) { panic("Constant must be int or pointer for '*' to work"); } - do_emit_atomic_init(env, get_Mul_left(init)); + emit_init_expression(env, get_Mul_left(init)); be_emit_cstring(" * "); - do_emit_atomic_init(env, get_Mul_right(init)); + emit_init_expression(env, get_Mul_right(init)); return; case iro_Unknown: @@ -800,50 +769,16 @@ static void do_emit_atomic_init(be_gas_decl_env_t *env, ir_node *init) static void emit_size_type(size_t size) { switch (size) { - case 1: - be_emit_cstring("\t.byte\t"); - break; - - case 2: - be_emit_cstring("\t.short\t"); - break; - - case 4: - be_emit_cstring("\t.long\t"); - break; - - case 8: - be_emit_cstring("\t.quad\t"); - break; - - case 10: - case 12: - case 16: /* Note: .octa does not work on mac */ - /* handled in arith */ - break; + case 1: be_emit_cstring("\t.byte\t"); break; + case 2: be_emit_cstring("\t.short\t"); break; + case 4: be_emit_cstring("\t.long\t"); break; + case 8: be_emit_cstring("\t.quad\t"); break; default: panic("Try to dump a type with %u bytes", (unsigned)size); } } -/** - * Emit an atomic value. - * - * @param env the gas output environment - * @param init a node representing the atomic value (on the const code irg) - */ -static void emit_atomic_init(be_gas_decl_env_t *env, ir_node *init) -{ - ir_mode *mode = get_irn_mode(init); - int bytes = get_mode_size_bytes(mode); - - emit_size_type(bytes); - do_emit_atomic_init(env, init); - be_emit_char('\n'); - be_emit_write_line(); -} - /** * Dump a string constant. * No checks are made!! @@ -948,6 +883,7 @@ typedef enum normal_or_bitfield_kind { typedef struct { normal_or_bitfield_kind kind; + ir_type *type; union { ir_node *value; ir_tarval *tarval; @@ -1099,10 +1035,12 @@ static void emit_ir_initializer(normal_or_bitfield *vals, assert(vals->kind != BITFIELD); vals->kind = TARVAL; + vals->type = type; vals->v.tarval = get_initializer_tarval_value(initializer); assert(get_type_mode(type) == get_tarval_mode(vals->v.tarval)); for (i = 1; i < get_type_size_bytes(type); ++i) { vals[i].kind = NORMAL; + vals[i].type = NULL; vals[i].v.value = NULL; } return; @@ -1112,9 +1050,11 @@ static void emit_ir_initializer(normal_or_bitfield *vals, assert(vals->kind != BITFIELD); vals->kind = NORMAL; + vals->type = type; vals->v.value = get_initializer_const_value(initializer); for (i = 1; i < get_type_size_bytes(type); ++i) { vals[i].kind = NORMAL; + vals[i].type = NULL; vals[i].v.value = NULL; } return; @@ -1179,6 +1119,97 @@ static void emit_ir_initializer(normal_or_bitfield *vals, panic("invalid ir_initializer kind found"); } +static void emit_tarval_data(ir_type *type, ir_tarval *tv) +{ + size_t size = get_type_size_bytes(type); + if (size == 12) { + /* this should be an x86 extended float */ + assert(be_get_backend_param()->byte_order_big_endian == 0); + + /* Beware: Mixed endian output! One little endian number emitted as + * three longs. Each long initializer is written in big endian. */ + be_emit_irprintf( + "\t.long\t0x%02x%02x%02x%02x\n" + "\t.long\t0x%02x%02x%02x%02x\n" + "\t.long\t0x%02x%02x%02x%02x\n", + get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), + get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0), + get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), + get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4), + get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10), + get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8) + ); + be_emit_write_line(); + } else if (size == 16) { + if (be_get_backend_param()->byte_order_big_endian) { + be_emit_irprintf( + "\t.long\t0x%02x%02x%02x%02x\n" + "\t.long\t0x%02x%02x%02x%02x\n" + "\t.long\t0x%02x%02x%02x%02x\n" + "\t.long\t0x%02x%02x%02x%02x\n", + get_tarval_sub_bits(tv, 15), get_tarval_sub_bits(tv, 14), + get_tarval_sub_bits(tv, 13), get_tarval_sub_bits(tv, 12), + get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10), + get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8), + get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), + get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4), + get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), + get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0) + ); + } else { + /* Beware: Mixed endian output! One little endian number emitted as + * three longs. Each long initializer is written in big endian. */ + be_emit_irprintf( + "\t.long\t0x%02x%02x%02x%02x\n" + "\t.long\t0x%02x%02x%02x%02x\n" + "\t.long\t0x%02x%02x%02x%02x\n" + "\t.long\t0x%02x%02x%02x%02x\n", + get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), + get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0), + get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), + get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4), + get_tarval_sub_bits(tv, 11), get_tarval_sub_bits(tv, 10), + get_tarval_sub_bits(tv, 9), get_tarval_sub_bits(tv, 8), + get_tarval_sub_bits(tv, 15), get_tarval_sub_bits(tv, 14), + get_tarval_sub_bits(tv, 13), get_tarval_sub_bits(tv, 12) + ); + } + be_emit_write_line(); + return; + } else { + /* default case */ + emit_size_type(size); + emit_arith_tarval(tv, size); + be_emit_char('\n'); + be_emit_write_line(); + } +} + +/** + * Emit an atomic value. + * + * @param env the gas output environment + * @param init a node representing the atomic value (on the const code irg) + */ +static void emit_node_data(be_gas_decl_env_t *env, ir_node *init, ir_type *type) +{ + size_t size = get_type_size_bytes(type); + if (size == 12 || size == 16) { + ir_tarval *tv; + if (!is_Const(init)) { + panic("12/16byte initializers only support Const nodes yet"); + } + tv = get_Const_tarval(init); + emit_tarval_data(type, tv); + return; + } + + emit_size_type(size); + emit_init_expression(env, init); + be_emit_char('\n'); + be_emit_write_line(); +} + static void emit_initializer(be_gas_decl_env_t *env, const ir_entity *entity) { const ir_initializer_t *initializer = entity->initializer; @@ -1214,37 +1245,31 @@ static void emit_initializer(be_gas_decl_env_t *env, const ir_entity *entity) /* now write values sorted */ for (k = 0; k < size; ) { int space = 0; - int elem_size = 1; normal_or_bitfield_kind kind = vals[k].kind; + int elem_size; switch (kind) { case NORMAL: if (vals[k].v.value != NULL) { - emit_atomic_init(env, vals[k].v.value); - elem_size = get_mode_size_bytes(get_irn_mode(vals[k].v.value)); + emit_node_data(env, vals[k].v.value, vals[k].type); + elem_size = get_type_size_bytes(vals[k].type); } else { elem_size = 0; } break; - case TARVAL: { - ir_tarval *tv = vals[k].v.tarval; - size_t size = get_mode_size_bytes(get_tarval_mode(tv)); - - assert(tv != NULL); - - elem_size = size; - emit_size_type(size); - emit_arith_tarval(tv, size); - be_emit_char('\n'); - be_emit_write_line(); + case TARVAL: + emit_tarval_data(vals[k].type, vals[k].v.tarval); + elem_size = get_type_size_bytes(vals[k].type); break; - } case STRING: elem_size = emit_string_initializer(vals[k].v.string); break; case BITFIELD: be_emit_irprintf("\t.byte\t%d\n", vals[k].v.bf_val); be_emit_write_line(); + elem_size = 1; break; + default: + panic("internal compiler error (invalid normal_or_bitfield_kind"); } k += elem_size; @@ -1346,7 +1371,7 @@ static void emit_compound_graph_init(be_gas_decl_env_t *env, int space = 0, skip = 0; if (vals[k].kind == NORMAL) { if (vals[k].v.value != NULL) { - emit_atomic_init(env, vals[k].v.value); + emit_node_data(env, vals[k].v.value, vals[k].type); skip = get_mode_size_bytes(get_irn_mode(vals[k].v.value)) - 1; } else { space = 1; diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index 2be449e0b..f6b4eeecc 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -99,7 +99,9 @@ transformer_t be_transformer = TRANSFORMER_DEFAULT; #endif -ir_mode *ia32_mode_fpcw = NULL; +ir_mode *ia32_mode_fpcw; +ir_mode *ia32_mode_E; +ir_type *ia32_type_E; /** The current omit-fp state */ static ir_type *omit_fp_between_type = NULL; @@ -1466,7 +1468,6 @@ static ia32_isa_t ia32_isa_template = { 5, /* costs for a reload instruction */ false, /* no custom abi handling */ }, - NULL, /* types */ NULL, /* tv_ents */ NULL, /* abstract machine */ IA32_FPU_ARCH_X87, /* FPU architecture */ @@ -1531,14 +1532,13 @@ static arch_env_t *ia32_init(FILE *file_handle) *isa = ia32_isa_template; if (ia32_mode_fpcw == NULL) { - ia32_mode_fpcw = new_ir_mode("Fpcw", irms_int_number, 16, 0, irma_none, 0); + ia32_mode_fpcw = new_int_mode("Fpcw", irma_twos_complement, 16, 0, 0); } ia32_register_init(); ia32_create_opcodes(&ia32_irn_ops); be_emit_init(file_handle); - isa->types = pmap_create(); isa->tv_ent = pmap_create(); isa->cpu = ia32_init_machine_description(); @@ -1561,7 +1561,6 @@ static void ia32_done(void *self) be_gas_emit_decls(isa->base.main_env); pmap_destroy(isa->tv_ent); - pmap_destroy(isa->types); be_emit_exit(); @@ -2125,13 +2124,21 @@ static const backend_params *ia32_get_libfirm_params(void) ia32_create_trampoline_fkt, 4 /* alignment of stack parameter */ }; + + if (ia32_mode_E == NULL) { + /* note mantissa is 64bit but with explicitely encoded 1 so the really + * usable part as counted by firm is only 63 bits */ + ia32_mode_E = new_float_mode("E", irma_x86_extended_float, 15, 63); + ia32_type_E = new_type_primitive(ia32_mode_E); + set_type_size_bytes(ia32_type_E, 12); + set_type_alignment_bytes(ia32_type_E, 16); + } + ir_mode *mode_long_long - = new_ir_mode("long long", irms_int_number, 64, 1, irma_twos_complement, - 64); + = new_int_mode("long long", irma_twos_complement, 64, 1, 64); ir_type *type_long_long = new_type_primitive(mode_long_long); ir_mode *mode_unsigned_long_long - = new_ir_mode("unsigned long long", irms_int_number, 64, 0, - irma_twos_complement, 64); + = new_int_mode("unsigned long long", irma_twos_complement, 64, 0, 64); ir_type *type_unsigned_long_long = new_type_primitive(mode_unsigned_long_long); @@ -2148,13 +2155,8 @@ static const backend_params *ia32_get_libfirm_params(void) 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); - ir_type *type = new_type_primitive(mode); - set_type_size_bytes(type, 12); - set_type_alignment_bytes(type, 4); - p.type_long_double = type; + p.mode_float_arithmetic = ia32_mode_E; + p.type_long_double = ia32_type_E; } return &p; } diff --git a/ir/be/ia32/bearch_ia32_t.h b/ir/be/ia32/bearch_ia32_t.h index 0e1a968f1..8763064dc 100644 --- a/ir/be/ia32/bearch_ia32_t.h +++ b/ir/be/ia32/bearch_ia32_t.h @@ -64,11 +64,10 @@ typedef struct ia32_irg_data_t { * IA32 ISA object */ struct ia32_isa_t { - arch_env_t base; /**< must be derived from arch_env_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 */ + arch_env_t base; /**< must be derived from arch_env_t */ + pmap *tv_ent; /**< A map of entities that store const tarvals */ + const be_machine_t *cpu; /**< the abstract machine */ + int fpu_arch; /**< FPU architecture */ }; /** @@ -101,6 +100,9 @@ extern transformer_t be_transformer; /** The mode for the floating point control word. */ extern ir_mode *ia32_mode_fpcw; +/** extended floatingpoint mode */ +extern ir_mode *ia32_mode_E; +extern ir_type *ia32_type_E; static inline ia32_irg_data_t *ia32_get_irg_data(const ir_graph *irg) { diff --git a/ir/be/ia32/ia32_common_transform.c b/ir/be/ia32/ia32_common_transform.c index e374eead1..758c09c46 100644 --- a/ir/be/ia32/ia32_common_transform.c +++ b/ir/be/ia32/ia32_common_transform.c @@ -64,30 +64,19 @@ static int check_immediate_constraint(long val, char immediate_constraint_type) } } -/** - * Get a primitive type for a mode with alignment 16. - */ -static ir_type *ia32_get_prim_type(pmap *types, ir_mode *mode) +ir_type *ia32_get_prim_type(const ir_mode *mode) { - ir_type *res = (ir_type*)pmap_get(types, mode); - if (res != NULL) - return res; - - res = new_type_primitive(mode); - if (get_mode_size_bits(mode) >= 80) { - set_type_alignment_bytes(res, 16); + if (mode == ia32_mode_E) { + return ia32_type_E; + } else { + return get_type_for_mode(mode); } - pmap_insert(types, mode, res); - return res; } -ir_entity *ia32_create_float_const_entity(ir_node *cnst) +ir_entity *ia32_create_float_const_entity(ia32_isa_t *isa, ir_tarval *tv, + ident *name) { - ir_graph *irg = get_irn_irg(cnst); - const arch_env_t *arch_env = be_get_irg_arch_env(irg); - ia32_isa_t *isa = (ia32_isa_t*) arch_env; - ir_tarval *tv = get_Const_tarval(cnst); - ir_entity *res = (ir_entity*)pmap_get(isa->tv_ent, tv); + ir_entity *res = (ir_entity*)pmap_get(isa->tv_ent, tv); ir_initializer_t *initializer; ir_mode *mode; ir_type *tp; @@ -112,8 +101,11 @@ ir_entity *ia32_create_float_const_entity(ir_node *cnst) } } - tp = ia32_get_prim_type(isa->types, mode); - res = new_entity(get_glob_type(), id_unique("C%u"), tp); + if (name == NULL) + name = id_unique("C%u"); + + tp = ia32_get_prim_type(mode); + res = new_entity(get_glob_type(), name, tp); set_entity_ld_ident(res, get_entity_ident(res)); set_entity_visibility(res, ir_visibility_private); add_entity_linkage(res, IR_LINKAGE_CONSTANT); diff --git a/ir/be/ia32/ia32_common_transform.h b/ir/be/ia32/ia32_common_transform.h index 3faf53f3b..9b03bb69b 100644 --- a/ir/be/ia32/ia32_common_transform.h +++ b/ir/be/ia32/ia32_common_transform.h @@ -46,13 +46,14 @@ struct constraint_t { extern ir_heights_t *ia32_heights; extern int ia32_no_pic_adjust; +ir_type *ia32_get_prim_type(const ir_mode *mode); + /** * Get an atomic entity that is initialized with a tarval forming * a given constant. - * - * @param cnst the node representing the constant */ -ir_entity *ia32_create_float_const_entity(ir_node *cnst); +ir_entity *ia32_create_float_const_entity(ia32_isa_t *isa, ir_tarval *tv, + ident *name); /** * Creates an immediate. diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index b362e0a90..31a60d5a6 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -1364,11 +1364,7 @@ static void Copy_emitter(const ir_node *node, const ir_node *op) if (arch_register_get_class(in) == &ia32_reg_classes[CLASS_ia32_vfp]) return; - if (get_irn_mode(node) == mode_E) { - ia32_emitf(node, "\tmovsd %R, %R\n", in, out); - } else { - ia32_emitf(node, "\tmovl %R, %R\n", in, out); - } + ia32_emitf(node, "\tmovl %R, %R\n", in, out); } static void emit_be_Copy(const ir_node *node) @@ -2345,13 +2341,9 @@ static void bemit_copy(const ir_node *copy) if (arch_register_get_class(in) == &ia32_reg_classes[CLASS_ia32_vfp]) return; - if (get_irn_mode(copy) == mode_E) { - panic("NIY"); - } else { - assert(arch_register_get_class(in) == &ia32_reg_classes[CLASS_ia32_gp]); - bemit8(0x8B); - bemit_modrr(in, out); - } + assert(arch_register_get_class(in) == &ia32_reg_classes[CLASS_ia32_gp]); + bemit8(0x8B); + bemit_modrr(in, out); } static void bemit_perm(const ir_node *node) diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 5aad7f004..a9394487a 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -4,6 +4,13 @@ $arch = "ia32"; +$mode_xmm = "mode_D"; +$mode_mmx = "mode_D"; +$mode_fp87 = "ia32_mode_E"; +$mode_gp = "mode_Iu"; +$mode_flags = "mode_Iu"; +$mode_fpcw = "ia32_mode_fpcw"; + # register types: $normal = 0; # no special type $ignore = 1; # ignore (do not assign this register) @@ -22,7 +29,7 @@ $state = 8; # register represents a state { name => "ebp" }, { name => "esp", type => $ignore }, { name => "gp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes - { mode => "mode_Iu" } + { mode => $mode_gp } ], mmx => [ { name => "mm0", type => $ignore }, @@ -33,7 +40,7 @@ $state = 8; # register represents a state { name => "mm5", type => $ignore }, { name => "mm6", type => $ignore }, { name => "mm7", type => $ignore }, - { mode => "mode_E", flags => "manual_ra" } + { mode => $mode_mmx, flags => "manual_ra" } ], xmm => [ { name => "xmm0" }, @@ -45,7 +52,7 @@ $state = 8; # register represents a state { name => "xmm6" }, { name => "xmm7" }, { name => "xmm_NOREG", type => $ignore | $virtual }, # we need a dummy register for NoReg nodes - { mode => "mode_E" } + { mode => $mode_xmm } ], vfp => [ { name => "vf0" }, @@ -57,7 +64,7 @@ $state = 8; # register represents a state { name => "vf6" }, { name => "vf7" }, { name => "vfp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes - { mode => "mode_E" } + { mode => $mode_fp87 } ], st => [ { name => "st0", realname => "st", type => $ignore }, @@ -68,11 +75,11 @@ $state = 8; # register represents a state { name => "st5", realname => "st(5)", type => $ignore }, { name => "st6", realname => "st(6)", type => $ignore }, { name => "st7", realname => "st(7)", type => $ignore }, - { mode => "mode_E", flags => "manual_ra" } + { mode => $mode_fp87, flags => "manual_ra" } ], fp_cw => [ # the floating point control word { name => "fpcw", type => $ignore | $state }, - { mode => "ia32_mode_fpcw", flags => "manual_ra|state" } + { mode => $mode_fpcw, flags => "manual_ra|state" } ], flags => [ { name => "eflags", type => 0 }, @@ -208,10 +215,6 @@ $custom_init_attr_func = \&ia32_custom_init_attr; %operands = ( ); -$mode_xmm = "mode_E"; -$mode_gp = "mode_Iu"; -$mode_flags = "mode_Iu"; -$mode_fpcw = "ia32_mode_fpcw"; $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ]; $status_flags_wo_cf = [ "PF", "AF", "ZF", "SF", "OF" ]; $fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM", @@ -1119,7 +1122,7 @@ NoReg_VFP => { reg_req => { out => [ "vfp_NOREG:I" ] }, units => [], emit => "", - mode => "mode_E", + mode => $mode_fp87, latency => 0, attr_type => "ia32_x87_attr_t", }, @@ -1132,7 +1135,7 @@ NoReg_XMM => { units => [], emit => "", latency => 0, - mode => "mode_E" + mode => $mode_xmm, }, ChangeCW => { @@ -2042,7 +2045,7 @@ vfadd => { am => "source,binary", latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2056,7 +2059,7 @@ vfmul => { am => "source,binary", latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2070,7 +2073,7 @@ vfsub => { am => "source,binary", latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2091,7 +2094,7 @@ vfprem => { ins => [ "left", "right", "fpcw" ], latency => 20, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2101,7 +2104,7 @@ vfabs => { ins => [ "value" ], latency => 2, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2111,7 +2114,7 @@ vfchs => { ins => [ "value" ], latency => 2, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2187,7 +2190,7 @@ vfldz => { outs => [ "res" ], latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2197,7 +2200,7 @@ vfld1 => { outs => [ "res" ], latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2207,7 +2210,7 @@ vfldpi => { outs => [ "res" ], latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2217,7 +2220,7 @@ vfldln2 => { outs => [ "res" ], latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2227,7 +2230,7 @@ vfldlg2 => { outs => [ "res" ], latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2237,7 +2240,7 @@ vfldl2t => { outs => [ "res" ], latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, @@ -2247,7 +2250,7 @@ vfldl2e => { outs => [ "res" ], latency => 4, units => [ "VFP" ], - mode => "mode_E", + mode => $mode_fp87, attr_type => "ia32_x87_attr_t", }, diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 7e3bfd6de..8319bbeb1 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -71,20 +71,6 @@ /* define this to construct SSE constants instead of load them */ #undef CONSTRUCT_SSE_CONST - -#define SFP_SIGN "0x80000000" -#define DFP_SIGN "0x8000000000000000" -#define SFP_ABS "0x7FFFFFFF" -#define DFP_ABS "0x7FFFFFFFFFFFFFFF" -#define DFP_INTMAX "9223372036854775807" -#define ULL_BIAS "18446744073709551616" - -#define ENT_SFP_SIGN "C_ia32_sfp_sign" -#define ENT_DFP_SIGN "C_ia32_dfp_sign" -#define ENT_SFP_ABS "C_ia32_sfp_abs" -#define ENT_DFP_ABS "C_ia32_dfp_abs" -#define ENT_ULL_BIAS "C_ia32_ull_bias" - #define mode_vfp (ia32_reg_classes[CLASS_ia32_vfp].mode) #define mode_xmm (ia32_reg_classes[CLASS_ia32_xmm].mode) @@ -215,20 +201,23 @@ static ir_node *get_symconst_base(void) */ static ir_node *gen_Const(ir_node *node) { - ir_node *old_block = get_nodes_block(node); - ir_node *block = be_transform_node(old_block); - dbg_info *dbgi = get_irn_dbg_info(node); - ir_mode *mode = get_irn_mode(node); + ir_node *old_block = get_nodes_block(node); + ir_node *block = be_transform_node(old_block); + dbg_info *dbgi = get_irn_dbg_info(node); + ir_mode *mode = get_irn_mode(node); + ir_tarval *tv = get_Const_tarval(node); assert(is_Const(node)); if (mode_is_float(mode)) { - ir_node *res = NULL; - ir_node *load; - ir_entity *floatent; + ir_graph *irg = get_irn_irg(node); + const arch_env_t *arch_env = be_get_irg_arch_env(irg); + ia32_isa_t *isa = (ia32_isa_t*) arch_env; + ir_node *res = NULL; + ir_node *load; + ir_entity *floatent; if (ia32_cg_config.use_sse2) { - ir_tarval *tv = get_Const_tarval(node); if (tarval_is_null(tv)) { load = new_bd_ia32_xZero(dbgi, block); set_ia32_ls_mode(load, mode); @@ -285,7 +274,7 @@ static ir_node *gen_Const(ir_node *node) } } #endif /* CONSTRUCT_SSE_CONST */ - floatent = ia32_create_float_const_entity(node); + floatent = ia32_create_float_const_entity(isa, tv, NULL); base = get_symconst_base(); load = new_bd_ia32_xLoad(dbgi, block, base, noreg_GP, nomem, @@ -296,11 +285,11 @@ static ir_node *gen_Const(ir_node *node) res = new_r_Proj(load, mode_xmm, pn_ia32_xLoad_res); } } else { - if (is_Const_null(node)) { + if (tarval_is_null(tv)) { load = new_bd_ia32_vfldz(dbgi, block); res = load; set_ia32_ls_mode(load, mode); - } else if (is_Const_one(node)) { + } else if (tarval_is_one(tv)) { load = new_bd_ia32_vfld1(dbgi, block); res = load; set_ia32_ls_mode(load, mode); @@ -308,7 +297,7 @@ static ir_node *gen_Const(ir_node *node) ir_mode *ls_mode; ir_node *base; - floatent = ia32_create_float_const_entity(node); + floatent = ia32_create_float_const_entity(isa, tv, NULL); /* create_float_const_ent is smart and sometimes creates smaller entities */ ls_mode = get_type_mode(get_entity_type(floatent)); @@ -327,9 +316,8 @@ end: SET_IA32_ORIG_NODE(load, node); return res; } else { /* non-float mode */ - ir_node *cnst; - ir_tarval *tv = get_Const_tarval(node); - long val; + ir_node *cnst; + long val; tv = tarval_convert_to(tv, mode_Iu); @@ -359,9 +347,9 @@ static ir_node *gen_SymConst(ir_node *node) if (mode_is_float(mode)) { if (ia32_cg_config.use_sse2) - cnst = new_bd_ia32_xLoad(dbgi, block, noreg_GP, noreg_GP, nomem, mode_E); + cnst = new_bd_ia32_xLoad(dbgi, block, noreg_GP, noreg_GP, nomem, mode_D); else - cnst = new_bd_ia32_vfld(dbgi, block, noreg_GP, noreg_GP, nomem, mode_E); + cnst = new_bd_ia32_vfld(dbgi, block, noreg_GP, noreg_GP, nomem, ia32_mode_E); set_ia32_am_sc(cnst, get_SymConst_entity(node)); set_ia32_use_frame(cnst); } else { @@ -386,64 +374,18 @@ static ir_node *gen_SymConst(ir_node *node) return cnst; } -/** - * Create a float type for the given mode and cache it. - * - * @param mode the mode for the float type (might be integer mode for SSE2 types) - * @param align alignment - */ -static ir_type *ia32_create_float_type(ir_mode *mode, unsigned align) +static ir_type *make_array_type(ir_type *tp) { - ir_type *tp; - - assert(align <= 16); - - if (mode == mode_Iu) { - static ir_type *int_Iu[16] = {NULL, }; - - if (int_Iu[align] == NULL) { - int_Iu[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return int_Iu[align]; - } else if (mode == mode_Lu) { - static ir_type *int_Lu[16] = {NULL, }; - - if (int_Lu[align] == NULL) { - int_Lu[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return int_Lu[align]; - } else if (mode == mode_F) { - static ir_type *float_F[16] = {NULL, }; - - if (float_F[align] == NULL) { - float_F[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return float_F[align]; - } else if (mode == mode_D) { - static ir_type *float_D[16] = {NULL, }; - - if (float_D[align] == NULL) { - float_D[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return float_D[align]; - } else { - static ir_type *float_E[16] = {NULL, }; - - if (float_E[align] == NULL) { - float_E[align] = tp = new_type_primitive(mode); - /* set the specified alignment */ - set_type_alignment_bytes(tp, align); - } - return float_E[align]; - } + unsigned alignment = get_type_alignment_bytes(tp); + unsigned size = get_type_size_bytes(tp); + ir_type *res = new_type_array(1, tp); + set_type_alignment_bytes(res, alignment); + set_array_bounds_int(res, 0, 0, 2); + if (alignment > size) + size = alignment; + set_type_size_bytes(res, 2 * size); + set_type_state(res, layout_fixed); + return res; } /** @@ -454,33 +396,27 @@ static ir_type *ia32_create_float_type(ir_mode *mode, unsigned align) static ir_type *ia32_create_float_array(ir_type *tp) { ir_mode *mode = get_type_mode(tp); - unsigned align = get_type_alignment_bytes(tp); ir_type *arr; - assert(align <= 16); - if (mode == mode_F) { - static ir_type *float_F[16] = {NULL, }; + static ir_type *float_F; - if (float_F[align] != NULL) - return float_F[align]; - arr = float_F[align] = new_type_array(1, tp); + arr = float_F; + if (arr == NULL) + arr = float_F = make_array_type(tp); } else if (mode == mode_D) { - static ir_type *float_D[16] = {NULL, }; + static ir_type *float_D; - if (float_D[align] != NULL) - return float_D[align]; - arr = float_D[align] = new_type_array(1, tp); + arr = float_D; + if (arr == NULL) + arr = float_D = make_array_type(tp); } else { - static ir_type *float_E[16] = {NULL, }; + static ir_type *float_E; - if (float_E[align] != NULL) - return float_E[align]; - arr = float_E[align] = new_type_array(1, tp); + arr = float_E; + if (arr == NULL) + arr = float_E = make_array_type(tp); } - set_type_alignment_bytes(arr, align); - set_type_size_bytes(arr, 2 * get_type_size_bytes(tp)); - set_type_state(arr, layout_fixed); return arr; } @@ -488,58 +424,56 @@ static ir_type *ia32_create_float_array(ir_type *tp) ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) { static const struct { - const char *ent_name; + const char *name; const char *cnst_str; - char mode; - unsigned char align; + char mode; } names [ia32_known_const_max] = { - { ENT_SFP_SIGN, SFP_SIGN, 0, 16 }, /* ia32_SSIGN */ - { ENT_DFP_SIGN, DFP_SIGN, 1, 16 }, /* ia32_DSIGN */ - { ENT_SFP_ABS, SFP_ABS, 0, 16 }, /* ia32_SABS */ - { ENT_DFP_ABS, DFP_ABS, 1, 16 }, /* ia32_DABS */ - { ENT_ULL_BIAS, ULL_BIAS, 2, 4 } /* ia32_ULLBIAS */ + { "C_sfp_sign", "0x80000000", 0 }, + { "C_dfp_sign", "0x8000000000000000", 1 }, + { "C_sfp_abs", "0x7FFFFFFF", 0 }, + { "C_dfp_abs", "0x7FFFFFFFFFFFFFFF", 1 }, + { "C_ull_bias", "0x10000000000000000", 2 } }; static ir_entity *ent_cache[ia32_known_const_max]; - const char *ent_name, *cnst_str; - ir_type *tp; - ir_entity *ent; - ir_tarval *tv; - ir_mode *mode; - - ent_name = names[kct].ent_name; - if (! ent_cache[kct]) { - cnst_str = names[kct].cnst_str; + ir_entity *ent = ent_cache[kct]; + if (ent == NULL) { + ir_graph *irg = current_ir_graph; + const arch_env_t *arch_env = be_get_irg_arch_env(irg); + ia32_isa_t *isa = (ia32_isa_t*) arch_env; + const char *cnst_str = names[kct].cnst_str; + ident *name = new_id_from_str(names[kct].name); + ir_mode *mode; + ir_tarval *tv; switch (names[kct].mode) { case 0: mode = mode_Iu; break; case 1: mode = mode_Lu; break; - default: mode = mode_F; break; + case 2: mode = mode_F; break; + default: panic("internal compiler error (ia32_gen_fp_known_const)"); } - tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode); - tp = ia32_create_float_type(mode, names[kct].align); + tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode); - if (kct == ia32_ULLBIAS) - tp = ia32_create_float_array(tp); - ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp); + if (kct == ia32_ULLBIAS) { + ir_type *type = ia32_get_prim_type(mode_F); + ir_type *atype = ia32_create_float_array(type); + ir_initializer_t *initializer; - set_entity_ld_ident(ent, get_entity_ident(ent)); - add_entity_linkage(ent, IR_LINKAGE_CONSTANT); - set_entity_visibility(ent, ir_visibility_private); + ent = new_entity(get_glob_type(), name, atype); - if (kct == ia32_ULLBIAS) { - ir_initializer_t *initializer = create_initializer_compound(2); + set_entity_ld_ident(ent, name); + set_entity_visibility(ent, ir_visibility_private); + add_entity_linkage(ent, IR_LINKAGE_CONSTANT); + initializer = create_initializer_compound(2); set_initializer_compound_value(initializer, 0, create_initializer_tarval(get_mode_null(mode))); set_initializer_compound_value(initializer, 1, create_initializer_tarval(tv)); - set_entity_initializer(ent, initializer); } else { - set_entity_initializer(ent, create_initializer_tarval(tv)); + ent = ia32_create_float_const_entity(isa, tv, name); } - /* cache the entry */ ent_cache[kct] = ent; } @@ -639,7 +573,11 @@ static void build_address(ia32_address_mode_t *am, ir_node *node, /* floating point immediates */ if (is_Const(node)) { - ir_entity *entity = ia32_create_float_const_entity(node); + ir_graph *irg = get_irn_irg(node); + const arch_env_t *arch_env = be_get_irg_arch_env(irg); + ia32_isa_t *isa = (ia32_isa_t*) arch_env; + ir_tarval *tv = get_Const_tarval(node); + ir_entity *entity = ia32_create_float_const_entity(isa, tv, NULL); addr->base = get_symconst_base(); addr->index = noreg_GP; addr->mem = nomem; @@ -2681,7 +2619,7 @@ static ir_node *gen_vfist(dbg_info *dbgi, ir_node *block, ir_node *base, /* Note: fisttp ALWAYS pop the tos. We have to ensure here that the value is copied if other users exists */ ir_node *vfisttp = new_bd_ia32_vfisttp(dbgi, block, base, index, mem, val); - ir_node *value = new_r_Proj(vfisttp, mode_E, pn_ia32_vfisttp_res); + ir_node *value = new_r_Proj(vfisttp, ia32_mode_E, pn_ia32_vfisttp_res); be_new_Keep(block, 1, &value); return vfisttp; @@ -2799,8 +2737,8 @@ static ir_node *gen_general_Store(ir_node *node) */ static ir_node *gen_Store(ir_node *node) { - ir_node *val = get_Store_value(node); - ir_mode *mode = get_irn_mode(val); + ir_node *val = get_Store_value(node); + ir_mode *mode = get_irn_mode(val); if (mode_is_float(mode) && is_Const(val)) { /* We can transform every floating const store @@ -3258,7 +3196,7 @@ static ir_entity *ia32_create_const_array(ir_node *c0, ir_node *c1, ir_mode **ne } - tp = ia32_create_float_type(mode, 4); + tp = ia32_get_prim_type(mode); tp = ia32_create_float_array(tp); ent = new_entity(get_glob_type(), id_unique("C%u"), tp); @@ -3508,31 +3446,15 @@ static ir_node *gen_Mux(ir_node *node) am.addr.symconst_ent = ia32_create_const_array(mux_false, mux_true, &new_mode); - switch (get_mode_size_bytes(new_mode)) { - case 4: + if (new_mode == mode_F) { scale = 2; - break; - case 8: + } else if (new_mode == mode_D) { scale = 3; - break; - case 10: - /* use 2 * 5 */ - scale = 1; - new_node = new_bd_ia32_Lea(dbgi, new_block, new_node, new_node); - set_ia32_am_scale(new_node, 2); - break; - case 12: - /* use 4 * 3 */ - scale = 2; - new_node = new_bd_ia32_Lea(dbgi, new_block, new_node, new_node); - set_ia32_am_scale(new_node, 1); - break; - case 16: + } else if (new_mode == ia32_mode_E) { /* arg, shift 16 NOT supported */ scale = 3; new_node = new_bd_ia32_Lea(dbgi, new_block, new_node, new_node); - break; - default: + } else { panic("Unsupported constant size"); } @@ -3733,7 +3655,7 @@ static ir_node *gen_x87_strict_conv(ir_mode *tgt_mode, ir_node *node) set_ia32_op_type(load, ia32_AddrModeS); SET_IA32_ORIG_NODE(load, node); - new_node = new_r_Proj(load, mode_E, pn_ia32_vfld_res); + new_node = new_r_Proj(load, ia32_mode_E, pn_ia32_vfld_res); return new_node; } @@ -3987,7 +3909,7 @@ static ir_node *gen_Conv(ir_node *node) set_ia32_ls_mode(res, tgt_mode); } else { unsigned int_mantissa = get_mode_size_bits(src_mode) - (mode_is_signed(src_mode) ? 1 : 0); - unsigned float_mantissa = tarval_ieee754_get_mantissa_size(tgt_mode); + unsigned float_mantissa = get_mode_mantissa_size(tgt_mode); res = gen_x87_gp_to_fp(node, src_mode); /* we need a strict-Conv, if the int mode has more bits than the @@ -5674,7 +5596,7 @@ static ir_node *gen_Proj_ASM(ir_node *node) } else if (mode_is_int(mode) || mode_is_reference(mode)) { mode = mode_Iu; } else if (mode_is_float(mode)) { - mode = mode_E; + mode = ia32_mode_E; } else { panic("unexpected proj mode at ASM"); } diff --git a/ir/be/sparc/bearch_sparc.c b/ir/be/sparc/bearch_sparc.c index a4c86ef5a..aca94f0f5 100644 --- a/ir/be/sparc/bearch_sparc.c +++ b/ir/be/sparc/bearch_sparc.c @@ -479,12 +479,10 @@ static const backend_params *sparc_get_backend_params(void) }; ir_mode *mode_long_long - = new_ir_mode("long long", irms_int_number, 64, 1, irma_twos_complement, - 64); + = new_int_mode("long long", irma_twos_complement, 64, 1, 64); ir_type *type_long_long = new_type_primitive(mode_long_long); ir_mode *mode_unsigned_long_long - = new_ir_mode("unsigned long long", irms_int_number, 64, 0, - irma_twos_complement, 64); + = new_int_mode("unsigned long long", irma_twos_complement, 64, 0, 64); ir_type *type_unsigned_long_long = new_type_primitive(mode_unsigned_long_long); @@ -495,13 +493,11 @@ static const backend_params *sparc_get_backend_params(void) p.mode_float_arithmetic = NULL; p.type_long_double = NULL; } else { - ir_mode *mode_long_double - = new_ir_mode("long double", irms_float_number, 128, 1, - irma_ieee754, 0); - ir_type *type_long_double = new_type_primitive(mode_long_double); + ir_type *type_long_double = new_type_primitive(mode_Q); set_type_alignment_bytes(type_long_double, 8); - p.type_long_double = type_long_double; + set_type_size_bytes(type_long_double, 16); + p.type_long_double = type_long_double; } return &p; } diff --git a/ir/be/sparc/sparc_new_nodes.c b/ir/be/sparc/sparc_new_nodes.c index 12be7e2a7..5ae98a669 100644 --- a/ir/be/sparc/sparc_new_nodes.c +++ b/ir/be/sparc/sparc_new_nodes.c @@ -40,6 +40,7 @@ #include "xmalloc.h" #include "bearch.h" +#include "bearch_sparc_t.h" #include "sparc_nodes_attr.h" #include "sparc_new_nodes.h" diff --git a/ir/be/sparc/sparc_spec.pl b/ir/be/sparc/sparc_spec.pl index 4881f7472..61ac07c89 100644 --- a/ir/be/sparc/sparc_spec.pl +++ b/ir/be/sparc/sparc_spec.pl @@ -8,7 +8,7 @@ $mode_flags = "mode_Bu"; $mode_fpflags = "mode_Bu"; $mode_fp = "mode_F"; $mode_fp2 = "mode_D"; -$mode_fp4 = "mode_E"; # not correct, we need to register a new mode +$mode_fp4 = "mode_Q"; # available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals) %reg_classes = ( diff --git a/ir/ir/irio.c b/ir/ir/irio.c index 863f4fcf0..c2b3702c9 100644 --- a/ir/ir/irio.c +++ b/ir/ir/irio.c @@ -71,7 +71,6 @@ typedef enum typetag_t tt_initializer, tt_iro, tt_keyword, - tt_mode_sort, tt_mode_arithmetic, tt_pin_state, tt_tpo, @@ -87,7 +86,9 @@ typedef enum keyword_t kw_constirg, kw_entity, kw_irg, - kw_mode, + kw_int_mode, + kw_reference_mode, + kw_float_mode, kw_modes, kw_type, kw_typegraph, @@ -181,14 +182,6 @@ static void symtbl_init(void) INSERT(tt_tpo, "union", tpo_union); INSERT(tt_tpo, "Unknown", tpo_unknown); - INSERT(tt_mode_sort, "auxiliary", irms_auxiliary); - INSERT(tt_mode_sort, "control_flow", irms_control_flow); - INSERT(tt_mode_sort, "memory", irms_memory); - INSERT(tt_mode_sort, "internal_boolean", irms_internal_boolean); - INSERT(tt_mode_sort, "reference", irms_reference); - INSERT(tt_mode_sort, "int_number", irms_int_number); - INSERT(tt_mode_sort, "float_number", irms_float_number); - INSERT(tt_segment, "global", IR_SEGMENT_GLOBAL); INSERT(tt_segment, "thread_local", IR_SEGMENT_THREAD_LOCAL); INSERT(tt_segment, "constructors", IR_SEGMENT_CONSTRUCTORS); @@ -208,7 +201,9 @@ static void symtbl_init(void) INSERTKEYWORD(constirg); INSERTKEYWORD(entity); INSERTKEYWORD(irg); - INSERTKEYWORD(mode); + INSERTKEYWORD(int_mode); + INSERTKEYWORD(float_mode); + INSERTKEYWORD(reference_mode); INSERTKEYWORD(modes); INSERTKEYWORD(type); INSERTKEYWORD(typegraph); @@ -788,20 +783,6 @@ static void export_node(ir_node *irn, void *ctx) fputs("}\n", env->file); } -static const char *get_mode_sort_name(ir_mode_sort sort) -{ - switch (sort) { - case irms_auxiliary: return "auxiliary"; - case irms_control_flow: return "control_flow"; - case irms_memory: return "memory"; - case irms_internal_boolean: return "internal_boolean"; - case irms_reference: return "reference"; - case irms_int_number: return "int_number"; - case irms_float_number: return "float_number"; - } - panic("invalid mode sort found"); -} - static void export_modes(io_env_t *env) { size_t i, n_modes = get_irp_n_modes(); @@ -810,28 +791,33 @@ static void export_modes(io_env_t *env) for (i = 0; i < n_modes; i++) { ir_mode *mode = get_irp_mode(i); - switch (get_mode_sort(mode)) { - case irms_auxiliary: - case irms_control_flow: - case irms_memory: - case irms_internal_boolean: - /* skip "internal" modes, which may not be user defined */ - continue; - default: - break; - } - fprintf(env->file, "\tmode "); - write_string(env, get_mode_name(mode)); - fprintf(env->file, "%s %u %d %s %u ", - get_mode_sort_name(get_mode_sort(mode)), - get_mode_size_bits(mode), get_mode_sign(mode), - get_mode_arithmetic_name(get_mode_arithmetic(mode)), - get_mode_modulo_shift(mode)); - if (mode_is_reference(mode)) { + if (mode_is_int(mode)) { + fprintf(env->file, "\tint_mode "); + write_string(env, get_mode_name(mode)); + fprintf(env->file, "%s %u %d %u ", + get_mode_arithmetic_name(get_mode_arithmetic(mode)), + get_mode_size_bits(mode), get_mode_sign(mode), + get_mode_modulo_shift(mode)); + } else if (mode_is_reference(mode)) { + fprintf(env->file, "\treference_mode "); + write_string(env, get_mode_name(mode)); + fprintf(env->file, "%s %u %u ", + get_mode_arithmetic_name(get_mode_arithmetic(mode)), + get_mode_size_bits(mode), + get_mode_modulo_shift(mode)); write_mode(env, get_reference_mode_signed_eq(mode)); write_mode(env, get_reference_mode_unsigned_eq(mode)); write_int(env, (mode == mode_P ? 1 : 0)); + } else if (mode_is_float(mode)) { + fprintf(env->file, "\tfloat_mode "); + write_string(env, get_mode_name(mode)); + fprintf(env->file, "%s %u %u ", + get_mode_arithmetic_name(get_mode_arithmetic(mode)), + get_mode_exponent_size(mode), + get_mode_mantissa_size(mode)); + } else { + /* skip "internal" modes */ } fputc('\n', env->file); } @@ -1249,7 +1235,6 @@ static const char *get_typetag_name(typetag_t typetag) case tt_keyword: return "keyword"; case tt_linkage: return "linkage"; case tt_mode_arithmetic: return "mode_arithmetic"; - case tt_mode_sort: return "mode_sort"; case tt_pin_state: return "pin state"; case tt_segment: return "segment"; case tt_tpo: return "type"; @@ -1754,32 +1739,38 @@ static int parse_modes(io_env_t *env) kwkind = (keyword_t) read_enum(env, tt_keyword); switch (kwkind) { - case kw_mode: { + case kw_int_mode: { const char *name = read_string(env); - ir_mode_sort sort = (ir_mode_sort)read_enum(env, tt_mode_sort); + ir_mode_arithmetic arith = read_mode_arithmetic(env); int size = read_long(env); int sign = read_long(env); + unsigned modulo_shift = read_long(env); + new_int_mode(name, arith, size, sign, modulo_shift); + break; + } + case kw_reference_mode: { + const char *name = read_string(env); ir_mode_arithmetic arith = read_mode_arithmetic(env); + int size = read_long(env); unsigned modulo_shift = read_long(env); - int vector_elems = read_long(env); - ir_mode *mode; - - if (vector_elems != 1) { - panic("no support for import of vector modes yes"); - } - - mode = new_ir_mode(name, sort, size, sign, arith, modulo_shift); - if (mode_is_reference(mode)) { - set_reference_mode_signed_eq(mode, read_mode(env)); - set_reference_mode_unsigned_eq(mode, read_mode(env)); - int is_mode_P = read_int(env); - if (is_mode_P) { - set_modeP_data(mode); - set_modeP_code(mode); - } + ir_mode *mode = new_reference_mode(name, arith, size, modulo_shift); + set_reference_mode_signed_eq(mode, read_mode(env)); + set_reference_mode_unsigned_eq(mode, read_mode(env)); + int is_mode_P = read_int(env); + if (is_mode_P) { + set_modeP_data(mode); + set_modeP_code(mode); } break; } + case kw_float_mode: { + const char *name = read_string(env); + ir_mode_arithmetic arith = read_mode_arithmetic(env); + int exponent_size = read_long(env); + int mantissa_size = read_long(env); + new_float_mode(name, arith, exponent_size, mantissa_size); + break; + } default: skip_to(env, '\n'); diff --git a/ir/ir/irmode.c b/ir/ir/irmode.c index 3e768479b..31e27c2b3 100644 --- a/ir/ir/irmode.c +++ b/ir/ir/irmode.c @@ -27,8 +27,8 @@ #include #include - #include +#include #include "irprog_t.h" #include "irmode_t.h" @@ -55,22 +55,19 @@ const char *get_mode_arithmetic_name(ir_mode_arithmetic ari) X(irma_none); X(irma_twos_complement); X(irma_ieee754); + X(irma_x86_extended_float); default: return ""; } #undef X } -static inline int modes_are_equal(const ir_mode *m, const ir_mode *n) +static bool modes_are_equal(const ir_mode *m, const ir_mode *n) { - if (m == n) return 1; - if (m->sort == n->sort && - m->arithmetic == n->arithmetic && - m->size == n->size && - m->sign == n->sign && - m->modulo_shift == n->modulo_shift) - return 1; - - return 0; + return m->sort == n->sort && + m->arithmetic == n->arithmetic && + m->size == n->size && + m->sign == n->sign && + m->modulo_shift == n->modulo_shift; } /** @@ -119,9 +116,12 @@ static void set_mode_values(ir_mode* mode) mode->all_one = tarval_b_true; break; - case irms_auxiliary: - case irms_memory: case irms_control_flow: + case irms_block: + case irms_tuple: + case irms_any: + case irms_bad: + case irms_memory: mode->min = tarval_bad; mode->max = tarval_bad; mode->null = tarval_bad; @@ -146,9 +146,9 @@ ir_mode *mode_ANY; ir_mode *mode_BAD; /* predefined numerical modes: */ -ir_mode *mode_F; /* float */ -ir_mode *mode_D; /* double */ -ir_mode *mode_E; /* long double */ +ir_mode *mode_F; +ir_mode *mode_D; +ir_mode *mode_Q; ir_mode *mode_Bs; /* integral values, signed and unsigned */ ir_mode *mode_Bu; /* 8 bit */ @@ -172,11 +172,10 @@ ir_mode *mode_P_data; /**< machine specific pointer mode for data addresses */ * functions defined in irmode.h * * */ -/* JNI access functions */ ir_mode *get_modeT(void) { return mode_T; } ir_mode *get_modeF(void) { return mode_F; } ir_mode *get_modeD(void) { return mode_D; } -ir_mode *get_modeE(void) { return mode_E; } +ir_mode *get_modeQ(void) { return mode_Q; } ir_mode *get_modeBs(void) { return mode_Bs; } ir_mode *get_modeBu(void) { return mode_Bu; } ir_mode *get_modeHs(void) { return mode_Hs; } @@ -219,74 +218,84 @@ void set_modeP_data(ir_mode *p) mode_P = p; } -/** - * Registers a new mode. - * - * @param new_mode The new mode template. +/* + * Creates a new mode. */ -static ir_mode *register_mode(const ir_mode *new_mode) -{ - ir_mode *mode = NULL; - - assert(new_mode); - - /* copy mode struct to modes array */ - mode = (ir_mode *)obstack_copy(&modes, new_mode, sizeof(*mode)); - ARR_APP1(ir_mode*, mode_list, mode); +static ir_mode *alloc_mode(const char *name, ir_mode_sort sort, + ir_mode_arithmetic arithmetic, unsigned bit_size, + int sign, unsigned modulo_shift) +{ + ir_mode *mode_tmpl = OALLOCZ(&modes, ir_mode); + + mode_tmpl->name = new_id_from_str(name); + mode_tmpl->sort = sort; + mode_tmpl->size = bit_size; + mode_tmpl->sign = sign ? 1 : 0; + mode_tmpl->modulo_shift = modulo_shift; + mode_tmpl->arithmetic = arithmetic; + mode_tmpl->link = NULL; + mode_tmpl->tv_priv = NULL; + return mode_tmpl; +} + +static ir_mode *register_mode(ir_mode *mode) +{ + /* does any of the existing modes have the same properties? */ + ir_mode *old = find_mode(mode); + if (old != NULL) { + /* remove new mode from obstack */ + obstack_free(&modes, mode); + return old; + } mode->kind = k_ir_mode; mode->type = new_type_primitive(mode); - - /* add the new mode to the irp list of modes */ + ARR_APP1(ir_mode*, mode_list, mode); add_irp_mode(mode); - set_mode_values(mode); - - hook_new_mode(new_mode, mode); + hook_new_mode(mode); return mode; } -/* - * Creates a new mode. - */ -ir_mode *new_ir_mode(const char *name, ir_mode_sort sort, int bit_size, int sign, - ir_mode_arithmetic arithmetic, unsigned int modulo_shift) -{ - ir_mode mode_tmpl; - ir_mode *mode = NULL; - - mode_tmpl.name = new_id_from_str(name); - mode_tmpl.sort = sort; - mode_tmpl.size = bit_size; - mode_tmpl.sign = sign ? 1 : 0; - mode_tmpl.modulo_shift = (mode_tmpl.sort == irms_int_number || - mode_tmpl.sort == irms_reference) ? modulo_shift : 0; - mode_tmpl.arithmetic = arithmetic; - mode_tmpl.link = NULL; - mode_tmpl.tv_priv = NULL; - - mode = find_mode(&mode_tmpl); - if (mode) { - hook_new_mode(&mode_tmpl, mode); - return mode; - } +ir_mode *new_int_mode(const char *name, ir_mode_arithmetic arithmetic, + unsigned bit_size, int sign, unsigned modulo_shift) +{ + ir_mode *result = alloc_mode(name, irms_int_number, arithmetic, bit_size, + sign, modulo_shift); + return register_mode(result); +} - /* sanity checks */ - switch (sort) { - case irms_auxiliary: - case irms_control_flow: - case irms_memory: - case irms_internal_boolean: - panic("internal modes cannot be user defined"); +ir_mode *new_reference_mode(const char *name, ir_mode_arithmetic arithmetic, + unsigned bit_size, unsigned modulo_shift) +{ + ir_mode *result = alloc_mode(name, irms_reference, arithmetic, bit_size, + 0, modulo_shift); + return register_mode(result); +} - case irms_float_number: - case irms_int_number: - case irms_reference: - mode = register_mode(&mode_tmpl); - break; +ir_mode *new_float_mode(const char *name, ir_mode_arithmetic arithmetic, + unsigned exponent_size, unsigned mantissa_size) +{ + bool explicit_one = false; + unsigned bit_size = exponent_size + mantissa_size + 1; + ir_mode *result; + + if (arithmetic == irma_x86_extended_float) { + explicit_one = true; + bit_size++; + } else if (arithmetic != irma_ieee754) { + panic("Arithmetic %s invalid for float"); } - assert(mode != NULL); - return mode; + if (exponent_size >= 256) + panic("Exponents >= 256 bits not supported"); + if (mantissa_size >= 256) + panic("Mantissa >= 256 bits not supported"); + + result = alloc_mode(name, irms_float_number, irma_ieee754, bit_size, 1, 0); + result->float_desc.exponent_size = exponent_size; + result->float_desc.mantissa_size = mantissa_size; + result->float_desc.explicit_one = explicit_one; + return register_mode(result); } /* Functions for the direct access to all attributes of an ir_mode */ @@ -300,11 +309,6 @@ const char *get_mode_name(const ir_mode *mode) return get_id_str(mode->name); } -ir_mode_sort (get_mode_sort)(const ir_mode* mode) -{ - return get_mode_sort_(mode); -} - unsigned (get_mode_size_bits)(const ir_mode *mode) { return get_mode_size_bits_(mode); @@ -453,6 +457,16 @@ int (mode_is_dataM)(const ir_mode *mode) return mode_is_dataM_(mode); } +unsigned (get_mode_mantissa_size)(const ir_mode *mode) +{ + return get_mode_mantissa_size_(mode); +} + +unsigned (get_mode_exponent_size)(const ir_mode *mode) +{ + return get_mode_exponent_size_(mode); +} + /* Returns true if sm can be converted to lm without loss. */ int smaller_mode(const ir_mode *sm, const ir_mode *lm) { @@ -583,177 +597,43 @@ void set_reference_mode_unsigned_eq(ir_mode *ref_mode, ir_mode *int_mode) ref_mode->eq_unsigned = int_mode; } +static ir_mode *new_internal_mode(const char *name, ir_mode_sort sort) +{ + ir_mode *mode = alloc_mode(name, sort, irma_none, 0, 0, 0); + return register_mode(mode); +} + /* initialization, build the default modes */ void init_mode(void) { - ir_mode newmode; - obstack_init(&modes); mode_list = NEW_ARR_F(ir_mode*, 0); /* initialize predefined modes */ - - /* Internal Modes */ - newmode.arithmetic = irma_none; - newmode.size = 0; - newmode.sign = 0; - newmode.modulo_shift = 0; - newmode.eq_signed = NULL; - newmode.eq_unsigned = NULL; - newmode.link = NULL; - newmode.tv_priv = NULL; - - /* Control Flow Modes*/ - newmode.sort = irms_control_flow; - - /* Basic Block */ - newmode.name = new_id_from_chars("BB", 2); - mode_BB = register_mode(&newmode); - - /* eXecution */ - newmode.name = new_id_from_chars("X", 1); - mode_X = register_mode(&newmode); - - /* Memory Modes */ - newmode.sort = irms_memory; - - /* Memory */ - newmode.name = new_id_from_chars("M", 1); - mode_M = register_mode(&newmode); - - /* Auxiliary Modes */ - newmode.sort = irms_auxiliary, - - /* Tuple */ - newmode.name = new_id_from_chars("T", 1); - mode_T = register_mode(&newmode); - - /* ANY */ - newmode.name = new_id_from_chars("ANY", 3); - mode_ANY = register_mode(&newmode); - - /* BAD */ - newmode.name = new_id_from_chars("BAD", 3); - mode_BAD = register_mode(&newmode); - - /* Internal Boolean Modes */ - newmode.sort = irms_internal_boolean; - - /* boolean */ - newmode.name = new_id_from_chars("b", 1); - mode_b = register_mode(&newmode); - - /* Float Number Modes */ - newmode.sort = irms_float_number; - newmode.arithmetic = irma_ieee754; - - /* float */ - newmode.name = new_id_from_chars("F", 1); - newmode.sign = 1; - newmode.size = 32; - mode_F = register_mode(&newmode); - - /* double */ - newmode.name = new_id_from_chars("D", 1); - newmode.sign = 1; - newmode.size = 64; - mode_D = register_mode(&newmode); - - /* extended */ - newmode.name = new_id_from_chars("E", 1); - newmode.sign = 1; - /* note that the tarval module is calculating with 80 bits, but we use - * 96 bits, as that is what will be stored to memory by most hardware */ - newmode.size = 96; - mode_E = register_mode(&newmode); - - /* Integer Number Modes */ - newmode.sort = irms_int_number; - newmode.arithmetic = irma_twos_complement; - - /* signed byte */ - newmode.name = new_id_from_chars("Bs", 2); - newmode.sign = 1; - newmode.size = 8; - newmode.modulo_shift = 32; - mode_Bs = register_mode(&newmode); - - /* unsigned byte */ - newmode.name = new_id_from_chars("Bu", 2); - newmode.arithmetic = irma_twos_complement; - newmode.sign = 0; - newmode.size = 8; - newmode.modulo_shift = 32; - mode_Bu = register_mode(&newmode); - - /* signed short integer */ - newmode.name = new_id_from_chars("Hs", 2); - newmode.sign = 1; - newmode.size = 16; - newmode.modulo_shift = 32; - mode_Hs = register_mode(&newmode); - - /* unsigned short integer */ - newmode.name = new_id_from_chars("Hu", 2); - newmode.sign = 0; - newmode.size = 16; - newmode.modulo_shift = 32; - mode_Hu = register_mode(&newmode); - - /* signed integer */ - newmode.name = new_id_from_chars("Is", 2); - newmode.sign = 1; - newmode.size = 32; - newmode.modulo_shift = 32; - mode_Is = register_mode(&newmode); - - /* unsigned integer */ - newmode.name = new_id_from_chars("Iu", 2); - newmode.sign = 0; - newmode.size = 32; - newmode.modulo_shift = 32; - mode_Iu = register_mode(&newmode); - - /* signed long integer */ - newmode.name = new_id_from_chars("Ls", 2); - newmode.sign = 1; - newmode.size = 64; - newmode.modulo_shift = 64; - mode_Ls = register_mode(&newmode); - - /* unsigned long integer */ - newmode.name = new_id_from_chars("Lu", 2); - newmode.sign = 0; - newmode.size = 64; - newmode.modulo_shift = 64; - mode_Lu = register_mode(&newmode); - - /* signed long long integer */ - newmode.name = new_id_from_chars("LLs", 3); - newmode.sign = 1; - newmode.size = 128; - newmode.modulo_shift = 128; - mode_LLs = register_mode(&newmode); - - /* unsigned long long integer */ - newmode.name = new_id_from_chars("LLu", 3); - newmode.sign = 0; - newmode.size = 128; - newmode.modulo_shift = 128; - mode_LLu = register_mode(&newmode); - - /* Reference Mode */ - newmode.sort = irms_reference; - newmode.arithmetic = irma_twos_complement; - - /* pointer */ - newmode.name = new_id_from_chars("P", 1); - newmode.sign = 0; - newmode.size = 32; - newmode.modulo_shift = 32; - newmode.eq_signed = mode_Is; - newmode.eq_unsigned = mode_Iu; - mode_P = register_mode(&newmode); + mode_BB = new_internal_mode("BB", irms_block); + mode_X = new_internal_mode("X", irms_control_flow); + mode_M = new_internal_mode("M", irms_memory); + mode_T = new_internal_mode("T", irms_tuple); + mode_ANY = new_internal_mode("ANY", irms_any); + mode_BAD = new_internal_mode("BAD", irms_bad); + mode_b = new_internal_mode("b", irms_internal_boolean); + + mode_F = new_float_mode("F", irma_ieee754, 8, 23); + mode_D = new_float_mode("D", irma_ieee754, 11, 52); + mode_Q = new_float_mode("Q", irma_ieee754, 15, 112); + + mode_Bs = new_int_mode("Bs", irma_twos_complement, 8, 1, 32); + mode_Bu = new_int_mode("Bu", irma_twos_complement, 8, 0, 32); + mode_Hs = new_int_mode("Hs", irma_twos_complement, 16, 1, 32); + mode_Hu = new_int_mode("Hu", irma_twos_complement, 16, 0, 32); + mode_Is = new_int_mode("Is", irma_twos_complement, 32, 1, 32); + mode_Iu = new_int_mode("Iu", irma_twos_complement, 32, 0, 32); + mode_Ls = new_int_mode("Ls", irma_twos_complement, 64, 1, 64); + mode_Lu = new_int_mode("Lu", irma_twos_complement, 64, 0, 64); + mode_LLs = new_int_mode("LLs", irma_twos_complement, 128, 1, 128); + mode_LLu = new_int_mode("LLu", irma_twos_complement, 128, 0, 128); + + mode_P = new_reference_mode("P", irma_twos_complement, 32, 32); /* set the machine specific modes to the predefined ones */ mode_P_code = mode_P; @@ -873,7 +753,6 @@ void finish_mode(void) mode_F = NULL; mode_D = NULL; - mode_E = NULL; mode_Bs = NULL; mode_Bu = NULL; diff --git a/ir/ir/irmode_t.h b/ir/ir/irmode_t.h index 06cf8a8d1..19d8f5cb7 100644 --- a/ir/ir/irmode_t.h +++ b/ir/ir/irmode_t.h @@ -143,6 +143,16 @@ static inline ir_type *get_type_for_mode_(const ir_mode *mode) return mode->type; } +static inline unsigned get_mode_mantissa_size_(const ir_mode *mode) +{ + return mode->float_desc.mantissa_size; +} + +static inline unsigned get_mode_exponent_size_(const ir_mode *mode) +{ + return mode->float_desc.exponent_size; +} + /** mode module initialization, call once before use of any other function **/ void init_mode(void); @@ -169,5 +179,7 @@ void finish_mode(void); #define mode_is_datab(mode) mode_is_datab_(mode) #define mode_is_dataM(mode) mode_is_dataM_(mode) #define get_type_for_mode(mode) get_type_for_mode_(mode) +#define get_mode_mantissa_size(mode) get_mode_mantissa_size_(mode) +#define get_mode_exponent_size(mode) get_mode_exponent_size_(mode) #endif diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index b67e8ed4c..a2300fc31 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -1249,7 +1249,7 @@ restart: if (mode_is_int(n_mode) && get_mode_arithmetic(a_mode) == irma_ieee754) { /* ConvI(ConvF(I)) -> I, iff float mantissa >= int mode */ unsigned int_mantissa = get_mode_size_bits(n_mode) - (mode_is_signed(n_mode) ? 1 : 0); - unsigned float_mantissa = tarval_ieee754_get_mantissa_size(a_mode); + unsigned float_mantissa = get_mode_mantissa_size(a_mode); if (float_mantissa >= int_mantissa) { n = b; @@ -3230,10 +3230,11 @@ static ir_node *transform_node_Mul(ir_node *n) return n; } } - if (get_mode_arithmetic(mode) == irma_ieee754) { + if (get_mode_arithmetic(mode) == irma_ieee754 + || get_mode_arithmetic(mode) == irma_x86_extended_float) { if (is_Const(a)) { ir_tarval *tv = get_Const_tarval(a); - if (tarval_ieee754_get_exponent(tv) == 1 && tarval_ieee754_zero_mantissa(tv) + if (tarval_get_exponent(tv) == 1 && tarval_zero_mantissa(tv) && !tarval_is_negative(tv)) { /* 2.0 * b = b + b */ n = new_rd_Add(get_irn_dbg_info(n), get_nodes_block(n), b, b, mode); @@ -3243,7 +3244,7 @@ static ir_node *transform_node_Mul(ir_node *n) } else if (is_Const(b)) { ir_tarval *tv = get_Const_tarval(b); - if (tarval_ieee754_get_exponent(tv) == 1 && tarval_ieee754_zero_mantissa(tv) + if (tarval_get_exponent(tv) == 1 && tarval_zero_mantissa(tv) && !tarval_is_negative(tv)) { /* a * 2.0 = a + a */ n = new_rd_Add(get_irn_dbg_info(n), get_nodes_block(n), a, a, mode); diff --git a/ir/ir/irtypes.h b/ir/ir/irtypes.h index e10eced14..b5786a524 100644 --- a/ir/ir/irtypes.h +++ b/ir/ir/irtypes.h @@ -26,6 +26,8 @@ #ifndef FIRM_IR_IRDEFS_H #define FIRM_IR_IRDEFS_H +#include + #include "firm_types.h" #include "irdom_t.h" #include "irmode.h" @@ -72,6 +74,51 @@ struct ir_op { ir_op_ops ops; /**< The operations of the this op. */ }; +/** Helper values for ir_mode_sort. */ +enum ir_mode_sort_helper { + irmsh_is_num = 0x10, /**< mode represents a number */ + irmsh_is_data = 0x20, /**< mode represents data (can be carried in registers) */ + irmsh_is_datab = 0x40, /**< mode represents data or is internal boolean */ + irmsh_is_dataM = 0x80, /**< mode represents data or is memory */ +}; + +/** + * These values represent the different mode classes of value representations. + * Beware: do not change the order of these values without checking + * the mode_is + */ +typedef enum ir_mode_sort { + irms_control_flow = 0, /**< Marks all control flow modes. */ + irms_block = 1, + irms_tuple = 2, + irms_any = 3, + irms_bad = 4, + irms_memory = 5 | irmsh_is_dataM, /**< Marks the memory mode. Not extensible. (irm_M) */ + + /** Internal boolean representation. + Storing to memory impossible, convert first. (irm_b) */ + irms_internal_boolean = 6 | irmsh_is_datab, + + /** A mode to represent entities. + Restricted int computations can be performed */ + irms_reference = 7 | irmsh_is_data | irmsh_is_datab | irmsh_is_dataM, + /** A mode to represent int numbers. + Integer computations can be performed. */ + irms_int_number = 8 | irmsh_is_data | irmsh_is_datab | irmsh_is_dataM | irmsh_is_num, + /** A mode to represent float numbers. + Floating point computations can be performed. */ + irms_float_number = 9 | irmsh_is_data | irmsh_is_datab | irmsh_is_dataM | irmsh_is_num, +} ir_mode_sort; + +/** + * A descriptor for an IEEE754 float value. + */ +typedef struct float_descriptor_t { + unsigned char exponent_size; /**< size of exponent in bits */ + unsigned char mantissa_size; /**< size of mantissa in bits */ + bool explicit_one; /**< set if the leading one is explicit */ +} float_descriptor_t; + /** * Contains relevant information about a mode. * @@ -97,18 +144,18 @@ struct ir_mode { ident *name; /**< Name ident of this mode */ ir_type *type; /**< corresponding primitive type */ - /* ----------------------------------------------------------------------- */ + /* ---------------------------------------------------------------------- */ /* On changing this struct you have to evaluate the mode_are_equal function!*/ - ir_mode_sort sort; /**< coarse classification of this mode: - int, float, reference ... - (see irmode.h) */ - ir_mode_arithmetic - arithmetic; /**< different arithmetic operations possible with a mode */ - unsigned size; /**< size of the mode in Bits. */ - unsigned sign:1; /**< signedness of this mode */ - unsigned int modulo_shift; /**< number of bits a values of this mode will be shifted */ - - /* ----------------------------------------------------------------------- */ + ir_mode_sort sort; /**< coarse classification of this mode: + int, float, reference ... + (see irmode.h) */ + ir_mode_arithmetic arithmetic; /**< different arithmetic operations possible with a mode */ + unsigned size; /**< size of the mode in Bits. */ + unsigned sign:1; /**< signedness of this mode */ + unsigned int modulo_shift; /**< number of bits a values of this mode will be shifted */ + float_descriptor_t float_desc; + + /* ---------------------------------------------------------------------- */ ir_tarval *min; /**< the minimum value that can be expressed */ ir_tarval *max; /**< the maximum value that can be expressed */ ir_tarval *null; /**< the value 0 */ diff --git a/ir/lower/lower_dw.c b/ir/lower/lower_dw.c index a7b908a55..04bab7b3c 100644 --- a/ir/lower/lower_dw.c +++ b/ir/lower/lower_dw.c @@ -2758,10 +2758,10 @@ static void setup_modes(void) /* produce lowered modes */ env->high_signed = doubleword_signed; env->high_unsigned = doubleword_unsigned; - env->low_signed = new_ir_mode("WS", irms_int_number, size_bits, 1, - arithmetic, modulo_shift); - env->low_unsigned = new_ir_mode("WU", irms_int_number, size_bits, 0, - arithmetic, modulo_shift); + env->low_signed = new_int_mode("WS", arithmetic, size_bits, 1, + modulo_shift); + env->low_unsigned = new_int_mode("WU", arithmetic, size_bits, 0, + modulo_shift); } static void enqueue_preds(ir_node *node) diff --git a/ir/opt/scalar_replace.c b/ir/opt/scalar_replace.c index 053b68081..85779e1ee 100644 --- a/ir/opt/scalar_replace.c +++ b/ir/opt/scalar_replace.c @@ -174,7 +174,6 @@ static bool check_load_store_mode(ir_mode *mode, ir_mode *ent_mode) if (ent_mode != mode) { if (ent_mode == NULL || get_mode_size_bits(ent_mode) != get_mode_size_bits(mode) || - get_mode_sort(ent_mode) != get_mode_sort(mode) || get_mode_arithmetic(ent_mode) != irma_twos_complement || get_mode_arithmetic(mode) != irma_twos_complement) return false; diff --git a/ir/stat/const_stat.c b/ir/stat/const_stat.c index 296e74bfd..c6df3d677 100644 --- a/ir/stat/const_stat.c +++ b/ir/stat/const_stat.c @@ -73,8 +73,8 @@ static float_classify_t classify_float_value(ir_tarval *tv) return STAT_FC_0; else if (tv == get_mode_one(mode)) return STAT_FC_1; - else if (tarval_is_finite(tv) && tarval_ieee754_zero_mantissa(tv)) { - int exp = tarval_ieee754_get_exponent(tv); + else if (tarval_is_finite(tv) && tarval_zero_mantissa(tv)) { + int exp = tarval_get_exponent(tv); if (! tarval_is_negative(tv)) { if (exp == 1) diff --git a/ir/tv/fltcalc.c b/ir/tv/fltcalc.c index f9ac91f7d..2d9d9ece0 100644 --- a/ir/tv/fltcalc.c +++ b/ir/tv/fltcalc.c @@ -110,7 +110,7 @@ typedef union { /* our floating point value */ struct fp_value { - ieee_descriptor_t desc; + float_descriptor_t desc; unsigned char clss; char sign; char value[1]; /* exp[value_size] + mant[value_size] */ @@ -722,7 +722,7 @@ static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result) } #if 0 -static void _power_of_ten(int exp, ieee_descriptor_t *desc, char *result) +static void _power_of_ten(int exp, float_descriptor_t *desc, char *result) { char *build; char *temp; @@ -838,14 +838,14 @@ int fc_get_buffer_length(void) } void *fc_val_from_str(const char *str, size_t len, - const ieee_descriptor_t *desc, void *result) + const float_descriptor_t *desc, void *result) { char *buffer; /* XXX excuse of an implementation to make things work */ long double val; fp_value *tmp = (fp_value*) alloca(calc_buffer_size); - ieee_descriptor_t tmp_desc; + float_descriptor_t tmp_desc; buffer = (char*) alloca(len+1); memcpy(buffer, str, len); @@ -861,7 +861,7 @@ void *fc_val_from_str(const char *str, size_t len, return fc_cast(tmp, desc, (fp_value*) result); } -fp_value *fc_val_from_ieee754(long double l, const ieee_descriptor_t *desc, +fp_value *fc_val_from_ieee754(long double l, const float_descriptor_t *desc, fp_value *result) { char *temp; @@ -973,7 +973,7 @@ long double fc_val_to_ieee754(const fp_value *val) uint32_t mantissa1; value_t buildval; - ieee_descriptor_t desc; + float_descriptor_t desc; unsigned mantissa_size; size_t long_double_size = sizeof(long double); @@ -1027,7 +1027,7 @@ long double fc_val_to_ieee754(const fp_value *val) return buildval.d; } -fp_value *fc_cast(const fp_value *value, const ieee_descriptor_t *desc, +fp_value *fc_cast(const fp_value *value, const float_descriptor_t *desc, fp_value *result) { char *temp; @@ -1087,7 +1087,7 @@ fp_value *fc_cast(const fp_value *value, const ieee_descriptor_t *desc, return result; } -fp_value *fc_get_max(const ieee_descriptor_t *desc, fp_value *result) +fp_value *fc_get_max(const float_descriptor_t *desc, fp_value *result) { if (result == NULL) result = calc_buffer; @@ -1104,7 +1104,7 @@ fp_value *fc_get_max(const ieee_descriptor_t *desc, fp_value *result) return result; } -fp_value *fc_get_min(const ieee_descriptor_t *desc, fp_value *result) +fp_value *fc_get_min(const float_descriptor_t *desc, fp_value *result) { if (result == NULL) result = calc_buffer; @@ -1114,7 +1114,7 @@ fp_value *fc_get_min(const ieee_descriptor_t *desc, fp_value *result) return result; } -fp_value *fc_get_snan(const ieee_descriptor_t *desc, fp_value *result) +fp_value *fc_get_snan(const float_descriptor_t *desc, fp_value *result) { if (result == NULL) result = calc_buffer; @@ -1130,7 +1130,7 @@ fp_value *fc_get_snan(const ieee_descriptor_t *desc, fp_value *result) return result; } -fp_value *fc_get_qnan(const ieee_descriptor_t *desc, fp_value *result) +fp_value *fc_get_qnan(const float_descriptor_t *desc, fp_value *result) { if (result == NULL) result = calc_buffer; @@ -1149,7 +1149,7 @@ fp_value *fc_get_qnan(const ieee_descriptor_t *desc, fp_value *result) return result; } -fp_value *fc_get_plusinf(const ieee_descriptor_t *desc, fp_value *result) +fp_value *fc_get_plusinf(const float_descriptor_t *desc, fp_value *result) { char *mant; @@ -1170,7 +1170,7 @@ fp_value *fc_get_plusinf(const ieee_descriptor_t *desc, fp_value *result) return result; } -fp_value *fc_get_minusinf(const ieee_descriptor_t *desc, fp_value *result) +fp_value *fc_get_minusinf(const float_descriptor_t *desc, fp_value *result) { if (result == NULL) result = calc_buffer; @@ -1332,7 +1332,7 @@ int fc_get_exponent(const fp_value *value) } /* Return non-zero if a given value can be converted lossless into another precision */ -int fc_can_lossless_conv_to(const fp_value *value, const ieee_descriptor_t *desc) +int fc_can_lossless_conv_to(const fp_value *value, const float_descriptor_t *desc) { int v; int exp_bias; diff --git a/ir/tv/fltcalc.h b/ir/tv/fltcalc.h index 1b07f6dbb..dd5d4f8ea 100644 --- a/ir/tv/fltcalc.h +++ b/ir/tv/fltcalc.h @@ -29,6 +29,7 @@ #include #include "firm_types.h" +#include "irtypes.h" enum { FC_DEC, @@ -58,15 +59,6 @@ typedef enum { FC_NAN, /**< Not A Number */ } value_class_t; -/** - * A descriptor for an IEEE float value. - */ -typedef struct ieee_descriptor_t { - unsigned char exponent_size; /**< size of exponent in bits */ - unsigned char mantissa_size; /**< size of mantissa in bits */ - unsigned char explicit_one; /**< set if the leading one is explicit */ -} ieee_descriptor_t; - struct fp_value; typedef struct fp_value fp_value; @@ -81,7 +73,7 @@ const void *fc_get_buffer(void); int fc_get_buffer_length(void); /*}@*/ -void *fc_val_from_str(const char *str, size_t len, const ieee_descriptor_t *desc, void *result); +void *fc_val_from_str(const char *str, size_t len, const float_descriptor_t *desc, void *result); /** get the representation of a floating point value * This function tries to builds a representation having the same value as the @@ -100,7 +92,7 @@ void *fc_val_from_str(const char *str, size_t len, const ieee_descriptor_t *desc * @return The result pointer passed to the function. If this was NULL this returns * a pointer to the internal accumulator buffer */ -fp_value *fc_val_from_ieee754(long double l, const ieee_descriptor_t *desc, +fp_value *fc_val_from_ieee754(long double l, const float_descriptor_t *desc, fp_value *result); /** retrieve the float value of an internal value @@ -130,7 +122,7 @@ long double fc_val_to_ieee754(const fp_value *val); * @return The result pointer passed to the function. If this was NULL this returns * a pointer to the internal accumulator buffer */ -fp_value *fc_cast(const fp_value *val, const ieee_descriptor_t *desc, fp_value *result); +fp_value *fc_cast(const fp_value *val, const float_descriptor_t *desc, fp_value *result); /*@{*/ /** build a special float value @@ -145,12 +137,12 @@ fp_value *fc_cast(const fp_value *val, const ieee_descriptor_t *desc, fp_value * * @return The result pointer passed to the function. If this was NULL this returns * a pointer to the internal accumulator buffer */ -fp_value *fc_get_min(const ieee_descriptor_t *desc, fp_value *result); -fp_value *fc_get_max(const ieee_descriptor_t *desc, fp_value *result); -fp_value *fc_get_snan(const ieee_descriptor_t *desc, fp_value *result); -fp_value *fc_get_qnan(const ieee_descriptor_t *desc, fp_value *result); -fp_value *fc_get_plusinf(const ieee_descriptor_t *desc, fp_value *result); -fp_value *fc_get_minusinf(const ieee_descriptor_t *desc, fp_value *result); +fp_value *fc_get_min(const float_descriptor_t *desc, fp_value *result); +fp_value *fc_get_max(const float_descriptor_t *desc, fp_value *result); +fp_value *fc_get_snan(const float_descriptor_t *desc, fp_value *result); +fp_value *fc_get_qnan(const float_descriptor_t *desc, fp_value *result); +fp_value *fc_get_plusinf(const float_descriptor_t *desc, fp_value *result); +fp_value *fc_get_minusinf(const float_descriptor_t *desc, fp_value *result); /*@}*/ int fc_is_zero(const fp_value *a); @@ -200,7 +192,7 @@ int fc_get_exponent(const fp_value *value); /** * Return non-zero if a given value can be converted lossless into another precision. */ -int fc_can_lossless_conv_to(const fp_value *value, const ieee_descriptor_t *desc); +int fc_can_lossless_conv_to(const fp_value *value, const float_descriptor_t *desc); /** Set new rounding mode * This function sets the rounding mode to one of the following, returning diff --git a/ir/tv/tv.c b/ir/tv/tv.c index d15de3567..47ef2d4b6 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -100,18 +100,6 @@ static tarval_int_overflow_mode_t int_overflow_mode = TV_OVERFLOW_WRAP; /** if this is set non-zero, the constant folding for floating point is OFF */ static int no_float = 0; -/** IEEE-754r half precision */ -static const ieee_descriptor_t half_desc = { 5, 10, 0 }; -/** IEEE-754 single precision */ -static const ieee_descriptor_t single_desc = { 8, 23, 0 }; -/** IEEE-754 double precision */ -static const ieee_descriptor_t double_desc = { 11, 52, 0 }; -/** Intel x87 extended precision */ -static const ieee_descriptor_t extended_desc = { 15, 63, 1 }; - -/** IEEE-754r quad precision */ -static const ieee_descriptor_t quad_desc = { 15, 112, 0 }; - /**************************************************************************** * private functions ****************************************************************************/ @@ -304,22 +292,9 @@ ir_tarval *tarval_unreachable = &reserved_tv[5]; /** * get the float descriptor for given mode. */ -static const ieee_descriptor_t *get_descriptor(const ir_mode *mode) -{ - switch (get_mode_size_bits(mode)) { - case 16: return &half_desc; - case 32: return &single_desc; - case 64: return &double_desc; - case 80: - case 96: - case 128: return &extended_desc; /* FIXME: HACK for x86 where we have - sizeof(long double)==16 with 10 byte - real payload */ - /* case 128: return &quad_desc; */ - default: - (void) quad_desc; - panic("Unsupported mode in get_descriptor()"); - } +static const float_descriptor_t *get_descriptor(const ir_mode *mode) +{ + return &mode->float_desc; } ir_tarval *new_integer_tarval_from_str(const char *str, size_t len, char sign, @@ -393,18 +368,13 @@ static ir_tarval *new_tarval_from_str_int(const char *str, size_t len, */ ir_tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode) { - const ieee_descriptor_t *desc; + const float_descriptor_t *desc; assert(str); assert(len); assert(mode); switch (get_mode_sort(mode)) { - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - panic("Unsupported tarval creation with mode %F", mode); - case irms_internal_boolean: /* match [tT][rR][uU][eE]|[fF][aA][lL][sS][eE] */ if (!strcasecmp(str, "true")) @@ -426,8 +396,9 @@ ir_tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode) /* FALLTHROUGH */ case irms_int_number: return new_tarval_from_str_int(str, len, mode); + default: + panic("Unsupported tarval creation with mode %F", mode); } - panic("Unsupported tarval creation with mode %F", mode); } /* @@ -483,7 +454,7 @@ long get_tarval_long(ir_tarval* tv) ir_tarval *new_tarval_from_long_double(long double d, ir_mode *mode) { - const ieee_descriptor_t *desc; + const float_descriptor_t *desc; assert(mode && (get_mode_sort(mode) == irms_float_number)); desc = get_descriptor(mode); @@ -569,14 +540,9 @@ ir_tarval *(get_tarval_unreachable)(void) ir_tarval *get_tarval_max(ir_mode *mode) { - const ieee_descriptor_t *desc; + const float_descriptor_t *desc; switch (get_mode_sort(mode)) { - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - panic("mode %F does not support maximum value", mode); - case irms_internal_boolean: return tarval_b_true; @@ -589,20 +555,16 @@ ir_tarval *get_tarval_max(ir_mode *mode) case irms_int_number: sc_max_from_bits(get_mode_size_bits(mode), mode_is_signed(mode), NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); + default: + panic("mode %F does not support maximum value", mode); } - return tarval_bad; } ir_tarval *get_tarval_min(ir_mode *mode) { - const ieee_descriptor_t *desc; + const float_descriptor_t *desc; switch (get_mode_sort(mode)) { - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - panic("mode %F does not support minimum value", mode); - case irms_internal_boolean: return tarval_b_false; @@ -615,8 +577,9 @@ ir_tarval *get_tarval_min(ir_mode *mode) case irms_int_number: sc_min_from_bits(get_mode_size_bits(mode), mode_is_signed(mode), NULL); return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode); + default: + panic("mode %F does not support minimum value", mode); } - return tarval_bad; } /** The bit pattern for the pointer NULL */ @@ -625,11 +588,6 @@ static long _null_value = 0; ir_tarval *get_tarval_null(ir_mode *mode) { switch (get_mode_sort(mode)) { - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - panic("mode %F does not support null value", mode); - case irms_float_number: return new_tarval_from_double(0.0, mode); @@ -639,18 +597,14 @@ ir_tarval *get_tarval_null(ir_mode *mode) case irms_reference: return new_tarval_from_long(_null_value, mode); + default: + panic("mode %F does not support null value", mode); } - return tarval_bad; } ir_tarval *get_tarval_one(ir_mode *mode) { switch (get_mode_sort(mode)) { - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - panic("mode %F does not support one value", mode); - case irms_internal_boolean: return tarval_b_true; @@ -660,28 +614,25 @@ ir_tarval *get_tarval_one(ir_mode *mode) case irms_reference: case irms_int_number: return new_tarval_from_long(1l, mode); + default: + panic("mode %F does not support one value", mode); } - return tarval_bad; } ir_tarval *get_tarval_all_one(ir_mode *mode) { switch (get_mode_sort(mode)) { - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - panic("mode %F does not support all-one value", mode); - case irms_int_number: case irms_internal_boolean: case irms_reference: return tarval_not(get_mode_null(mode)); - case irms_float_number: return new_tarval_from_double(1.0, mode); + + default: + panic("mode %F does not support all-one value", mode); } - return tarval_bad; } int tarval_is_constant(ir_tarval *tv) @@ -696,12 +647,6 @@ int tarval_is_constant(ir_tarval *tv) ir_tarval *get_tarval_minus_one(ir_mode *mode) { switch (get_mode_sort(mode)) { - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - case irms_internal_boolean: - panic("mode %F does not support minus one value", mode); - case irms_reference: return tarval_bad; @@ -710,13 +655,15 @@ ir_tarval *get_tarval_minus_one(ir_mode *mode) case irms_int_number: return new_tarval_from_long(-1l, mode); + + default: + panic("mode %F does not support minus one value", mode); } - return tarval_bad; } ir_tarval *get_tarval_nan(ir_mode *mode) { - const ieee_descriptor_t *desc; + const float_descriptor_t *desc; if (get_mode_sort(mode) == irms_float_number) { desc = get_descriptor(mode); @@ -729,7 +676,7 @@ ir_tarval *get_tarval_nan(ir_mode *mode) ir_tarval *get_tarval_plus_inf(ir_mode *mode) { if (get_mode_sort(mode) == irms_float_number) { - const ieee_descriptor_t *desc = get_descriptor(mode); + const float_descriptor_t *desc = get_descriptor(mode); fc_get_plusinf(desc, NULL); return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); } else @@ -739,7 +686,7 @@ ir_tarval *get_tarval_plus_inf(ir_mode *mode) ir_tarval *get_tarval_minus_inf(ir_mode *mode) { if (get_mode_sort(mode) == irms_float_number) { - const ieee_descriptor_t *desc = get_descriptor(mode); + const float_descriptor_t *desc = get_descriptor(mode); fc_get_minusinf(desc, NULL); return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode); } else @@ -825,13 +772,6 @@ ir_relation tarval_cmp(ir_tarval *a, ir_tarval *b) /* Here the two tarvals are unequal and of the same mode */ switch (get_mode_sort(a->mode)) { - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - if (a == b) - return ir_relation_equal; - return ir_relation_false; - case irms_float_number: /* * BEWARE: we cannot compare a == b here, because @@ -854,8 +794,10 @@ ir_relation tarval_cmp(ir_tarval *a, ir_tarval *b) if (a == b) return ir_relation_equal; return a == tarval_b_true ? ir_relation_greater : ir_relation_less; + + default: + panic("can't compare values of mode %F", a->mode); } - return ir_relation_false; } /* @@ -865,7 +807,7 @@ ir_tarval *tarval_convert_to(ir_tarval *src, ir_mode *dst_mode) { char *buffer; fp_value *res = NULL; - const ieee_descriptor_t *desc; + const float_descriptor_t *desc; int len; carry_flag = -1; @@ -877,12 +819,7 @@ ir_tarval *tarval_convert_to(ir_tarval *src, ir_mode *dst_mode) return src; switch (get_mode_sort(src->mode)) { - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - break; - - /* cast float to something */ + /* cast float to something */ case irms_float_number: switch (get_mode_sort(dst_mode)) { case irms_float_number: @@ -958,6 +895,8 @@ ir_tarval *tarval_convert_to(ir_tarval *src, ir_mode *dst_mode) return get_tarval_overflow(buffer, src->length, dst_mode); } break; + default: + return tarval_bad; } return tarval_bad; @@ -1494,21 +1433,9 @@ int tarval_snprintf(char *buf, size_t len, ir_tarval *tv) return snprintf(buf, len, "%s%s%s", prefix, (tv == tarval_b_true) ? "true" : "false", suffix); } - case irms_control_flow: - case irms_memory: - case irms_auxiliary: - if (tv == tarval_bad) - return snprintf(buf, len, ""); - if (tv == tarval_undefined) - return snprintf(buf, len, ""); - if (tv == tarval_unreachable) - return snprintf(buf, len, ""); - if (tv == tarval_reachable) - return snprintf(buf, len, ""); + default: return snprintf(buf, len, ""); } - - return 0; } /** @@ -1662,16 +1589,18 @@ int get_tarval_lowest_bit(ir_tarval *tv) * Returns non-zero if the mantissa of a floating point IEEE-754 * tarval is zero (i.e. 1.0Exxx) */ -int tarval_ieee754_zero_mantissa(ir_tarval *tv) +int tarval_zero_mantissa(ir_tarval *tv) { - assert(get_mode_arithmetic(tv->mode) == irma_ieee754); + assert(get_mode_arithmetic(tv->mode) == irma_ieee754 + || get_mode_arithmetic(tv->mode) == irma_x86_extended_float); return fc_zero_mantissa((const fp_value*) tv->value); } /* Returns the exponent of a floating point IEEE-754 tarval. */ -int tarval_ieee754_get_exponent(ir_tarval *tv) +int tarval_get_exponent(ir_tarval *tv) { - assert(get_mode_arithmetic(tv->mode) == irma_ieee754); + assert(get_mode_arithmetic(tv->mode) == irma_ieee754 + || get_mode_arithmetic(tv->mode) == irma_x86_extended_float); return fc_get_exponent((const fp_value*) tv->value); } @@ -1681,7 +1610,7 @@ int tarval_ieee754_get_exponent(ir_tarval *tv) */ int tarval_ieee754_can_conv_lossless(ir_tarval *tv, ir_mode *mode) { - const ieee_descriptor_t *desc = get_descriptor(mode); + const float_descriptor_t *desc = get_descriptor(mode); return fc_can_lossless_conv_to((const fp_value*) tv->value, desc); } @@ -1691,18 +1620,6 @@ unsigned tarval_ieee754_get_exact(void) return fc_is_exact(); } -/* Return the size of the mantissa in bits (including possible - implicit bits) for the given mode. */ -unsigned tarval_ieee754_get_mantissa_size(const ir_mode *mode) -{ - const ieee_descriptor_t *desc; - - assert(get_mode_arithmetic(mode) == irma_ieee754); - desc = get_descriptor(mode); - - return desc->mantissa_size + desc->explicit_one; -} - /* check if its the a floating point NaN */ int tarval_is_NaN(ir_tarval *tv) {