Commit e3b765fc authored by Matthias Braun's avatar Matthias Braun
Browse files

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
parent f8211068
......@@ -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))
......
......@@ -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,
......
......@@ -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.
*/
......
......@@ -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;
......
......@@ -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:
......
......@@ -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 = (
......
......@@ -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();
......
......@@ -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);