2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief This file implements the mapping of 64Bit intrinsic
23 * functions to code or library calls.
24 * @author Michael Beck
39 #include "ia32_new_nodes.h"
40 #include "bearch_ia32_t.h"
41 #include "gen_ia32_regalloc_if.h"
43 /** The array of all intrinsics that must be mapped. */
44 static i_record *intrinsics;
46 /** An array to cache all entities */
47 static ir_entity *i_ents[iro_MaxOpcode];
50 * Maps all intrinsic calls that the backend support
51 * and map all instructions the backend did not support
54 void ia32_handle_intrinsics(void) {
55 if (intrinsics && ARR_LEN(intrinsics) > 0)
56 lower_intrinsics(intrinsics, ARR_LEN(intrinsics));
59 #define BINOP_Left_Low 0
60 #define BINOP_Left_High 1
61 #define BINOP_Right_Low 2
62 #define BINOP_Right_High 3
65 * Replace a call be a tuple of l_res, h_res.
67 static void resolve_call(ir_node *call, ir_node *l_res, ir_node *h_res, ir_graph *irg, ir_node *block) {
72 res = new_r_Tuple(irg, block, h_res == NULL ? 1 : 2, in);
74 turn_into_tuple(call, pn_Call_max);
75 set_Tuple_pred(call, pn_Call_M_regular, get_irg_no_mem(irg));
76 set_Tuple_pred(call, pn_Call_X_regular, new_r_Jmp(irg, block));
77 set_Tuple_pred(call, pn_Call_X_except, get_irg_bad(irg));
78 set_Tuple_pred(call, pn_Call_T_result, res);
79 set_Tuple_pred(call, pn_Call_M_except, get_irg_no_mem(irg));
80 set_Tuple_pred(call, pn_Call_P_value_res_base, get_irg_bad(irg));
84 * Map an Add (a_l, a_h, b_l, b_h)
86 static int map_Add(ir_node *call, void *ctx) {
87 ir_graph *irg = current_ir_graph;
88 dbg_info *dbg = get_irn_dbg_info(call);
89 ir_node *block = get_nodes_block(call);
90 ir_node **params = get_Call_param_arr(call);
91 ir_type *method = get_Call_type(call);
92 ir_node *a_l = params[BINOP_Left_Low];
93 ir_node *a_h = params[BINOP_Left_High];
94 ir_node *b_l = params[BINOP_Right_Low];
95 ir_node *b_h = params[BINOP_Right_High];
96 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
97 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
98 ir_node *l_res, *h_res, *add;
101 /* l_res = a_l + b_l */
102 /* h_res = a_h + b_h + carry */
104 add = new_rd_ia32_Add64Bit(dbg, irg, block, a_l, a_h, b_l, b_h);
105 l_res = new_r_Proj(irg, block, add, l_res_mode, pn_ia32_Add64Bit_low_res);
106 h_res = new_r_Proj(irg, block, add, h_res_mode, pn_ia32_Add64Bit_high_res);
108 resolve_call(call, l_res, h_res, irg, block);
113 * Map a Sub (a_l, a_h, b_l, b_h)
115 static int map_Sub(ir_node *call, void *ctx) {
116 ir_graph *irg = current_ir_graph;
117 dbg_info *dbg = get_irn_dbg_info(call);
118 ir_node *block = get_nodes_block(call);
119 ir_node **params = get_Call_param_arr(call);
120 ir_type *method = get_Call_type(call);
121 ir_node *a_l = params[BINOP_Left_Low];
122 ir_node *a_h = params[BINOP_Left_High];
123 ir_node *b_l = params[BINOP_Right_Low];
124 ir_node *b_h = params[BINOP_Right_High];
125 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
126 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
127 ir_node *l_res, *h_res, *res;
130 /* l_res = a_l - b_l */
131 /* h_res = a_h - b_h - carry */
133 res = new_rd_ia32_Sub64Bit(dbg, irg, block, a_l, a_h, b_l, b_h);
134 l_res = new_r_Proj(irg, block, res, l_res_mode, pn_ia32_Sub64Bit_low_res);
135 h_res = new_r_Proj(irg, block, res, h_res_mode, pn_ia32_Sub64Bit_high_res);
137 resolve_call(call, l_res, h_res, irg, block);
142 * Map a Shl (a_l, a_h, count)
144 static int map_Shl(ir_node *call, void *ctx) {
145 ir_graph *irg = current_ir_graph;
146 dbg_info *dbg = get_irn_dbg_info(call);
147 ir_node *block = get_nodes_block(call);
148 ir_node **params = get_Call_param_arr(call);
149 ir_type *method = get_Call_type(call);
150 ir_node *a_l = params[BINOP_Left_Low];
151 ir_node *a_h = params[BINOP_Left_High];
152 ir_node *cnt = params[BINOP_Right_Low];
153 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
154 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
155 ir_node *l_res, *h_res;
158 /* h_res = SHLD a_h, a_l, cnt */
159 h_res = new_rd_ia32_l_ShlD(dbg, irg, block, a_h, a_l, cnt, l_res_mode);
161 /* l_res = SHL a_l, cnt */
162 l_res = new_rd_ia32_l_Shl(dbg, irg, block, a_l, cnt, h_res_mode);
164 //add_irn_dep(l_res, h_res);
166 resolve_call(call, l_res, h_res, irg, block);
171 * Map a Shr (a_l, a_h, count)
173 static int map_Shr(ir_node *call, void *ctx) {
174 ir_graph *irg = current_ir_graph;
175 dbg_info *dbg = get_irn_dbg_info(call);
176 ir_node *block = get_nodes_block(call);
177 ir_node **params = get_Call_param_arr(call);
178 ir_type *method = get_Call_type(call);
179 ir_node *a_l = params[BINOP_Left_Low];
180 ir_node *a_h = params[BINOP_Left_High];
181 ir_node *cnt = params[BINOP_Right_Low];
182 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
183 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
184 ir_node *l_res, *h_res;
187 /* l_res = SHRD a_l, a_h, cnt */
188 l_res = new_rd_ia32_l_ShrD(dbg, irg, block, a_l, a_h, cnt, l_res_mode);
190 /* h_res = SHR a_h, cnt */
191 h_res = new_rd_ia32_l_Shr(dbg, irg, block, a_h, cnt, h_res_mode);
193 //add_irn_dep(h_res, l_res);
195 resolve_call(call, l_res, h_res, irg, block);
200 * Map a Shrs (a_l, a_h, count)
202 static int map_Shrs(ir_node *call, void *ctx) {
203 ir_graph *irg = current_ir_graph;
204 dbg_info *dbg = get_irn_dbg_info(call);
205 ir_node *block = get_nodes_block(call);
206 ir_node **params = get_Call_param_arr(call);
207 ir_type *method = get_Call_type(call);
208 ir_node *a_l = params[BINOP_Left_Low];
209 ir_node *a_h = params[BINOP_Left_High];
210 ir_node *cnt = params[BINOP_Right_Low];
211 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
212 ir_node *l_res, *h_res;
215 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
217 /* l_res = SHRD a_l, a_h, cnt */
218 l_res = new_rd_ia32_l_ShrD(dbg, irg, block, a_l, a_h, cnt, l_mode);
220 /* h_res = SAR a_h, cnt */
221 h_res = new_rd_ia32_l_Sar(dbg, irg, block, a_h, cnt, l_mode);
223 //add_irn_dep(h_res, l_res);
225 resolve_call(call, l_res, h_res, irg, block);
230 * Map a Mul (a_l, a_h, b_l, b_h)
232 static int map_Mul(ir_node *call, void *ctx) {
233 ir_graph *irg = current_ir_graph;
234 dbg_info *dbg = get_irn_dbg_info(call);
235 ir_node *block = get_nodes_block(call);
236 ir_node **params = get_Call_param_arr(call);
237 ir_type *method = get_Call_type(call);
238 ir_node *a_l = params[BINOP_Left_Low];
239 ir_node *a_h = params[BINOP_Left_High];
240 ir_node *b_l = params[BINOP_Right_Low];
241 ir_node *b_h = params[BINOP_Right_High];
242 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
243 ir_node *l_res, *h_res, *mul, *pEDX, *add;
246 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
257 mul = new_rd_ia32_l_Mul(dbg, irg, block, a_l, b_l);
258 pEDX = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EDX);
259 l_res = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EAX);
261 mul = new_rd_Mul(dbg, irg, block, a_h, b_l, l_mode);
262 add = new_rd_Add(dbg, irg, block, mul, pEDX, l_mode);
263 mul = new_rd_Mul(dbg, irg, block, a_l, b_h, l_mode);
264 h_res = new_rd_Add(dbg, irg, block, add, mul, l_mode);
266 resolve_call(call, l_res, h_res, irg, block);
272 * Map a Minus (a_l, a_h)
274 static int map_Minus(ir_node *call, void *ctx) {
275 ir_graph *irg = current_ir_graph;
276 dbg_info *dbg = get_irn_dbg_info(call);
277 ir_node *block = get_nodes_block(call);
278 ir_node **params = get_Call_param_arr(call);
279 ir_type *method = get_Call_type(call);
280 ir_node *a_l = params[BINOP_Left_Low];
281 ir_node *a_h = params[BINOP_Left_High];
282 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
283 ir_node *l_res, *h_res, *cnst, *res;
286 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
288 /* too bad: we need 0 in a register here */
289 cnst = new_Const_long(l_mode, 0);
291 /* l_res = 0 - a_l */
292 /* h_res = 0 - a_h - carry */
294 res = new_rd_ia32_Minus64Bit(dbg, irg, block, cnst, a_l, a_h);
295 l_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Minus64Bit_low_res);
296 h_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Minus64Bit_high_res);
298 resolve_call(call, l_res, h_res, irg, block);
304 * Map a Abs (a_l, a_h)
306 static int map_Abs(ir_node *call, void *ctx) {
307 ir_graph *irg = current_ir_graph;
308 dbg_info *dbg = get_irn_dbg_info(call);
309 ir_node *block = get_nodes_block(call);
310 ir_node **params = get_Call_param_arr(call);
311 ir_type *method = get_Call_type(call);
312 ir_node *a_l = params[BINOP_Left_Low];
313 ir_node *a_h = params[BINOP_Left_High];
314 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
315 ir_node *l_res, *h_res, *sign, *sub_l, *sub_h, *res;
318 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
321 Code inspired by gcc output :) (although gcc doubles the
322 operation for t1 as t2 and uses t1 for operations with low part
323 and t2 for operations with high part which is actually unnecessary
324 because t1 and t2 represent the same value)
330 h_res = t3 - t1 - carry
334 sign = new_rd_ia32_l_Sar(dbg, irg, block, a_h, new_Const_long(l_mode, 31), l_mode);
335 sub_l = new_rd_ia32_l_Xor(dbg, irg, block, a_l, sign, l_mode);
336 sub_h = new_rd_ia32_l_Xor(dbg, irg, block, a_h, sign, l_mode);
337 res = new_rd_ia32_Sub64Bit(dbg, irg, block, sub_l, sub_h, sign, sign);
338 l_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_low_res);
339 h_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_high_res);
341 resolve_call(call, l_res, h_res, irg, block);
349 } ia32_intrinsic_divmod_t;
352 * Maps a Div/Mod (a_l, a_h, b_l, b_h)
354 static int DivMod_mapper(ir_node *call, void *ctx, ia32_intrinsic_divmod_t dmtp) {
355 ia32_intrinsic_env_t *env = ctx;
356 ir_graph *irg = current_ir_graph;
357 dbg_info *dbg = get_irn_dbg_info(call);
358 ir_node *block = get_nodes_block(call);
359 ir_node **params = get_Call_param_arr(call);
360 ir_type *method = get_Call_type(call);
361 ir_node *a_l = params[BINOP_Left_Low];
362 ir_node *a_h = params[BINOP_Left_High];
363 ir_node *b_l = params[BINOP_Right_Low];
364 ir_node *b_h = params[BINOP_Right_High];
365 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
366 int mode_bytes = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode);
367 ir_entity *ent_a = env->irg == irg ? env->ll_div_op1 : NULL;
368 ir_entity *ent_b = env->irg == irg ? env->ll_div_op2 : NULL;
369 ir_node *l_res, *h_res, *frame;
370 ir_node *store_l, *store_h;
371 ir_node *op_mem[2], *mem, *fa_mem, *fb_mem;
372 ir_node *fa, *fb, *fres;
374 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
376 /* allocate memory on frame to store args */
378 ent_a = env->ll_div_op1 =
379 frame_alloc_area(get_irg_frame_type(irg), 2 * mode_bytes, 16, 0);
384 ent_b = env->ll_div_op2 =
385 frame_alloc_area(get_irg_frame_type(irg), 2 * mode_bytes, 16, 0);
389 frame = get_irg_frame(irg);
391 /* store first arg */
392 store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, a_l, get_irg_no_mem(irg));
393 set_ia32_frame_ent(store_l, ent_a);
394 set_ia32_use_frame(store_l);
395 set_ia32_ls_mode(store_l, get_irn_mode(a_l));
398 store_h = new_rd_ia32_l_Store(dbg, irg, block, frame, a_h, get_irg_no_mem(irg));
399 set_ia32_frame_ent(store_h, ent_a);
400 add_ia32_am_offs_int(store_h, mode_bytes);
401 set_ia32_use_frame(store_h);
402 set_ia32_ls_mode(store_h, get_irn_mode(a_h));
405 mem = new_r_Sync(irg, block, 2, op_mem);
407 /* load first arg into FPU */
408 fa = new_rd_ia32_l_vfild(dbg, irg, block, frame, mem);
409 set_ia32_frame_ent(fa, ent_a);
410 set_ia32_use_frame(fa);
411 set_ia32_ls_mode(fa, mode_D);
412 fa_mem = new_r_Proj(irg, block, fa, mode_M, pn_ia32_l_vfild_M);
413 fa = new_r_Proj(irg, block, fa, mode_E, pn_ia32_l_vfild_res);
415 /* store second arg */
416 store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, b_l, get_irg_no_mem(irg));
417 set_ia32_frame_ent(store_l, ent_b);
418 set_ia32_use_frame(store_l);
419 set_ia32_ls_mode(store_l, get_irn_mode(b_l));
422 store_h = new_rd_ia32_l_Store(dbg, irg, block, frame, b_h, get_irg_no_mem(irg));
423 set_ia32_frame_ent(store_h, ent_b);
424 add_ia32_am_offs_int(store_h, mode_bytes);
425 set_ia32_use_frame(store_h);
426 set_ia32_ls_mode(store_h, get_irn_mode(b_h));
429 mem = new_r_Sync(irg, block, 2, op_mem);
431 /* load second arg into FPU */
432 fb = new_rd_ia32_l_vfild(dbg, irg, block, frame, mem);
433 set_ia32_frame_ent(fb, ent_b);
434 set_ia32_use_frame(fb);
435 set_ia32_ls_mode(fb, mode_D);
436 fb_mem = new_r_Proj(irg, block, fb, mode_M, pn_ia32_l_vfild_M);
437 fb = new_r_Proj(irg, block, fb, mode_E, pn_ia32_l_vfild_res);
442 mem = new_r_Sync(irg, block, 2, op_mem);
444 /* perform division */
446 case IA32_INTRINSIC_DIV:
447 fres = new_rd_ia32_l_vfdiv(dbg, irg, block, fa, fb);
448 fres = new_rd_Proj(dbg, irg, block, fres, mode_E, pn_ia32_l_vfdiv_res);
450 case IA32_INTRINSIC_MOD:
451 fres = new_rd_ia32_l_vfprem(dbg, irg, block, fa, fb, mode_E);
457 /* store back result, we use ent_a here */
458 fres = new_rd_ia32_l_vfist(dbg, irg, block, frame, fres, mem);
459 set_ia32_frame_ent(fres, ent_a);
460 set_ia32_use_frame(fres);
461 set_ia32_ls_mode(fres, mode_D);
464 /* load low part of the result */
465 l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
466 set_ia32_frame_ent(l_res, ent_a);
467 set_ia32_use_frame(l_res);
468 set_ia32_ls_mode(l_res, l_mode);
469 l_res = new_r_Proj(irg, block, l_res, l_mode, pn_ia32_l_Load_res);
471 /* load hight part of the result */
472 h_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
473 set_ia32_frame_ent(h_res, ent_a);
474 add_ia32_am_offs_int(h_res, mode_bytes);
475 set_ia32_use_frame(h_res);
476 set_ia32_ls_mode(h_res, l_mode);
477 h_res = new_r_Proj(irg, block, h_res, l_mode, pn_ia32_l_Load_res);
480 resolve_call(call, l_res, h_res, irg, block);
485 static int map_Div(ir_node *call, void *ctx) {
486 return DivMod_mapper(call, ctx, IA32_INTRINSIC_DIV);
489 static int map_Mod(ir_node *call, void *ctx) {
490 return DivMod_mapper(call, ctx, IA32_INTRINSIC_MOD);
494 * Maps a Conv (a_l, a_h)
496 static int map_Conv(ir_node *call, void *ctx) {
497 ia32_intrinsic_env_t *env = ctx;
498 ir_graph *irg = current_ir_graph;
499 dbg_info *dbg = get_irn_dbg_info(call);
500 ir_node *block = get_nodes_block(call);
501 ir_node **params = get_Call_param_arr(call);
502 ir_type *method = get_Call_type(call);
503 int n = get_Call_n_params(call);
504 int gp_bytes = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode);
506 ir_node *l_res, *h_res, *frame, *fres;
507 ir_node *store_l, *store_h;
508 ir_node *op_mem[2], *mem;
511 /* We have a Conv float -> long long here */
512 ir_node *a_f = params[0];
513 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
514 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
516 assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
518 /* allocate memory on frame to store args */
519 ent = env->irg == irg ? env->d_ll_conv : NULL;
521 ent = env->d_ll_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
526 frame = get_irg_frame(irg);
529 Now we create a node to move the value from a XMM register into
530 x87 FPU because it is unknown here, which FPU is used.
531 This node is killed in transformation phase when not needed.
532 Otherwise it is split up into a movsd + fld
534 a_f = new_rd_ia32_l_SSEtoX87(dbg, irg, block, frame, a_f, get_irg_no_mem(irg), mode_D);
535 set_ia32_frame_ent(a_f, ent);
536 set_ia32_use_frame(a_f);
537 set_ia32_ls_mode(a_f, mode_D);
539 /* store from FPU as Int */
540 a_f = new_rd_ia32_l_vfist(dbg, irg, block, frame, a_f, get_irg_no_mem(irg));
541 set_ia32_frame_ent(a_f, ent);
542 set_ia32_use_frame(a_f);
543 set_ia32_ls_mode(a_f, mode_D);
546 /* load low part of the result */
547 l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
548 set_ia32_frame_ent(l_res, ent);
549 set_ia32_use_frame(l_res);
550 set_ia32_ls_mode(l_res, l_res_mode);
551 l_res = new_r_Proj(irg, block, l_res, l_res_mode, pn_ia32_l_Load_res);
553 /* load hight part of the result */
554 h_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
555 set_ia32_frame_ent(h_res, ent);
556 add_ia32_am_offs_int(h_res, gp_bytes);
557 set_ia32_use_frame(h_res);
558 set_ia32_ls_mode(h_res, h_res_mode);
559 h_res = new_r_Proj(irg, block, h_res, h_res_mode, pn_ia32_l_Load_res);
562 resolve_call(call, l_res, h_res, irg, block);
565 /* We have a Conv long long -> float here */
566 ir_node *a_l = params[BINOP_Left_Low];
567 ir_node *a_h = params[BINOP_Left_High];
568 ir_mode *mode_a_l = get_irn_mode(a_l);
569 ir_mode *mode_a_h = get_irn_mode(a_h);
570 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
572 assert(! mode_is_float(mode_a_l) && ! mode_is_float(mode_a_h) && "unexpected Conv call");
574 /* allocate memory on frame to store args */
575 ent = env->irg == irg ? env->ll_d_conv : NULL;
577 ent = env->ll_d_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
582 frame = get_irg_frame(irg);
584 /* store first arg (low part) */
585 store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, a_l, get_irg_no_mem(irg));
586 set_ia32_frame_ent(store_l, ent);
587 set_ia32_use_frame(store_l);
588 set_ia32_ls_mode(store_l, get_irn_mode(a_l));
591 /* store second arg (high part) */
592 store_h = new_rd_ia32_l_Store(dbg, irg, block, frame, a_h, get_irg_no_mem(irg));
593 set_ia32_frame_ent(store_h, ent);
594 add_ia32_am_offs_int(store_h, gp_bytes);
595 set_ia32_use_frame(store_h);
596 set_ia32_ls_mode(store_h, get_irn_mode(a_h));
599 mem = new_r_Sync(irg, block, 2, op_mem);
601 /* Load arg into x87 FPU (implicit convert) */
602 fres = new_rd_ia32_l_vfild(dbg, irg, block, frame, mem);
603 set_ia32_frame_ent(fres, ent);
604 set_ia32_use_frame(fres);
605 set_ia32_ls_mode(fres, mode_D);
606 mem = new_r_Proj(irg, block, fres, mode_M, pn_ia32_l_vfild_M);
607 fres = new_r_Proj(irg, block, fres, fres_mode, pn_ia32_l_vfild_res);
610 Now we create a node to move the loaded value into a XMM
611 register because it is unknown here, which FPU is used.
612 This node is killed in transformation phase when not needed.
613 Otherwise it is split up into a fst + movsd
615 fres = new_rd_ia32_l_X87toSSE(dbg, irg, block, frame, fres, mem, fres_mode);
616 set_ia32_frame_ent(fres, ent);
617 set_ia32_use_frame(fres);
618 set_ia32_ls_mode(fres, fres_mode);
621 resolve_call(call, fres, NULL, irg, block);
624 assert(0 && "unexpected Conv call");
630 /* Ia32 implementation of intrinsic mapping. */
631 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
632 const ir_mode *imode, const ir_mode *omode,
636 ir_entity **ent = NULL;
637 i_mapper_func mapper;
640 intrinsics = NEW_ARR_F(i_record, 0);
642 switch (get_op_code(op)) {
644 ent = &i_ents[iro_Add];
648 ent = &i_ents[iro_Sub];
652 ent = &i_ents[iro_Shl];
656 ent = &i_ents[iro_Shr];
660 ent = &i_ents[iro_Shrs];
664 ent = &i_ents[iro_Mul];
668 ent = &i_ents[iro_Minus];
672 ent = &i_ents[iro_Abs];
676 ent = &i_ents[iro_Div];
680 ent = &i_ents[iro_Mod];
684 ent = &i_ents[iro_Conv];
688 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
689 return def_create_intrinsic_fkt(method, op, imode, omode, context);
693 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
695 ident *id = mangle(IDENT("L"), get_op_ident(op));
696 *ent = new_entity(get_glob_type(), id, method);
699 elt.i_call.kind = INTRINSIC_CALL;
700 elt.i_call.i_ent = *ent;
701 elt.i_call.i_mapper = mapper;
702 elt.i_call.ctx = context;
703 elt.i_call.link = NULL;
705 ARR_APP1(i_record, intrinsics, elt);