2 * Copyright (C) 1995-2008 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_Last + 1];
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)
56 if (intrinsics && ARR_LEN(intrinsics) > 0) {
57 lower_intrinsics(intrinsics, ARR_LEN(intrinsics), /*part_block_used=*/1);
61 #define BINOP_Left_Low 0
62 #define BINOP_Left_High 1
63 #define BINOP_Right_Low 2
64 #define BINOP_Right_High 3
67 * Reroute edges from the pn_Call_T_result proj of a call.
69 * @param proj the pn_Call_T_result Proj
70 * @param l_res the lower 32 bit result
71 * @param h_res the upper 32 bit result or NULL
72 * @param irg the graph to replace on
74 static void reroute_result(ir_node *proj, ir_node *l_res, ir_node *h_res, ir_graph *irg)
76 const ir_edge_t *edge, *next;
78 foreach_out_edge_safe(proj, edge, next) {
79 ir_node *proj = get_edge_src_irn(edge);
80 long pn = get_Proj_proj(proj);
83 edges_reroute(proj, l_res, irg);
84 } else if (pn == 1 && h_res != NULL) {
85 edges_reroute(proj, h_res, irg);
87 panic("Unsupported Result-Proj from Call found");
93 * Replace a call be a tuple of l_res, h_res.
95 * @param call the call node to replace
96 * @param l_res the lower 32 bit result
97 * @param h_res the upper 32 bit result or NULL
98 * @param irg the graph to replace on
99 * @param block the block to replace on (always the call block)
101 static void resolve_call(ir_node *call, ir_node *l_res, ir_node *h_res, ir_graph *irg, ir_node *block)
103 ir_node *jmp, *res, *in[2];
104 ir_node *bad = get_irg_bad(irg);
105 ir_node *nomem = get_irg_no_mem(irg);
108 if (edges_activated(irg)) {
109 /* use rerouting to prevent some warning in the backend */
110 const ir_edge_t *edge, *next;
112 foreach_out_edge_safe(call, edge, next) {
113 ir_node *proj = get_edge_src_irn(edge);
114 pn_Call pn = get_Proj_proj(proj);
117 case pn_Call_X_regular:
119 * We do not check here if this call really has exception and regular Proj's.
120 * new_r_Jmp might than be CSEd with the real exit jmp and then bad things happen
121 * (in movgen.c from 186.crafty for example).
122 * So be sure the newly created Jmp cannot CSE.
124 old_cse = get_opt_cse();
126 jmp = new_r_Jmp(block);
127 set_opt_cse(old_cse);
128 edges_reroute(proj, jmp, irg);
131 case pn_Call_X_except:
132 case pn_Call_P_value_res_base:
133 /* should not happen here */
134 edges_reroute(proj, bad, irg);
137 /* should not happen here */
138 edges_reroute(proj, nomem, irg);
140 case pn_Call_T_result:
141 reroute_result(proj, l_res, h_res, irg);
144 panic("Wrong Proj from Call");
150 /* no edges, build Tuple */
156 res = new_r_Tuple(block, 2, in);
159 turn_into_tuple(call, pn_Call_max);
162 * We do not check here if this call really has exception and regular Proj's.
163 * new_r_Jmp might than be CSEd with the real exit jmp and then bad things happen
164 * (in movgen.c from 186.crafty for example).
165 * So be sure the newly created Jmp cannot CSE.
167 old_cse = get_opt_cse();
169 jmp = new_r_Jmp(block);
170 set_opt_cse(old_cse);
172 set_Tuple_pred(call, pn_Call_M, nomem);
173 set_Tuple_pred(call, pn_Call_X_regular, jmp);
174 set_Tuple_pred(call, pn_Call_X_except, bad);
175 set_Tuple_pred(call, pn_Call_T_result, res);
176 set_Tuple_pred(call, pn_Call_P_value_res_base, bad);
181 * Map an Add (a_l, a_h, b_l, b_h)
183 static int map_Add(ir_node *call, void *ctx)
185 dbg_info *dbg = get_irn_dbg_info(call);
186 ir_node *block = get_nodes_block(call);
187 ir_node **params = get_Call_param_arr(call);
188 ir_type *method = get_Call_type(call);
189 ir_node *a_l = params[BINOP_Left_Low];
190 ir_node *a_h = params[BINOP_Left_High];
191 ir_node *b_l = params[BINOP_Right_Low];
192 ir_node *b_h = params[BINOP_Right_High];
193 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
194 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
195 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
196 ir_node *add_low, *add_high, *flags;
197 ir_node *l_res, *h_res;
200 /* l_res = a_l + b_l */
201 /* h_res = a_h + b_h + carry */
203 add_low = new_bd_ia32_l_Add(dbg, block, a_l, b_l, mode_T);
204 flags = new_r_Proj(add_low, mode_flags, pn_ia32_flags);
205 add_high = new_bd_ia32_l_Adc(dbg, block, a_h, b_h, flags, h_mode);
207 l_res = new_r_Proj(add_low, l_mode, pn_ia32_res);
210 resolve_call(call, l_res, h_res, current_ir_graph, block);
215 * Map a Sub (a_l, a_h, b_l, b_h)
217 static int map_Sub(ir_node *call, void *ctx)
219 dbg_info *dbg = get_irn_dbg_info(call);
220 ir_node *block = get_nodes_block(call);
221 ir_node **params = get_Call_param_arr(call);
222 ir_type *method = get_Call_type(call);
223 ir_node *a_l = params[BINOP_Left_Low];
224 ir_node *a_h = params[BINOP_Left_High];
225 ir_node *b_l = params[BINOP_Right_Low];
226 ir_node *b_h = params[BINOP_Right_High];
227 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
228 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
229 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
230 ir_node *sub_low, *sub_high, *flags;
231 ir_node *l_res, *h_res;
234 /* l_res = a_l - b_l */
235 /* h_res = a_h - b_h - carry */
237 sub_low = new_bd_ia32_l_Sub(dbg, block, a_l, b_l, mode_T);
238 flags = new_r_Proj(sub_low, mode_flags, pn_ia32_flags);
239 sub_high = new_bd_ia32_l_Sbb(dbg, block, a_h, b_h, flags, h_mode);
241 l_res = new_r_Proj(sub_low, l_mode, pn_ia32_res);
244 resolve_call(call, l_res, h_res, current_ir_graph, block);
249 * Map a Shl (a_l, a_h, count)
251 static int map_Shl(ir_node *call, void *ctx)
253 ir_graph *irg = current_ir_graph;
254 dbg_info *dbg = get_irn_dbg_info(call);
255 ir_node *block = get_nodes_block(call);
256 ir_node **params = get_Call_param_arr(call);
257 ir_type *method = get_Call_type(call);
258 ir_node *a_l = params[BINOP_Left_Low];
259 ir_node *a_h = params[BINOP_Left_High];
260 ir_node *cnt = params[BINOP_Right_Low];
261 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
262 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
264 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
268 /* the shift count is a const, create better code */
269 ir_tarval *tv = get_Const_tarval(cnt);
271 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
272 /* simplest case: shift only the lower bits. Note that there is no
273 need to reduce the constant here, this is done by the hardware. */
274 ir_node *conv = new_rd_Conv(dbg, block, a_l, h_mode);
275 h_res = new_rd_Shl(dbg, block, conv, cnt, h_mode);
276 l_res = new_rd_Const(dbg, irg, get_mode_null(l_mode));
279 /* h_res = SHLD a_h, a_l, cnt */
280 h_res = new_bd_ia32_l_ShlD(dbg, block, a_h, a_l, cnt, h_mode);
282 /* l_res = SHL a_l, cnt */
283 l_res = new_bd_ia32_l_ShlDep(dbg, block, a_l, cnt, h_res, l_mode);
286 resolve_call(call, l_res, h_res, irg, block);
291 upper = get_nodes_block(call);
293 /* h_res = SHLD a_h, a_l, cnt */
294 h1 = new_bd_ia32_l_ShlD(dbg, upper, a_h, a_l, cnt, h_mode);
296 /* l_res = SHL a_l, cnt */
297 l1 = new_bd_ia32_l_ShlDep(dbg, upper, a_l, cnt, h1, l_mode);
299 c_mode = get_irn_mode(cnt);
300 irn = new_r_Const_long(irg, c_mode, 32);
301 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
302 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
303 irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
304 cond = new_rd_Cond(dbg, upper, irn);
306 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
307 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
309 /* the block for cnt >= 32 */
310 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
311 h2 = new_rd_Conv(dbg, n_block, l1, h_mode);
312 l2 = new_r_Const(irg, get_mode_null(l_mode));
313 in[1] = new_r_Jmp(n_block);
315 set_irn_in(block, 2, in);
319 l_res = new_r_Phi(block, 2, in, l_mode);
320 set_Block_phis(block, l_res);
324 h_res = new_r_Phi(block, 2, in, h_mode);
325 set_Phi_next(l_res, h_res);
326 set_Phi_next(h_res, NULL);
329 set_nodes_block(call, block);
330 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
331 set_nodes_block(irn, block);
333 resolve_call(call, l_res, h_res, irg, block);
338 * Map a Shr (a_l, a_h, count)
340 static int map_Shr(ir_node *call, void *ctx)
342 ir_graph *irg = current_ir_graph;
343 dbg_info *dbg = get_irn_dbg_info(call);
344 ir_node *block = get_nodes_block(call);
345 ir_node **params = get_Call_param_arr(call);
346 ir_type *method = get_Call_type(call);
347 ir_node *a_l = params[BINOP_Left_Low];
348 ir_node *a_h = params[BINOP_Left_High];
349 ir_node *cnt = params[BINOP_Right_Low];
350 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
351 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
353 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
357 /* the shift count is a const, create better code */
358 ir_tarval *tv = get_Const_tarval(cnt);
360 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
361 /* simplest case: shift only the higher bits. Note that there is no
362 need to reduce the constant here, this is done by the hardware. */
363 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
364 h_res = new_rd_Const(dbg, irg, get_mode_null(h_mode));
365 l_res = new_rd_Shr(dbg, block, conv, cnt, l_mode);
367 /* l_res = SHRD a_h:a_l, cnt */
368 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
370 /* h_res = SHR a_h, cnt */
371 h_res = new_bd_ia32_l_ShrDep(dbg, block, a_h, cnt, l_res, h_mode);
373 resolve_call(call, l_res, h_res, irg, block);
378 upper = get_nodes_block(call);
380 /* l_res = SHRD a_h:a_l, cnt */
381 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
383 /* h_res = SHR a_h, cnt */
384 h1 = new_bd_ia32_l_ShrDep(dbg, upper, a_h, cnt, l1, h_mode);
386 c_mode = get_irn_mode(cnt);
387 irn = new_r_Const_long(irg, c_mode, 32);
388 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
389 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
390 irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
391 cond = new_rd_Cond(dbg, upper, irn);
393 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
394 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
396 /* the block for cnt >= 32 */
397 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
398 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
399 h2 = new_r_Const(irg, get_mode_null(h_mode));
400 in[1] = new_r_Jmp(n_block);
402 set_irn_in(block, 2, in);
406 l_res = new_r_Phi(block, 2, in, l_mode);
407 set_Block_phis(block, l_res);
411 h_res = new_r_Phi(block, 2, in, h_mode);
412 set_Phi_next(l_res, h_res);
413 set_Phi_next(h_res, NULL);
416 set_nodes_block(call, block);
417 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
418 set_nodes_block(irn, block);
420 resolve_call(call, l_res, h_res, irg, block);
425 * Map a Shrs (a_l, a_h, count)
427 static int map_Shrs(ir_node *call, void *ctx)
429 ir_graph *irg = current_ir_graph;
430 dbg_info *dbg = get_irn_dbg_info(call);
431 ir_node *block = get_nodes_block(call);
432 ir_node **params = get_Call_param_arr(call);
433 ir_type *method = get_Call_type(call);
434 ir_node *a_l = params[BINOP_Left_Low];
435 ir_node *a_h = params[BINOP_Left_High];
436 ir_node *cnt = params[BINOP_Right_Low];
437 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
438 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
440 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
444 /* the shift count is a const, create better code */
445 ir_tarval *tv = get_Const_tarval(cnt);
447 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
448 /* simplest case: shift only the higher bits. Note that there is no
449 need to reduce the constant here, this is done by the hardware. */
450 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
451 ir_mode *c_mode = get_irn_mode(cnt);
453 h_res = new_rd_Shrs(dbg, block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
454 l_res = new_rd_Shrs(dbg, block, conv, cnt, l_mode);
456 /* l_res = SHRD a_h:a_l, cnt */
457 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
459 /* h_res = SAR a_h, cnt */
460 h_res = new_bd_ia32_l_SarDep(dbg, block, a_h, cnt, l_res, h_mode);
462 resolve_call(call, l_res, h_res, irg, block);
467 upper = get_nodes_block(call);
469 /* l_res = SHRD a_h:a_l, cnt */
470 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
472 /* h_res = SAR a_h, cnt */
473 h1 = new_bd_ia32_l_SarDep(dbg, upper, a_h, cnt, l1, h_mode);
475 c_mode = get_irn_mode(cnt);
476 irn = new_r_Const_long(irg, c_mode, 32);
477 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
478 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
479 irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
480 cond = new_rd_Cond(dbg, upper, irn);
482 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
483 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
485 /* the block for cnt >= 32 */
486 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
487 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
488 h2 = new_rd_Shrs(dbg, n_block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
489 in[1] = new_r_Jmp(n_block);
491 set_irn_in(block, 2, in);
495 l_res = new_r_Phi(block, 2, in, l_mode);
496 set_Block_phis(block, l_res);
500 h_res = new_r_Phi(block, 2, in, h_mode);
501 set_Phi_next(l_res, h_res);
502 set_Phi_next(h_res, NULL);
505 set_nodes_block(call, block);
506 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
507 set_nodes_block(irn, block);
509 resolve_call(call, l_res, h_res, irg, block);
514 * Checks where node high is a sign extension of low.
516 static int is_sign_extend(ir_node *low, ir_node *high)
521 ir_tarval *shift_count;
523 high_r = get_Shrs_right(high);
524 if (!is_Const(high_r)) return 0;
526 shift_count = get_Const_tarval(high_r);
527 if (!tarval_is_long(shift_count)) return 0;
528 if (get_tarval_long(shift_count) != 31) return 0;
530 high_l = get_Shrs_left(high);
532 if (is_Conv(low) && get_Conv_op(low) == high_l) return 1;
533 if (is_Conv(high_l) && get_Conv_op(high_l) == low) return 1;
534 } else if (is_Const(low) && is_Const(high)) {
535 ir_tarval *tl = get_Const_tarval(low);
536 ir_tarval *th = get_Const_tarval(high);
538 if (tarval_is_long(th) && tarval_is_long(tl)) {
539 long l = get_tarval_long(tl);
540 long h = get_tarval_long(th);
542 return (h == 0 && l >= 0) || (h == -1 && l < 0);
550 * Map a Mul (a_l, a_h, b_l, b_h)
552 static int map_Mul(ir_node *call, void *ctx)
554 dbg_info *dbg = get_irn_dbg_info(call);
555 ir_node *block = get_nodes_block(call);
556 ir_node **params = get_Call_param_arr(call);
557 ir_type *method = get_Call_type(call);
558 ir_node *a_l = params[BINOP_Left_Low];
559 ir_node *a_h = params[BINOP_Left_High];
560 ir_node *b_l = params[BINOP_Right_Low];
561 ir_node *b_h = params[BINOP_Right_High];
562 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
563 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
564 ir_node *l_res, *h_res, *mul, *pEDX, *add;
577 /* handle the often used case of 32x32=64 mul */
578 if (is_sign_extend(a_l, a_h) && is_sign_extend(b_l, b_h)) {
579 mul = new_bd_ia32_l_IMul(dbg, block, a_l, b_l);
580 h_res = new_rd_Proj(dbg, mul, h_mode, pn_ia32_l_IMul_res_high);
581 l_res = new_rd_Proj(dbg, mul, l_mode, pn_ia32_l_IMul_res_low);
583 /* note that zero extension is handled hare efficiently */
584 mul = new_bd_ia32_l_Mul(dbg, block, a_l, b_l);
585 pEDX = new_rd_Proj(dbg, mul, h_mode, pn_ia32_l_Mul_res_high);
586 l_res = new_rd_Proj(dbg, mul, l_mode, pn_ia32_l_Mul_res_low);
588 b_l = new_rd_Conv(dbg, block, b_l, h_mode);
589 mul = new_rd_Mul( dbg, block, a_h, b_l, h_mode);
590 add = new_rd_Add( dbg, block, mul, pEDX, h_mode);
591 a_l = new_rd_Conv(dbg, block, a_l, h_mode);
592 mul = new_rd_Mul( dbg, block, a_l, b_h, h_mode);
593 h_res = new_rd_Add( dbg, block, add, mul, h_mode);
595 resolve_call(call, l_res, h_res, current_ir_graph, block);
601 * Map a Minus (a_l, a_h)
603 static int map_Minus(ir_node *call, void *ctx)
605 dbg_info *dbg = get_irn_dbg_info(call);
606 ir_node *block = get_nodes_block(call);
607 ir_node **params = get_Call_param_arr(call);
608 ir_type *method = get_Call_type(call);
609 ir_node *a_l = params[BINOP_Left_Low];
610 ir_node *a_h = params[BINOP_Left_High];
611 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
612 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
613 ir_node *l_res, *h_res, *res;
616 res = new_bd_ia32_Minus64Bit(dbg, block, a_l, a_h);
617 l_res = new_r_Proj(res, l_mode, pn_ia32_Minus64Bit_low_res);
618 h_res = new_r_Proj(res, h_mode, pn_ia32_Minus64Bit_high_res);
620 resolve_call(call, l_res, h_res, current_ir_graph, block);
627 * Map a Abs (a_l, a_h)
629 static int map_Abs(ir_node *call, void *ctx)
631 dbg_info *dbg = get_irn_dbg_info(call);
632 ir_node *block = get_nodes_block(call);
633 ir_node **params = get_Call_param_arr(call);
634 ir_type *method = get_Call_type(call);
635 ir_node *a_l = params[BINOP_Left_Low];
636 ir_node *a_h = params[BINOP_Left_High];
637 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
638 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
639 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
640 ir_node *l_res, *h_res, *sign, *sub_l, *sub_h;
647 Code inspired by gcc output :) (although gcc doubles the
648 operation for t1 as t2 and uses t1 for operations with low part
649 and t2 for operations with high part which is actually unnecessary
650 because t1 and t2 represent the same value)
656 h_res = t3 - t1 - carry
660 /* TODO: give a hint to the backend somehow to not create a cltd here... */
661 sign = new_rd_Shrs(dbg, block, a_h, new_r_Const_long(irg, l_mode, 31), h_mode);
662 sign_l = new_rd_Conv(dbg, block, sign, l_mode);
663 sub_l = new_rd_Eor(dbg, block, a_l, sign_l, l_mode);
664 sub_h = new_rd_Eor(dbg, block, a_h, sign, h_mode);
666 l_sub = new_bd_ia32_l_Sub(dbg, block, sub_l, sign_l, mode_T);
667 l_res = new_r_Proj(l_sub, l_mode, pn_ia32_res);
668 flags = new_r_Proj(l_sub, mode_flags, pn_ia32_flags);
669 h_res = new_bd_ia32_l_Sbb(dbg, block, sub_h, sign, flags, h_mode);
671 resolve_call(call, l_res, h_res, current_ir_graph, block);
677 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
680 * Maps a Div. Change into a library call.
682 static int map_Div(ir_node *call, void *ctx)
684 ia32_intrinsic_env_t *env = ctx;
685 ir_type *method = get_Call_type(call);
686 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
689 ir_graph *irg = get_irn_irg(call);
692 if (mode_is_signed(h_mode)) {
693 /* 64bit signed Division */
696 /* create library entity */
697 ent = env->divdi3 = new_entity(get_glob_type(), ID("__divdi3"), method);
698 set_entity_visibility(ent, ir_visibility_external);
699 set_entity_ld_ident(ent, ID("__divdi3"));
702 /* 64bit unsigned Division */
705 /* create library entity */
706 ent = env->udivdi3 = new_entity(get_glob_type(), ID("__udivdi3"), method);
707 set_entity_visibility(ent, ir_visibility_external);
708 set_entity_ld_ident(ent, ID("__udivdi3"));
712 ptr = get_Call_ptr(call);
714 ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
715 set_Call_ptr(call, ptr);
721 * Maps a Mod. Change into a library call
723 static int map_Mod(ir_node *call, void *ctx)
725 ia32_intrinsic_env_t *env = ctx;
726 ir_type *method = get_Call_type(call);
727 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
730 ir_graph *irg = get_irn_irg(call);
733 if (mode_is_signed(h_mode)) {
734 /* 64bit signed Modulo */
737 /* create library entity */
738 ent = env->moddi3 = new_entity(get_glob_type(), ID("__moddi3"), method);
739 set_entity_visibility(ent, ir_visibility_external);
740 set_entity_ld_ident(ent, ID("__moddi3"));
743 /* 64bit signed Modulo */
746 /* create library entity */
747 ent = env->umoddi3 = new_entity(get_glob_type(), ID("__umoddi3"), method);
748 set_entity_visibility(ent, ir_visibility_external);
749 set_entity_ld_ident(ent, ID("__umoddi3"));
753 ptr = get_Call_ptr(call);
755 ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
756 set_Call_ptr(call, ptr);
764 static int map_Conv(ir_node *call, void *ctx)
766 ir_graph *irg = current_ir_graph;
767 dbg_info *dbg = get_irn_dbg_info(call);
768 ir_node *block = get_nodes_block(call);
769 ir_node **params = get_Call_param_arr(call);
770 ir_type *method = get_Call_type(call);
771 int n = get_Call_n_params(call);
772 ir_node *l_res, *h_res;
776 ir_node *float_to_ll;
778 /* We have a Conv float -> long long here */
779 ir_node *a_f = params[0];
780 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
781 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
783 assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
785 if (mode_is_signed(h_res_mode)) {
786 /* convert from float to signed 64bit */
787 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, block, a_f);
789 l_res = new_r_Proj(float_to_ll, l_res_mode,
790 pn_ia32_l_FloattoLL_res_low);
791 h_res = new_r_Proj(float_to_ll, h_res_mode,
792 pn_ia32_l_FloattoLL_res_high);
794 /* convert from float to signed 64bit */
795 ir_mode *flt_mode = get_irn_mode(a_f);
796 ir_tarval *flt_tv = new_tarval_from_str("9223372036854775808", 19, flt_mode);
797 ir_node *flt_corr = new_r_Const(irg, flt_tv);
798 ir_node *lower_blk = block;
800 ir_node *cmp, *proj, *cond, *blk, *int_phi, *flt_phi;
804 upper_blk = get_nodes_block(call);
806 cmp = new_rd_Cmp(dbg, upper_blk, a_f, flt_corr);
807 proj = new_r_Proj(cmp, mode_b, pn_Cmp_Lt);
808 cond = new_rd_Cond(dbg, upper_blk, proj);
809 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
810 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
811 blk = new_r_Block(irg, 1, &in[1]);
812 in[1] = new_r_Jmp(blk);
814 set_irn_in(lower_blk, 2, in);
817 in[0] = new_r_Const(irg, get_mode_null(h_res_mode));
818 in[1] = new_r_Const_long(irg, h_res_mode, 0x80000000);
820 int_phi = new_r_Phi(lower_blk, 2, in, h_res_mode);
823 in[1] = new_rd_Sub(dbg, upper_blk, a_f, flt_corr, flt_mode);
825 flt_phi = new_r_Phi(lower_blk, 2, in, flt_mode);
827 /* fix Phi links for next part_block() */
828 set_Block_phis(lower_blk, int_phi);
829 set_Phi_next(int_phi, flt_phi);
830 set_Phi_next(flt_phi, NULL);
832 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi);
834 l_res = new_r_Proj(float_to_ll, l_res_mode,
835 pn_ia32_l_FloattoLL_res_low);
836 h_res = new_r_Proj(float_to_ll, h_res_mode,
837 pn_ia32_l_FloattoLL_res_high);
839 h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, h_res_mode);
841 /* move the call and its Proj's to the lower block */
842 set_nodes_block(call, lower_blk);
844 for (proj = get_irn_link(call); proj != NULL; proj = get_irn_link(proj))
845 set_nodes_block(proj, lower_blk);
849 resolve_call(call, l_res, h_res, irg, block);
851 ir_node *ll_to_float;
853 /* We have a Conv long long -> float here */
854 ir_node *a_l = params[BINOP_Left_Low];
855 ir_node *a_h = params[BINOP_Left_High];
856 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
858 assert(! mode_is_float(get_irn_mode(a_l))
859 && ! mode_is_float(get_irn_mode(a_h)));
861 ll_to_float = new_bd_ia32_l_LLtoFloat(dbg, block, a_h, a_l, fres_mode);
864 resolve_call(call, ll_to_float, NULL, irg, block);
866 panic("unexpected Conv call %+F", call);
872 /* Ia32 implementation of intrinsic mapping. */
873 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
874 const ir_mode *imode, const ir_mode *omode,
878 ir_entity **ent = NULL;
879 i_mapper_func mapper;
882 intrinsics = NEW_ARR_F(i_record, 0);
884 switch (get_op_code(op)) {
886 ent = &i_ents[iro_Add];
890 ent = &i_ents[iro_Sub];
894 ent = &i_ents[iro_Shl];
898 ent = &i_ents[iro_Shr];
902 ent = &i_ents[iro_Shrs];
906 ent = &i_ents[iro_Mul];
910 ent = &i_ents[iro_Minus];
914 ent = &i_ents[iro_Div];
918 ent = &i_ents[iro_Mod];
922 ent = &i_ents[iro_Conv];
926 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
927 return def_create_intrinsic_fkt(method, op, imode, omode, context);
931 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
933 ident *id = id_mangle(IDENT("L"), get_op_ident(op));
934 *ent = new_entity(get_glob_type(), id, method);
935 set_entity_visibility(*ent, ir_visibility_private);
938 elt.i_call.kind = INTRINSIC_CALL;
939 elt.i_call.i_ent = *ent;
940 elt.i_call.i_mapper = mapper;
941 elt.i_call.ctx = context;
942 elt.i_call.link = NULL;
944 ARR_APP1(i_record, intrinsics, elt);