#define SFP_ABS "0x7FFFFFFF"
#define DFP_ABS "0x7FFFFFFFFFFFFFFF"
#define DFP_INTMAX "9223372036854775807"
+#define ULL_BIAS "18446744073709551616"
#define TP_SFP_SIGN "ia32_sfp_sign"
#define TP_DFP_SIGN "ia32_dfp_sign"
#define TP_SFP_ABS "ia32_sfp_abs"
#define TP_DFP_ABS "ia32_dfp_abs"
-#define TP_INT_MAX "ia32_int_max"
+#define TP_ULL_BIAS "ia32_ull_bias"
-#define ENT_SFP_SIGN "IA32_SFP_SIGN"
-#define ENT_DFP_SIGN "IA32_DFP_SIGN"
-#define ENT_SFP_ABS "IA32_SFP_ABS"
-#define ENT_DFP_ABS "IA32_DFP_ABS"
-#define ENT_INT_MAX "IA32_INT_MAX"
+#define ENT_SFP_SIGN ".LC_ia32_sfp_sign"
+#define ENT_DFP_SIGN ".LC_ia32_dfp_sign"
+#define ENT_SFP_ABS ".LC_ia32_sfp_abs"
+#define ENT_DFP_ABS ".LC_ia32_dfp_abs"
+#define ENT_ULL_BIAS ".LC_ia32_ull_bias"
#define mode_vfp (ia32_reg_classes[CLASS_ia32_vfp].mode)
#define mode_xmm (ia32_reg_classes[CLASS_ia32_xmm].mode)
{ TP_DFP_SIGN, ENT_DFP_SIGN, DFP_SIGN, 1, 16 }, /* ia32_DSIGN */
{ TP_SFP_ABS, ENT_SFP_ABS, SFP_ABS, 0, 16 }, /* ia32_SABS */
{ TP_DFP_ABS, ENT_DFP_ABS, DFP_ABS, 1, 16 }, /* ia32_DABS */
- { TP_INT_MAX, ENT_INT_MAX, DFP_INTMAX, 2, 4 } /* ia32_INTMAX */
+ { TP_ULL_BIAS, ENT_ULL_BIAS, ULL_BIAS, 2, 4 } /* ia32_ULLBIAS */
};
static ir_entity *ent_cache[ia32_known_const_max];
const char *tp_name, *ent_name, *cnst_str;
ir_type *tp;
- ir_node *cnst;
- ir_graph *rem;
ir_entity *ent;
tarval *tv;
ir_mode *mode;
/* set the specified alignment */
set_type_alignment_bytes(tp, names[kct].align);
+ if (kct == ia32_ULLBIAS) {
+ /* we are in the backend, construct a fixed type here */
+ unsigned size = get_type_size_bytes(tp);
+ tp = new_type_array(new_id_from_str(tp_name), 1, tp);
+ set_type_alignment_bytes(tp, names[kct].align);
+ set_type_size_bytes(tp, 2 * size);
+ set_type_state(tp, layout_fixed);
+ }
ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);
set_entity_ld_ident(ent, get_entity_ident(ent));
set_entity_variability(ent, variability_constant);
set_entity_allocation(ent, allocation_static);
- /* we create a new entity here: It's initialization must resist on the
- const code irg */
- rem = current_ir_graph;
- current_ir_graph = get_const_code_irg();
- cnst = new_Const(mode, tv);
- current_ir_graph = rem;
+ if (kct == ia32_ULLBIAS) {
+ ir_initializer_t *initializer = create_initializer_compound(2);
+
+ set_initializer_compound_value(initializer, 0,
+ create_initializer_tarval(get_tarval_null(mode)));
+ set_initializer_compound_value(initializer, 1,
+ create_initializer_tarval(tv));
- set_atomic_ent_value(ent, cnst);
+ set_entity_initializer(ent, initializer);
+ } else {
+ set_entity_initializer(ent, create_initializer_tarval(tv));
+ }
/* cache the entry */
ent_cache[kct] = ent;
src_mode = get_irn_mode(get_Conv_op(node));
dest_mode = get_irn_mode(node);
- return ia32_mode_needs_gp_reg(src_mode)
- && ia32_mode_needs_gp_reg(dest_mode)
- && get_mode_size_bits(dest_mode) < get_mode_size_bits(src_mode);
+ return
+ ia32_mode_needs_gp_reg(src_mode) &&
+ ia32_mode_needs_gp_reg(dest_mode) &&
+ get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
}
/* Skip all Down-Conv's on a given node and return the resulting node. */
assert(use_am || !(flags & match_8bit_am));
assert(use_am || !(flags & match_16bit_am));
- if (mode_bits == 8) {
- if (!(flags & match_8bit_am))
- use_am = 0;
- /* we don't automatically add upconvs yet */
- assert((flags & match_mode_neutral) || (flags & match_8bit));
- } else if (mode_bits == 16) {
- if (!(flags & match_16bit_am))
- use_am = 0;
- /* we don't automatically add upconvs yet */
- assert((flags & match_mode_neutral) || (flags & match_16bit));
+ if ((mode_bits == 8 && !(flags & match_8bit_am)) ||
+ (mode_bits == 16 && !(flags & match_16bit_am))) {
+ use_am = 0;
}
/* we can simply skip downconvs for mode neutral nodes: the upper bits
ia32_address_t *addr = &am.addr;
memset(&am, 0, sizeof(am));
- assert(flags & match_dest_am);
assert(flags & match_immediate); /* there is no destam node without... */
commutative = (flags & match_commutative) != 0;
}
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_bd_ia32_AddMem, new_bd_ia32_AddMem8Bit,
- match_dest_am | match_commutative |
- match_immediate);
+ match_commutative | match_immediate);
break;
case iro_Sub:
op1 = get_Sub_left(val);
}
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_bd_ia32_SubMem, new_bd_ia32_SubMem8Bit,
- match_dest_am | match_immediate);
+ match_immediate);
break;
case iro_And:
op1 = get_And_left(val);
op2 = get_And_right(val);
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_bd_ia32_AndMem, new_bd_ia32_AndMem8Bit,
- match_dest_am | match_commutative |
- match_immediate);
+ match_commutative | match_immediate);
break;
case iro_Or:
op1 = get_Or_left(val);
op2 = get_Or_right(val);
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_bd_ia32_OrMem, new_bd_ia32_OrMem8Bit,
- match_dest_am | match_commutative |
- match_immediate);
+ match_commutative | match_immediate);
break;
case iro_Eor:
op1 = get_Eor_left(val);
op2 = get_Eor_right(val);
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_bd_ia32_XorMem, new_bd_ia32_XorMem8Bit,
- match_dest_am | match_commutative |
- match_immediate);
+ match_commutative | match_immediate);
break;
case iro_Shl:
op1 = get_Shl_left(val);
op2 = get_Shl_right(val);
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_bd_ia32_ShlMem, new_bd_ia32_ShlMem,
- match_dest_am | match_immediate);
+ match_immediate);
break;
case iro_Shr:
op1 = get_Shr_left(val);
op2 = get_Shr_right(val);
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_bd_ia32_ShrMem, new_bd_ia32_ShrMem,
- match_dest_am | match_immediate);
+ match_immediate);
break;
case iro_Shrs:
op1 = get_Shrs_left(val);
op2 = get_Shrs_right(val);
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_bd_ia32_SarMem, new_bd_ia32_SarMem,
- match_dest_am | match_immediate);
+ match_immediate);
break;
case iro_Rotl:
op1 = get_Rotl_left(val);
op2 = get_Rotl_right(val);
new_node = dest_am_binop(val, op1, op2, mem, ptr, mode,
new_bd_ia32_RolMem, new_bd_ia32_RolMem,
- match_dest_am | match_immediate);
+ match_immediate);
break;
/* TODO: match ROR patterns... */
case iro_Mux:
return new_node;
}
+static bool possible_int_mode_for_fp(ir_mode *mode)
+{
+ unsigned size;
+
+ if (!mode_is_signed(mode))
+ return false;
+ size = get_mode_size_bits(mode);
+ if (size != 16 && size != 32)
+ return false;
+ return true;
+}
+
static int is_float_to_int_conv(const ir_node *node)
{
ir_mode *mode = get_irn_mode(node);
ir_node *conv_op;
ir_mode *conv_mode;
- if (mode != mode_Is && mode != mode_Hs)
+ if (!possible_int_mode_for_fp(mode))
return 0;
if (!is_Conv(node))
return upper_bits_clean(get_irn_n(transformed_node, n_ia32_Shr_val), mode);
}
- case iro_ia32_And:
- if (mode_is_signed(mode))
- return false; /* TODO handle signed modes */
- return
- upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_right), mode) ||
- upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_left), mode);
+ case iro_ia32_Sar:
+ /* TODO too conservative if shift amount is constant */
+ return upper_bits_clean(get_irn_n(transformed_node, n_ia32_Sar_val), mode);
+ case iro_ia32_And:
+ if (!mode_is_signed(mode)) {
+ return
+ upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_right), mode) ||
+ upper_bits_clean(get_irn_n(transformed_node, n_ia32_And_left), mode);
+ }
+ /* TODO if one is known to be zero extended, then || is sufficient */
+ /* FALLTHROUGH */
case iro_ia32_Or:
case iro_ia32_Xor:
return
match_arguments(&am, block, and_left, and_right, NULL,
match_commutative |
match_am | match_8bit_am | match_16bit_am |
- match_am_and_immediates | match_immediate |
- match_8bit | match_16bit);
+ match_am_and_immediates | match_immediate);
/* use 32bit compare mode if possible since the opcode is smaller */
if (upper_bits_clean(am.new_op1, cmp_mode) &&
match_arguments(&am, block, left, right, NULL,
match_commutative | match_am | match_8bit_am |
match_16bit_am | match_am_and_immediates |
- match_immediate | match_8bit | match_16bit);
+ match_immediate);
/* use 32bit compare mode if possible since the opcode is smaller */
if (upper_bits_clean(am.new_op1, cmp_mode) &&
upper_bits_clean(am.new_op2, cmp_mode)) {
ir_node *val_true = get_Mux_true(node);
ir_node *val_false = get_Mux_false(node);
ir_node *new_node;
- match_flags_t match_flags;
ia32_address_mode_t am;
ia32_address_t *addr;
addr = &am.addr;
- match_flags = match_commutative | match_am | match_16bit_am |
- match_mode_neutral;
-
- match_arguments(&am, block, val_false, val_true, flags, match_flags);
+ match_arguments(&am, block, val_false, val_true, flags,
+ match_commutative | match_am | match_16bit_am | match_mode_neutral);
new_node = new_bd_ia32_CMov(dbgi, new_block, addr->base, addr->index,
addr->mem, am.new_op1, am.new_op2, new_flags,
return new_node;
}
+static ir_node *create_Conv_I2I(dbg_info *dbgi, ir_node *block, ir_node *base,
+ ir_node *index, ir_node *mem, ir_node *val, ir_mode *mode)
+{
+ ir_node *(*func)(dbg_info*, ir_node*, ir_node*, ir_node*, ir_node*, ir_node*, ir_mode*);
+
+ func = get_mode_size_bits(mode) == 8 ?
+ new_bd_ia32_Conv_I2I8Bit : new_bd_ia32_Conv_I2I;
+ return func(dbgi, block, base, index, mem, val, mode);
+}
+
/**
* Create a conversion from general purpose to x87 register
*/
ir_node *fild;
ir_node *store;
ir_node *new_node;
- int src_bits;
/* fild can use source AM if the operand is a signed 16bit or 32bit integer */
- if (src_mode == mode_Is || src_mode == mode_Hs) {
+ if (possible_int_mode_for_fp(src_mode)) {
ia32_address_mode_t am;
- match_arguments(&am, src_block, NULL, op, NULL,
- match_am | match_try_am | match_16bit | match_16bit_am);
+ match_arguments(&am, src_block, NULL, op, NULL, match_am | match_try_am | match_16bit_am);
if (am.op_type == ia32_AddrModeS) {
ia32_address_t *addr = &am.addr;
mode = get_irn_mode(op);
/* first convert to 32 bit signed if necessary */
- src_bits = get_mode_size_bits(src_mode);
- if (src_bits == 8) {
- new_op = new_bd_ia32_Conv_I2I8Bit(dbgi, block, noreg, noreg, nomem,
- new_op, src_mode);
- SET_IA32_ORIG_NODE(new_op, node);
- mode = mode_Is;
- } else if (src_bits < 32) {
- new_op = new_bd_ia32_Conv_I2I(dbgi, block, noreg, noreg, nomem,
- new_op, src_mode);
- SET_IA32_ORIG_NODE(new_op, node);
+ if (get_mode_size_bits(src_mode) < 32) {
+ if (!upper_bits_clean(new_op, src_mode)) {
+ new_op = create_Conv_I2I(dbgi, block, noreg, noreg, nomem, new_op, src_mode);
+ SET_IA32_ORIG_NODE(new_op, node);
+ }
mode = mode_Is;
}
dbg_info *dbgi, ir_node *block, ir_node *op,
ir_node *node)
{
- int src_bits = get_mode_size_bits(src_mode);
- int tgt_bits = get_mode_size_bits(tgt_mode);
- ir_node *new_block = be_transform_node(block);
- ir_node *new_node;
- ir_mode *smaller_mode;
- int smaller_bits;
+ ir_node *new_block = be_transform_node(block);
+ ir_node *new_node;
+ ir_mode *smaller_mode;
ia32_address_mode_t am;
ia32_address_t *addr = &am.addr;
(void) node;
- if (src_bits < tgt_bits) {
+ if (get_mode_size_bits(src_mode) < get_mode_size_bits(tgt_mode)) {
smaller_mode = src_mode;
- smaller_bits = src_bits;
} else {
smaller_mode = tgt_mode;
- smaller_bits = tgt_bits;
}
#ifdef DEBUG_libfirm
#endif
match_arguments(&am, block, NULL, op, NULL,
- match_8bit | match_16bit |
match_am | match_8bit_am | match_16bit_am);
if (upper_bits_clean(am.new_op2, smaller_mode)) {
return am.new_op2;
}
- if (smaller_bits == 8) {
- new_node = new_bd_ia32_Conv_I2I8Bit(dbgi, new_block, addr->base,
- addr->index, addr->mem, am.new_op2,
- smaller_mode);
- } else {
- new_node = new_bd_ia32_Conv_I2I(dbgi, new_block, addr->base,
- addr->index, addr->mem, am.new_op2,
- smaller_mode);
- }
+ new_node = create_Conv_I2I(dbgi, new_block, addr->base, addr->index,
+ addr->mem, am.new_op2, smaller_mode);
set_am_attributes(new_node, &am);
/* match_arguments assume that out-mode = in-mode, this isn't true here
* so fix it */
ir_node *nomem = new_NoMem();
ir_node *res = NULL;
+ assert(!mode_is_int(src_mode) || src_bits <= 32);
+ assert(!mode_is_int(tgt_mode) || tgt_bits <= 32);
+
if (src_mode == mode_b) {
assert(mode_is_int(tgt_mode) || mode_is_reference(tgt_mode));
/* nothing to do, we already model bools as 0/1 ints */
assert(get_irn_mode(op) == mode_P);
- match_arguments(&am, block, NULL, op, NULL,
- match_am | match_8bit_am | match_16bit_am |
- match_immediate | match_8bit | match_16bit);
+ match_arguments(&am, block, NULL, op, NULL, match_am | match_immediate);
new_node = new_bd_ia32_IJmp(dbgi, new_block, addr->base, addr->index,
addr->mem, am.new_op2);
ir_node *new_val_low = be_transform_node(val_low);
ir_node *new_val_high = be_transform_node(val_high);
ir_node *in[2];
- ir_node *sync;
- ir_node *fild;
- ir_node *store_low;
- ir_node *store_high;
+ ir_node *sync, *fild, *res;
+ ir_node *store_low, *store_high;
- if (!mode_is_signed(get_irn_mode(val_high))) {
- panic("unsigned long long -> float not supported yet (%+F)", node);
+ if (ia32_cg_config.use_sse2) {
+ panic("ia32_l_LLtoFloat not implemented for SSE2");
}
/* do a store */
SET_IA32_ORIG_NODE(fild, node);
- return new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res);
+ res = new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res);
+
+ if (! mode_is_signed(get_irn_mode(val_high))) {
+ ia32_address_mode_t am;
+
+ ir_node *count = create_Immediate(NULL, 0, 31);
+ ir_node *fadd;
+
+ am.addr.base = ia32_new_NoReg_gp(env_cg);
+ am.addr.index = new_bd_ia32_Shr(dbgi, block, new_val_high, count);
+ am.addr.mem = nomem;
+ am.addr.offset = 0;
+ am.addr.scale = 2;
+ am.addr.symconst_ent = ia32_gen_fp_known_const(ia32_ULLBIAS);
+ am.addr.use_frame = 0;
+ am.addr.frame_entity = NULL;
+ am.addr.symconst_sign = 0;
+ am.ls_mode = mode_F;
+ am.mem_proj = nomem;
+ am.op_type = ia32_AddrModeS;
+ am.new_op1 = res;
+ am.new_op2 = ia32_new_NoReg_vfp(env_cg);
+ am.pinned = op_pin_state_floats;
+ am.commutative = 1;
+ am.ins_permuted = 0;
+
+ fadd = new_bd_ia32_vfadd(dbgi, block, am.addr.base, am.addr.index, am.addr.mem,
+ am.new_op1, am.new_op2, get_fpcw());
+ set_am_attributes(fadd, &am);
+
+ set_irn_mode(fadd, mode_T);
+ res = new_rd_Proj(NULL, irg, block, fadd, mode_vfp, pn_ia32_res);
+ }
+ return res;
}
static ir_node *gen_ia32_l_FloattoLL(ir_node *node)