More missing config.h
[libfirm] / ir / be / ia32 / ia32_intrinsics.c
index b3d7c5a..6910d83 100644 (file)
@@ -132,12 +132,12 @@ static int map_Shl(ir_node *call, void *ctx) {
        ir_node  *l_res, *h_res;
 
        /* h_res = SHLD a_h, a_l, cnt */
-       l_res = new_rd_ia32_l_ShlD(dbg, irg, block, a_h, a_l, cnt, l_res_mode);
+       h_res = new_rd_ia32_l_ShlD(dbg, irg, block, a_h, a_l, cnt, l_res_mode);
 
        /* l_res = SHL a_l, cnt */
-       h_res = new_rd_ia32_l_Shl(dbg, irg, block, a_l, cnt, h_res_mode);
+       l_res = new_rd_ia32_l_Shl(dbg, irg, block, a_l, cnt, h_res_mode);
 
-       add_irn_dep(h_res, l_res);
+       add_irn_dep(l_res, h_res);
 
        resolve_call(call, l_res, h_res, irg, block);
        return 1;
@@ -311,10 +311,15 @@ static int map_Abs(ir_node *call, void *ctx) {
        return 1;
 }
 
+typedef enum {
+       IA32_INTRINSIC_DIV,
+       IA32_INTRINSIC_MOD,
+} ia32_intrinsic_divmod_t;
+
 /**
  * Maps a Div/Mod (a_l, a_h, b_l, b_h)
  */
-static int DivMod_mapper(ir_node *call, void *ctx, int need_mod) {
+static int DivMod_mapper(ir_node *call, void *ctx, ia32_intrinsic_divmod_t dmtp) {
        ia32_intrinsic_env_t *env = ctx;
        ir_graph *irg        = current_ir_graph;
        dbg_info *dbg        = get_irn_dbg_info(call);
@@ -328,27 +333,27 @@ static int DivMod_mapper(ir_node *call, void *ctx, int need_mod) {
        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));
        int      mode_bytes  = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode);
-       entity   *ent_a      = env->ll_div_op1;
-       entity   *ent_b      = env->ll_div_op2;
+       entity   *ent_a      = env->irg == irg ? env->ll_div_op1 : NULL;
+       entity   *ent_b      = env->irg == irg ? env->ll_div_op2 : NULL;
        ir_node  *l_res, *h_res, *frame;
        ir_node  *store_l, *store_h;
        ir_node  *op_mem[2], *mem, *fa_mem, *fb_mem;
        ir_node  *fa, *fb, *fres;
-       char     buf[3];
 
        /* allocate memory on frame to store args */
 
        if (! ent_a) {
                ent_a = env->ll_div_op1 =
                        frame_alloc_area(get_irg_frame_type(irg), 2 * mode_bytes, 16, 0);
+               env->irg = irg;
        }
 
        if (! ent_b) {
                ent_b = env->ll_div_op2 =
                        frame_alloc_area(get_irg_frame_type(irg), 2 * mode_bytes, 16, 0);
+               env->irg = irg;
        }
 
-       snprintf(buf, sizeof(buf), "%d", mode_bytes);
        frame = get_irg_frame(irg);
 
        /* store first arg */
@@ -360,7 +365,7 @@ static int DivMod_mapper(ir_node *call, void *ctx, int need_mod) {
 
        store_h   = new_rd_ia32_l_Store(dbg, irg, block, frame, a_h, get_irg_no_mem(irg));
        set_ia32_frame_ent(store_h, ent_a);
-       add_ia32_am_offs(store_h, buf);
+       add_ia32_am_offs_int(store_h, mode_bytes);
        set_ia32_use_frame(store_h);
        set_ia32_ls_mode(store_h, get_irn_mode(a_h));
        op_mem[1] = new_r_Proj(irg, block, store_h, mode_M, pn_ia32_l_Store_M);
@@ -384,7 +389,7 @@ static int DivMod_mapper(ir_node *call, void *ctx, int need_mod) {
 
        store_h   = new_rd_ia32_l_Store(dbg, irg, block, frame, b_h, get_irg_no_mem(irg));
        set_ia32_frame_ent(store_h, ent_b);
-       add_ia32_am_offs(store_h, buf);
+       add_ia32_am_offs_int(store_h, mode_bytes);
        set_ia32_use_frame(store_h);
        set_ia32_ls_mode(store_h, get_irn_mode(b_h));
        op_mem[1] = new_r_Proj(irg, block, store_h, mode_M, pn_ia32_l_Store_M);
@@ -405,13 +410,15 @@ static int DivMod_mapper(ir_node *call, void *ctx, int need_mod) {
        mem = new_r_Sync(irg, block, 2, op_mem);
 
        /* perform division */
-       fres = new_rd_ia32_l_vfdiv(dbg, irg, block, fa, fb, mode_D);
-
-       if (need_mod) {
-               /* we need modulo: mod = a - b * res */
-
-               fres = new_rd_ia32_l_vfmul(dbg, irg, block, fb, fres, mode_D);
-               fres = new_rd_ia32_l_vfsub(dbg, irg, block, fa, fres, mode_D);
+       switch (dmtp) {
+               case IA32_INTRINSIC_DIV:
+                       fres = new_rd_ia32_l_vfdiv(dbg, irg, block, fa, fb, mode_D);
+                       break;
+               case IA32_INTRINSIC_MOD:
+                       fres = new_rd_ia32_l_vfprem(dbg, irg, block, fa, fb, mode_D);
+                       break;
+               default:
+                       assert(0);
        }
 
        /* store back result, we use ent_a here */
@@ -431,7 +438,7 @@ static int DivMod_mapper(ir_node *call, void *ctx, int need_mod) {
        /* load hight part of the result */
        h_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
        set_ia32_frame_ent(h_res, ent_a);
-       add_ia32_am_offs(h_res, buf);
+       add_ia32_am_offs_int(h_res, mode_bytes);
        set_ia32_use_frame(h_res);
        set_ia32_ls_mode(h_res, h_res_mode);
        h_res = new_r_Proj(irg, block, h_res, h_res_mode, pn_ia32_l_Load_res);
@@ -443,11 +450,11 @@ static int DivMod_mapper(ir_node *call, void *ctx, int need_mod) {
 }
 
 static int map_Div(ir_node *call, void *ctx) {
-       return DivMod_mapper(call, ctx, 0);
+       return DivMod_mapper(call, ctx, IA32_INTRINSIC_DIV);
 }
 
 static int map_Mod(ir_node *call, void *ctx) {
-       return DivMod_mapper(call, ctx, 1);
+       return DivMod_mapper(call, ctx, IA32_INTRINSIC_MOD);
 }
 
 /**
@@ -466,7 +473,6 @@ static int map_Conv(ir_node *call, void *ctx) {
        ir_node  *l_res, *h_res, *frame, *fres;
        ir_node  *store_l, *store_h;
        ir_node  *op_mem[2], *mem;
-       char     buf[3];
 
        if (n == 1) {
                /* We have a Conv float -> long long here */
@@ -477,13 +483,13 @@ static int map_Conv(ir_node *call, void *ctx) {
                assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
 
                /* allocate memory on frame to store args */
-               ent = env->d_ll_conv;
+               ent = env->irg == irg ? env->d_ll_conv : NULL;
                if (! ent) {
-                       ent = env->d_ll_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
+                       ent      = env->d_ll_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
+                       env->irg = irg;
                }
 
                /* Store arg */
-               snprintf(buf, sizeof(buf), "%d", gp_bytes);
                frame = get_irg_frame(irg);
 
                /*
@@ -514,7 +520,7 @@ static int map_Conv(ir_node *call, void *ctx) {
                /* load hight part of the result */
                h_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
                set_ia32_frame_ent(h_res, ent);
-               add_ia32_am_offs(h_res, buf);
+               add_ia32_am_offs_int(h_res, gp_bytes);
                set_ia32_use_frame(h_res);
                set_ia32_ls_mode(h_res, h_res_mode);
                h_res = new_r_Proj(irg, block, h_res, h_res_mode, pn_ia32_l_Load_res);
@@ -533,13 +539,13 @@ static int map_Conv(ir_node *call, void *ctx) {
                assert(! mode_is_float(mode_a_l) && ! mode_is_float(mode_a_h) && "unexpected Conv call");
 
                /* allocate memory on frame to store args */
-               ent = env->ll_d_conv;
+               ent = env->irg == irg ? env->ll_d_conv : NULL;
                if (! ent) {
                        ent = env->ll_d_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
+                       env->irg = irg;
                }
 
                /* Store arg */
-               snprintf(buf, sizeof(buf), "%d", gp_bytes);
                frame = get_irg_frame(irg);
 
                /* store first arg (low part) */
@@ -552,7 +558,7 @@ static int map_Conv(ir_node *call, void *ctx) {
                /* store second arg (high part) */
                store_h   = new_rd_ia32_l_Store(dbg, irg, block, frame, a_h, get_irg_no_mem(irg));
                set_ia32_frame_ent(store_h, ent);
-               add_ia32_am_offs(store_h, buf);
+               add_ia32_am_offs_int(store_h, gp_bytes);
                set_ia32_use_frame(store_h);
                set_ia32_ls_mode(store_h, get_irn_mode(a_h));
                op_mem[1] = new_r_Proj(irg, block, store_h, mode_M, pn_ia32_l_Store_M);