+ l_sub = new_bd_ia32_l_Sub(dbg, block, sub_l, sign_l, mode_T);
+ l_res = new_r_Proj(l_sub, l_mode, pn_ia32_res);
+ flags = new_r_Proj(l_sub, mode_flags, pn_ia32_flags);
+ h_res = new_bd_ia32_l_Sbb(dbg, block, sub_h, sign, flags, h_mode);
+
+ resolve_call(call, l_res, h_res, current_ir_graph, block);
+
+ return 1;
+}
+
+#define ID(x) new_id_from_chars(x, sizeof(x)-1)
+
+/**
+ * Maps a Div. Change into a library call.
+ */
+static int map_Div(ir_node *call, void *ctx)
+{
+ ia32_intrinsic_env_t *env = ctx;
+ ir_type *method = get_Call_type(call);
+ ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
+ ir_node *ptr;
+ ir_entity *ent;
+ ir_graph *irg = get_irn_irg(call);
+ symconst_symbol sym;
+
+ if (mode_is_signed(h_mode)) {
+ /* 64bit signed Division */
+ ent = env->divdi3;
+ if (ent == NULL) {
+ /* create library entity */
+ ent = env->divdi3 = new_entity(get_glob_type(), ID("__divdi3"), method);
+ set_entity_visibility(ent, ir_visibility_external);
+ set_entity_ld_ident(ent, ID("__divdi3"));
+ }
+ } else {
+ /* 64bit unsigned Division */
+ ent = env->udivdi3;
+ if (ent == NULL) {
+ /* create library entity */
+ ent = env->udivdi3 = new_entity(get_glob_type(), ID("__udivdi3"), method);
+ set_entity_visibility(ent, ir_visibility_external);
+ set_entity_ld_ident(ent, ID("__udivdi3"));
+ }
+ }
+
+ ptr = get_Call_ptr(call);
+ sym.entity_p = ent;
+ ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
+ set_Call_ptr(call, ptr);
+
+ return 1;
+}
+
+/**
+ * Maps a Mod. Change into a library call
+ */
+static int map_Mod(ir_node *call, void *ctx)
+{
+ ia32_intrinsic_env_t *env = ctx;
+ ir_type *method = get_Call_type(call);
+ ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
+ ir_node *ptr;
+ ir_entity *ent;
+ ir_graph *irg = get_irn_irg(call);
+ symconst_symbol sym;
+
+ if (mode_is_signed(h_mode)) {
+ /* 64bit signed Modulo */
+ ent = env->moddi3;
+ if (ent == NULL) {
+ /* create library entity */
+ ent = env->moddi3 = new_entity(get_glob_type(), ID("__moddi3"), method);
+ set_entity_visibility(ent, ir_visibility_external);
+ set_entity_ld_ident(ent, ID("__moddi3"));
+ }
+ } else {
+ /* 64bit signed Modulo */
+ ent = env->umoddi3;
+ if (ent == NULL) {
+ /* create library entity */
+ ent = env->umoddi3 = new_entity(get_glob_type(), ID("__umoddi3"), method);
+ set_entity_visibility(ent, ir_visibility_external);
+ set_entity_ld_ident(ent, ID("__umoddi3"));
+ }
+ }
+
+ ptr = get_Call_ptr(call);
+ sym.entity_p = ent;
+ ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
+ set_Call_ptr(call, ptr);
+
+ return 1;
+}
+
+/**
+ * Maps a Conv.
+ */
+static int map_Conv(ir_node *call, void *ctx)
+{
+ ir_graph *irg = current_ir_graph;
+ dbg_info *dbg = get_irn_dbg_info(call);
+ ir_node *block = get_nodes_block(call);
+ ir_node **params = get_Call_param_arr(call);
+ ir_type *method = get_Call_type(call);
+ int n = get_Call_n_params(call);
+ ir_node *l_res, *h_res;
+ (void) ctx;
+
+ if (n == 1) {
+ ir_node *float_to_ll;
+
+ /* We have a Conv float -> long long here */
+ ir_node *a_f = params[0];
+ ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
+ ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
+
+ assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
+
+ if (mode_is_signed(h_res_mode)) {
+ /* convert from float to signed 64bit */
+ float_to_ll = new_bd_ia32_l_FloattoLL(dbg, block, a_f);
+
+ l_res = new_r_Proj(float_to_ll, l_res_mode,
+ pn_ia32_l_FloattoLL_res_low);
+ h_res = new_r_Proj(float_to_ll, h_res_mode,
+ pn_ia32_l_FloattoLL_res_high);
+ } else {
+ /* convert from float to signed 64bit */
+ ir_mode *flt_mode = get_irn_mode(a_f);
+ tarval *flt_tv = new_tarval_from_str("9223372036854775808", 19, flt_mode);
+ ir_node *flt_corr = new_Const(flt_tv);
+ ir_node *lower_blk = block;
+ ir_node *upper_blk;
+ ir_node *cmp, *proj, *cond, *blk, *int_phi, *flt_phi;
+ ir_node *in[2];
+
+ part_block(call);
+ upper_blk = get_nodes_block(call);
+
+ cmp = new_rd_Cmp(dbg, upper_blk, a_f, flt_corr);
+ proj = new_r_Proj(cmp, mode_b, pn_Cmp_Lt);
+ cond = new_rd_Cond(dbg, upper_blk, proj);
+ in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
+ in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
+ blk = new_r_Block(irg, 1, &in[1]);
+ in[1] = new_r_Jmp(blk);
+
+ set_irn_in(lower_blk, 2, in);
+
+ /* create to Phis */
+ in[0] = new_Const(get_mode_null(h_res_mode));
+ in[1] = new_Const_long(h_res_mode, 0x80000000);
+
+ int_phi = new_r_Phi(lower_blk, 2, in, h_res_mode);
+
+ in[0] = a_f;
+ in[1] = new_rd_Sub(dbg, upper_blk, a_f, flt_corr, flt_mode);
+
+ flt_phi = new_r_Phi(lower_blk, 2, in, flt_mode);
+
+ /* fix Phi links for next part_block() */
+ set_Block_phis(lower_blk, int_phi);
+ set_Phi_next(int_phi, flt_phi);
+ set_Phi_next(flt_phi, NULL);
+
+ float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi);
+
+ l_res = new_r_Proj(float_to_ll, l_res_mode,
+ pn_ia32_l_FloattoLL_res_low);
+ h_res = new_r_Proj(float_to_ll, h_res_mode,
+ pn_ia32_l_FloattoLL_res_high);
+
+ h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, h_res_mode);
+
+ /* move the call and its Proj's to the lower block */
+ set_nodes_block(call, lower_blk);
+
+ for (proj = get_irn_link(call); proj != NULL; proj = get_irn_link(proj))
+ set_nodes_block(proj, lower_blk);
+ block = lower_blk;
+ }
+ /* lower the call */
+ resolve_call(call, l_res, h_res, irg, block);
+ } else if (n == 2) {
+ ir_node *ll_to_float;
+
+ /* We have a Conv long long -> float here */
+ ir_node *a_l = params[BINOP_Left_Low];
+ ir_node *a_h = params[BINOP_Left_High];
+ ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
+
+ assert(! mode_is_float(get_irn_mode(a_l))
+ && ! mode_is_float(get_irn_mode(a_h)));
+
+ ll_to_float = new_bd_ia32_l_LLtoFloat(dbg, block, a_h, a_l, fres_mode);
+
+ /* lower the call */
+ resolve_call(call, ll_to_float, NULL, irg, block);
+ } else {
+ panic("unexpected Conv call %+F", call);
+ }