X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_intrinsics.c;h=85ef7fe3749bef777c35808769819fedb7b58d0b;hb=217290f085a982f29062ff1d7613ca48a88bfbf4;hp=88c02f27fd0dfa170d09da020744d82ecb1ddac6;hpb=ed00af335a4266f1b2573bb0463ec3c7ad39f125;p=libfirm diff --git a/ir/be/ia32/ia32_intrinsics.c b/ir/be/ia32/ia32_intrinsics.c index 88c02f27f..85ef7fe37 100644 --- a/ir/be/ia32/ia32_intrinsics.c +++ b/ir/be/ia32/ia32_intrinsics.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -44,8 +44,8 @@ /** The array of all intrinsics that must be mapped. */ static i_record *intrinsics; -/** An array to cache all entities */ -static ir_entity *i_ents[iro_MaxOpcode]; +/** An array to cache all entities. */ +static ir_entity *i_ents[iro_Last + 1]; /* * Maps all intrinsic calls that the backend support @@ -237,13 +237,13 @@ static int map_Shl(ir_node *call, void *ctx) { in[0] = l1; in[1] = l2; l_res = new_r_Phi(irg, block, 2, in, l_mode); - set_irn_link(block, l_res); + set_Block_phis(block, l_res); in[0] = h1; in[1] = h2; h_res = new_r_Phi(irg, block, 2, in, h_mode); - set_irn_link(l_res, h_res); - set_irn_link(h_res, NULL); + set_Phi_next(l_res, h_res); + set_Phi_next(h_res, NULL); /* move it down */ set_nodes_block(call, block); @@ -315,7 +315,7 @@ static int map_Shr(ir_node *call, void *ctx) { /* the block for cnt >= 32 */ n_block = new_rd_Block(dbg, irg, 1, &in[1]); l2 = new_rd_Conv(dbg, irg, n_block, h1, l_mode); - h2 = new_r_Const(irg, n_block, l_mode, get_mode_null(h_mode)); + h2 = new_r_Const(irg, n_block, h_mode, get_mode_null(h_mode)); in[1] = new_r_Jmp(irg, n_block); set_irn_in(block, 2, in); @@ -323,13 +323,13 @@ static int map_Shr(ir_node *call, void *ctx) { in[0] = l1; in[1] = l2; l_res = new_r_Phi(irg, block, 2, in, l_mode); - set_irn_link(block, l_res); + set_Block_phis(block, l_res); in[0] = h1; in[1] = h2; h_res = new_r_Phi(irg, block, 2, in, h_mode); - set_irn_link(l_res, h_res); - set_irn_link(h_res, NULL); + set_Phi_next(l_res, h_res); + set_Phi_next(h_res, NULL); /* move it down */ set_nodes_block(call, block); @@ -411,13 +411,13 @@ static int map_Shrs(ir_node *call, void *ctx) { in[0] = l1; in[1] = l2; l_res = new_r_Phi(irg, block, 2, in, l_mode); - set_irn_link(block, l_res); + set_Block_phis(block, l_res); in[0] = h1; in[1] = h2; h_res = new_r_Phi(irg, block, 2, in, h_mode); - set_irn_link(l_res, h_res); - set_irn_link(h_res, NULL); + set_Phi_next(l_res, h_res); + set_Phi_next(h_res, NULL); /* move it down */ set_nodes_block(call, block); @@ -634,7 +634,7 @@ static int map_Div(ir_node *call, void *ctx) { 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, 0)); + ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1)); ir_node *ptr; ir_entity *ent; symconst_symbol sym; @@ -668,20 +668,18 @@ static int map_Mod(ir_node *call, void *ctx) { * Maps a Conv. */ static int map_Conv(ir_node *call, void *ctx) { - ia32_intrinsic_env_t *env = 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); - int gp_bytes = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode); - ir_entity *ent; - ir_node *l_res, *h_res, *frame, *fres; - ir_node *store_l, *store_h; - ir_node *op_mem[2], *mem; + 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)); @@ -689,60 +687,18 @@ 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->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); - env->irg = irg; - } + float_to_ll = new_rd_ia32_l_FloattoLL(dbg, irg, block, a_f); - /* Store arg */ - frame = get_irg_frame(irg); - - /* - Now we create a node to move the value from a XMM register into - x87 FPU because it is unknown here, which FPU is used. - This node is killed in transformation phase when not needed. - Otherwise it is split up into a movsd + fld - */ - a_f = new_rd_ia32_l_SSEtoX87(dbg, irg, block, frame, a_f, get_irg_no_mem(irg), mode_D); - set_ia32_frame_ent(a_f, ent); - set_ia32_use_frame(a_f); - set_ia32_ls_mode(a_f, mode_D); - - if (mode_is_signed(h_res_mode)) { - /* a float to signed conv, the simple case */ - - /* store from FPU as Int */ - a_f = new_rd_ia32_l_vfist(dbg, irg, block, frame, a_f, get_irg_no_mem(irg)); - set_ia32_frame_ent(a_f, ent); - set_ia32_use_frame(a_f); - set_ia32_ls_mode(a_f, mode_Ls); - mem = a_f; - - /* load low part of the result */ - l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem); - set_ia32_frame_ent(l_res, ent); - set_ia32_use_frame(l_res); - set_ia32_ls_mode(l_res, l_res_mode); - l_res = new_r_Proj(irg, block, l_res, l_res_mode, pn_ia32_l_Load_res); - - /* 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_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); - } else { - /* a float to unsigned conv, more complicated */ - panic("Float->unsigned64 NYI\n"); - } + l_res = new_r_Proj(irg, block, float_to_ll, l_res_mode, + pn_ia32_l_FloattoLL_res_low); + h_res = new_r_Proj(irg, block, float_to_ll, h_res_mode, + pn_ia32_l_FloattoLL_res_high); /* lower the call */ resolve_call(call, l_res, h_res, irg, block); - } - else if (n == 2) { + } 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]; @@ -751,57 +707,13 @@ static int map_Conv(ir_node *call, void *ctx) { assert(! mode_is_float(get_irn_mode(a_l)) && ! mode_is_float(get_irn_mode(a_h))); - /* allocate memory on frame to store args */ - 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 */ - frame = get_irg_frame(irg); - - /* store first arg (low part) */ - store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, a_l, get_irg_no_mem(irg)); - set_ia32_frame_ent(store_l, ent); - set_ia32_use_frame(store_l); - set_ia32_ls_mode(store_l, get_irn_mode(a_l)); - op_mem[0] = store_l; - - /* 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_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] = store_h; - - mem = new_r_Sync(irg, block, 2, op_mem); - - /* Load arg into x87 FPU (implicit convert) */ - fres = new_rd_ia32_l_vfild(dbg, irg, block, frame, mem); - set_ia32_frame_ent(fres, ent); - set_ia32_use_frame(fres); - set_ia32_ls_mode(fres, mode_D); - mem = new_r_Proj(irg, block, fres, mode_M, pn_ia32_l_vfild_M); - fres = new_r_Proj(irg, block, fres, fres_mode, pn_ia32_l_vfild_res); - - /* - Now we create a node to move the loaded value into a XMM - register because it is unknown here, which FPU is used. - This node is killed in transformation phase when not needed. - Otherwise it is split up into a fst + movsd - */ - fres = new_rd_ia32_l_X87toSSE(dbg, irg, block, frame, fres, mem, fres_mode); - set_ia32_frame_ent(fres, ent); - set_ia32_use_frame(fres); - set_ia32_ls_mode(fres, fres_mode); + ll_to_float = new_rd_ia32_l_LLtoFloat(dbg, irg, block, a_h, a_l, + fres_mode); /* lower the call */ - resolve_call(call, fres, NULL, irg, block); - } - else { - assert(0 && "unexpected Conv call"); + resolve_call(call, ll_to_float, NULL, irg, block); + } else { + panic("unexpected Conv call %+F", call); } return 1;