+/**
+ * Map a Minus (a_l, a_h)
+ */
+static int map_Minus(ir_node *call, void *ctx)
+{
+ 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);
+ ir_node *a_l = params[BINOP_Left_Low];
+ ir_node *a_h = params[BINOP_Left_High];
+ ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
+ ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
+ ir_node *l_res, *h_res, *res;
+ (void) ctx;
+
+ res = new_bd_ia32_Minus64Bit(dbg, block, a_l, a_h);
+ l_res = new_r_Proj(res, l_mode, pn_ia32_Minus64Bit_low_res);
+ h_res = new_r_Proj(res, h_mode, pn_ia32_Minus64Bit_high_res);
+
+ 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 = (ia32_intrinsic_env_t*)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 */
+ ident *id = ID("__divdi3");
+ ent = env->divdi3 = create_compilerlib_entity(id, method);
+ }
+ } else {
+ /* 64bit unsigned Division */
+ ent = env->udivdi3;
+ if (ent == NULL) {
+ /* create library entity */
+ ident *id = ID("__udivdi3");
+ ent = env->udivdi3 = create_compilerlib_entity(id, method);
+ }
+ }
+
+ 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 = (ia32_intrinsic_env_t*)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 */
+ ident *id = ID("__moddi3");
+ ent = env->moddi3 = create_compilerlib_entity(id, method);
+ }
+ } else {
+ /* 64bit signed Modulo */
+ ent = env->umoddi3;
+ if (ent == NULL) {
+ /* create library entity */
+ ident *id = ID("__umoddi3");
+ ent = env->umoddi3 = create_compilerlib_entity(id, method);
+ }
+ }
+
+ 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 unsigned 64bit. */
+ ir_tarval *flt_tv = new_tarval_from_str("9223372036854775808", 19, ia32_mode_E);
+ ir_node *flt_corr = new_r_Const(irg, 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);
+
+ a_f = new_rd_Conv(dbg, upper_blk, a_f, ia32_mode_E);
+ cmp = new_rd_Cmp(dbg, upper_blk, a_f, flt_corr, ir_relation_less);
+ cond = new_rd_Cond(dbg, upper_blk, cmp);
+ 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_r_Const(irg, get_mode_null(h_res_mode));
+ in[1] = new_r_Const_long(irg, 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, ia32_mode_E);
+
+ flt_phi = new_r_Phi(lower_blk, 2, in, ia32_mode_E);
+
+ /* fix Phi links for next part_block() */
+ if (is_Phi(int_phi))
+ add_Block_phi(lower_blk, int_phi);
+ if (is_Phi(flt_phi))
+ add_Block_phi(lower_blk, flt_phi);
+
+ 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 = (ir_node*)get_irn_link(call); proj != NULL;
+ proj = (ir_node*)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);
+ }
+
+ return 1;
+}
+
+/* Ia32 implementation of intrinsic mapping. */
+ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
+ const ir_mode *imode, const ir_mode *omode,
+ void *context)