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"
44 /** The array of all intrinsics that must be mapped. */
45 static i_record *intrinsics;
47 /** An array to cache all entities. */
48 static ir_entity *i_ents[iro_Last + 1];
51 * Maps all intrinsic calls that the backend support
52 * and map all instructions the backend did not support
55 void ia32_handle_intrinsics(void)
57 if (intrinsics && ARR_LEN(intrinsics) > 0) {
58 lower_intrinsics(intrinsics, ARR_LEN(intrinsics), /*part_block_used=*/1);
62 #define BINOP_Left_Low 0
63 #define BINOP_Left_High 1
64 #define BINOP_Right_Low 2
65 #define BINOP_Right_High 3
68 * Reroute edges from the pn_Call_T_result proj of a call.
70 * @param proj the pn_Call_T_result Proj
71 * @param l_res the lower 32 bit result
72 * @param h_res the upper 32 bit result or NULL
74 static void reroute_result(ir_node *proj, ir_node *l_res, ir_node *h_res)
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);
84 } else if (pn == 1 && h_res != NULL) {
85 edges_reroute(proj, h_res);
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 *nomem = get_irg_no_mem(irg);
107 if (edges_activated(irg)) {
108 /* use rerouting to prevent some warning in the backend */
109 const ir_edge_t *edge, *next;
111 foreach_out_edge_safe(call, edge, next) {
112 ir_node *proj = get_edge_src_irn(edge);
113 pn_Call pn = (pn_Call)get_Proj_proj(proj);
116 case pn_Call_X_regular:
118 * We do not check here if this call really has exception and regular Proj's.
119 * new_r_Jmp might than be CSEd with the real exit jmp and then bad things happen
120 * (in movgen.c from 186.crafty for example).
121 * So be sure the newly created Jmp cannot CSE.
123 old_cse = get_opt_cse();
125 jmp = new_r_Jmp(block);
126 set_opt_cse(old_cse);
127 edges_reroute(proj, jmp);
130 case pn_Call_X_except:
131 /* should not happen here */
132 edges_reroute(proj, new_r_Bad(irg, mode_X));
135 /* should not happen here */
136 edges_reroute(proj, nomem);
138 case pn_Call_T_result:
139 reroute_result(proj, l_res, h_res);
142 panic("Wrong Proj from Call");
148 /* no edges, build Tuple */
154 res = new_r_Tuple(block, 2, in);
157 turn_into_tuple(call, pn_Call_max);
160 * We do not check here if this call really has exception and regular Proj's.
161 * new_r_Jmp might than be CSEd with the real exit jmp and then bad things happen
162 * (in movgen.c from 186.crafty for example).
163 * So be sure the newly created Jmp cannot CSE.
165 old_cse = get_opt_cse();
167 jmp = new_r_Jmp(block);
168 set_opt_cse(old_cse);
170 set_Tuple_pred(call, pn_Call_M, nomem);
171 set_Tuple_pred(call, pn_Call_X_regular, jmp);
172 set_Tuple_pred(call, pn_Call_X_except, new_r_Bad(irg, mode_X));
173 set_Tuple_pred(call, pn_Call_T_result, res);
178 * Map an Add (a_l, a_h, b_l, b_h)
180 static int map_Add(ir_node *call, void *ctx)
182 dbg_info *dbg = get_irn_dbg_info(call);
183 ir_node *block = get_nodes_block(call);
184 ir_node **params = get_Call_param_arr(call);
185 ir_type *method = get_Call_type(call);
186 ir_node *a_l = params[BINOP_Left_Low];
187 ir_node *a_h = params[BINOP_Left_High];
188 ir_node *b_l = params[BINOP_Right_Low];
189 ir_node *b_h = params[BINOP_Right_High];
190 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
191 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
192 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
193 ir_node *add_low, *add_high, *flags;
194 ir_node *l_res, *h_res;
197 /* l_res = a_l + b_l */
198 /* h_res = a_h + b_h + carry */
200 add_low = new_bd_ia32_l_Add(dbg, block, a_l, b_l, mode_T);
201 flags = new_r_Proj(add_low, mode_flags, pn_ia32_flags);
202 add_high = new_bd_ia32_l_Adc(dbg, block, a_h, b_h, flags, h_mode);
204 l_res = new_r_Proj(add_low, l_mode, pn_ia32_res);
207 resolve_call(call, l_res, h_res, current_ir_graph, block);
212 * Map a Sub (a_l, a_h, b_l, b_h)
214 static int map_Sub(ir_node *call, void *ctx)
216 dbg_info *dbg = get_irn_dbg_info(call);
217 ir_node *block = get_nodes_block(call);
218 ir_node **params = get_Call_param_arr(call);
219 ir_type *method = get_Call_type(call);
220 ir_node *a_l = params[BINOP_Left_Low];
221 ir_node *a_h = params[BINOP_Left_High];
222 ir_node *b_l = params[BINOP_Right_Low];
223 ir_node *b_h = params[BINOP_Right_High];
224 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
225 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
226 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
227 ir_node *sub_low, *sub_high, *flags;
228 ir_node *l_res, *h_res;
231 /* l_res = a_l - b_l */
232 /* h_res = a_h - b_h - carry */
234 sub_low = new_bd_ia32_l_Sub(dbg, block, a_l, b_l, mode_T);
235 flags = new_r_Proj(sub_low, mode_flags, pn_ia32_flags);
236 sub_high = new_bd_ia32_l_Sbb(dbg, block, a_h, b_h, flags, h_mode);
238 l_res = new_r_Proj(sub_low, l_mode, pn_ia32_res);
241 resolve_call(call, l_res, h_res, current_ir_graph, block);
246 * Map a Shl (a_l, a_h, count)
248 static int map_Shl(ir_node *call, void *ctx)
250 ir_graph *irg = current_ir_graph;
251 dbg_info *dbg = get_irn_dbg_info(call);
252 ir_node *block = get_nodes_block(call);
253 ir_node **params = get_Call_param_arr(call);
254 ir_type *method = get_Call_type(call);
255 ir_node *a_l = params[BINOP_Left_Low];
256 ir_node *a_h = params[BINOP_Left_High];
257 ir_node *cnt = params[BINOP_Right_Low];
258 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
259 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
261 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
265 /* the shift count is a const, create better code */
266 ir_tarval *tv = get_Const_tarval(cnt);
268 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode))
269 & (ir_relation_greater_equal)) {
270 /* simplest case: shift only the lower bits. Note that there is no
271 need to reduce the constant here, this is done by the hardware. */
272 ir_node *conv = new_rd_Conv(dbg, block, a_l, h_mode);
273 h_res = new_rd_Shl(dbg, block, conv, cnt, h_mode);
274 l_res = new_rd_Const(dbg, irg, get_mode_null(l_mode));
277 /* h_res = SHLD a_h, a_l, cnt */
278 h_res = new_bd_ia32_l_ShlD(dbg, block, a_h, a_l, cnt, h_mode);
280 /* l_res = SHL a_l, cnt */
281 l_res = new_bd_ia32_l_ShlDep(dbg, block, a_l, cnt, h_res, l_mode);
284 resolve_call(call, l_res, h_res, irg, block);
289 upper = get_nodes_block(call);
291 /* h_res = SHLD a_h, a_l, cnt */
292 h1 = new_bd_ia32_l_ShlD(dbg, upper, a_h, a_l, cnt, h_mode);
294 /* l_res = SHL a_l, cnt */
295 l1 = new_bd_ia32_l_ShlDep(dbg, upper, a_l, cnt, h1, l_mode);
297 c_mode = get_irn_mode(cnt);
298 irn = new_r_Const_long(irg, c_mode, 32);
299 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
300 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)), ir_relation_equal);
301 cond = new_rd_Cond(dbg, upper, irn);
303 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
304 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
306 /* the block for cnt >= 32 */
307 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
308 h2 = new_rd_Conv(dbg, n_block, l1, h_mode);
309 l2 = new_r_Const(irg, get_mode_null(l_mode));
310 in[1] = new_r_Jmp(n_block);
312 set_irn_in(block, 2, in);
316 l_res = new_r_Phi(block, 2, in, l_mode);
317 set_Block_phis(block, l_res);
321 h_res = new_r_Phi(block, 2, in, h_mode);
322 set_Phi_next(l_res, h_res);
323 set_Phi_next(h_res, NULL);
326 set_nodes_block(call, block);
327 for (irn = (ir_node*)get_irn_link(call); irn != NULL;
328 irn = (ir_node*)get_irn_link(irn)) {
329 set_nodes_block(irn, block);
332 resolve_call(call, l_res, h_res, irg, block);
337 * Map a Shr (a_l, a_h, count)
339 static int map_Shr(ir_node *call, void *ctx)
341 ir_graph *irg = current_ir_graph;
342 dbg_info *dbg = get_irn_dbg_info(call);
343 ir_node *block = get_nodes_block(call);
344 ir_node **params = get_Call_param_arr(call);
345 ir_type *method = get_Call_type(call);
346 ir_node *a_l = params[BINOP_Left_Low];
347 ir_node *a_h = params[BINOP_Left_High];
348 ir_node *cnt = params[BINOP_Right_Low];
349 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
350 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
352 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
356 /* the shift count is a const, create better code */
357 ir_tarval *tv = get_Const_tarval(cnt);
359 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (ir_relation_greater_equal)) {
360 /* simplest case: shift only the higher bits. Note that there is no
361 need to reduce the constant here, this is done by the hardware. */
362 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
363 h_res = new_rd_Const(dbg, irg, get_mode_null(h_mode));
364 l_res = new_rd_Shr(dbg, block, conv, cnt, l_mode);
366 /* l_res = SHRD a_h:a_l, cnt */
367 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
369 /* h_res = SHR a_h, cnt */
370 h_res = new_bd_ia32_l_ShrDep(dbg, block, a_h, cnt, l_res, h_mode);
372 resolve_call(call, l_res, h_res, irg, block);
377 upper = get_nodes_block(call);
379 /* l_res = SHRD a_h:a_l, cnt */
380 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
382 /* h_res = SHR a_h, cnt */
383 h1 = new_bd_ia32_l_ShrDep(dbg, upper, a_h, cnt, l1, h_mode);
385 c_mode = get_irn_mode(cnt);
386 irn = new_r_Const_long(irg, c_mode, 32);
387 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
388 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)), ir_relation_equal);
389 cond = new_rd_Cond(dbg, upper, irn);
391 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
392 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
394 /* the block for cnt >= 32 */
395 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
396 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
397 h2 = new_r_Const(irg, get_mode_null(h_mode));
398 in[1] = new_r_Jmp(n_block);
400 set_irn_in(block, 2, in);
404 l_res = new_r_Phi(block, 2, in, l_mode);
405 set_Block_phis(block, l_res);
409 h_res = new_r_Phi(block, 2, in, h_mode);
410 set_Phi_next(l_res, h_res);
411 set_Phi_next(h_res, NULL);
414 set_nodes_block(call, block);
415 for (irn = (ir_node*)get_irn_link(call); irn != NULL;
416 irn = (ir_node*)get_irn_link(irn)) {
417 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)) & (ir_relation_greater_equal)) {
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)), ir_relation_equal);
479 cond = new_rd_Cond(dbg, upper, irn);
481 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
482 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
484 /* the block for cnt >= 32 */
485 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
486 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
487 h2 = new_rd_Shrs(dbg, n_block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
488 in[1] = new_r_Jmp(n_block);
490 set_irn_in(block, 2, in);
494 l_res = new_r_Phi(block, 2, in, l_mode);
495 set_Block_phis(block, l_res);
499 h_res = new_r_Phi(block, 2, in, h_mode);
500 set_Phi_next(l_res, h_res);
501 set_Phi_next(h_res, NULL);
504 set_nodes_block(call, block);
505 for (irn = (ir_node*)get_irn_link(call); irn != NULL;
506 irn = (ir_node*)get_irn_link(irn)) {
507 set_nodes_block(irn, block);
510 resolve_call(call, l_res, h_res, irg, block);
515 * Checks where node high is a sign extension of low.
517 static int is_sign_extend(ir_node *low, ir_node *high)
522 ir_tarval *shift_count;
524 high_r = get_Shrs_right(high);
525 if (!is_Const(high_r)) return 0;
527 shift_count = get_Const_tarval(high_r);
528 if (!tarval_is_long(shift_count)) return 0;
529 if (get_tarval_long(shift_count) != 31) return 0;
531 high_l = get_Shrs_left(high);
533 if (is_Conv(low) && get_Conv_op(low) == high_l) return 1;
534 if (is_Conv(high_l) && get_Conv_op(high_l) == low) return 1;
535 } else if (is_Const(low) && is_Const(high)) {
536 ir_tarval *tl = get_Const_tarval(low);
537 ir_tarval *th = get_Const_tarval(high);
539 if (tarval_is_long(th) && tarval_is_long(tl)) {
540 long l = get_tarval_long(tl);
541 long h = get_tarval_long(th);
543 return (h == 0 && l >= 0) || (h == -1 && l < 0);
551 * Map a Mul (a_l, a_h, b_l, b_h)
553 static int map_Mul(ir_node *call, void *ctx)
555 dbg_info *dbg = get_irn_dbg_info(call);
556 ir_node *block = get_nodes_block(call);
557 ir_node **params = get_Call_param_arr(call);
558 ir_type *method = get_Call_type(call);
559 ir_node *a_l = params[BINOP_Left_Low];
560 ir_node *a_h = params[BINOP_Left_High];
561 ir_node *b_l = params[BINOP_Right_Low];
562 ir_node *b_h = params[BINOP_Right_High];
563 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
564 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
565 ir_node *l_res, *h_res, *mul, *pEDX, *add;
578 /* handle the often used case of 32x32=64 mul */
579 if (is_sign_extend(a_l, a_h) && is_sign_extend(b_l, b_h)) {
580 mul = new_bd_ia32_l_IMul(dbg, block, a_l, b_l);
581 h_res = new_rd_Proj(dbg, mul, h_mode, pn_ia32_l_IMul_res_high);
582 l_res = new_rd_Proj(dbg, mul, l_mode, pn_ia32_l_IMul_res_low);
584 /* note that zero extension is handled hare efficiently */
585 mul = new_bd_ia32_l_Mul(dbg, block, a_l, b_l);
586 pEDX = new_rd_Proj(dbg, mul, h_mode, pn_ia32_l_Mul_res_high);
587 l_res = new_rd_Proj(dbg, mul, l_mode, pn_ia32_l_Mul_res_low);
589 b_l = new_rd_Conv(dbg, block, b_l, h_mode);
590 mul = new_rd_Mul( dbg, block, a_h, b_l, h_mode);
591 add = new_rd_Add( dbg, block, mul, pEDX, h_mode);
592 a_l = new_rd_Conv(dbg, block, a_l, h_mode);
593 mul = new_rd_Mul( dbg, block, a_l, b_h, h_mode);
594 h_res = new_rd_Add( dbg, block, add, mul, h_mode);
596 resolve_call(call, l_res, h_res, current_ir_graph, block);
602 * Map a Minus (a_l, a_h)
604 static int map_Minus(ir_node *call, void *ctx)
606 dbg_info *dbg = get_irn_dbg_info(call);
607 ir_node *block = get_nodes_block(call);
608 ir_node **params = get_Call_param_arr(call);
609 ir_type *method = get_Call_type(call);
610 ir_node *a_l = params[BINOP_Left_Low];
611 ir_node *a_h = params[BINOP_Left_High];
612 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
613 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
614 ir_node *l_res, *h_res, *res;
617 res = new_bd_ia32_Minus64Bit(dbg, block, a_l, a_h);
618 l_res = new_r_Proj(res, l_mode, pn_ia32_Minus64Bit_low_res);
619 h_res = new_r_Proj(res, h_mode, pn_ia32_Minus64Bit_high_res);
621 resolve_call(call, l_res, h_res, current_ir_graph, block);
628 * Map a Abs (a_l, a_h)
630 static int map_Abs(ir_node *call, void *ctx)
632 dbg_info *dbg = get_irn_dbg_info(call);
633 ir_node *block = get_nodes_block(call);
634 ir_node **params = get_Call_param_arr(call);
635 ir_type *method = get_Call_type(call);
636 ir_node *a_l = params[BINOP_Left_Low];
637 ir_node *a_h = params[BINOP_Left_High];
638 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
639 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
640 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
641 ir_node *l_res, *h_res, *sign, *sub_l, *sub_h;
648 Code inspired by gcc output :) (although gcc doubles the
649 operation for t1 as t2 and uses t1 for operations with low part
650 and t2 for operations with high part which is actually unnecessary
651 because t1 and t2 represent the same value)
657 h_res = t3 - t1 - carry
661 /* TODO: give a hint to the backend somehow to not create a cltd here... */
662 sign = new_rd_Shrs(dbg, block, a_h, new_r_Const_long(irg, l_mode, 31), h_mode);
663 sign_l = new_rd_Conv(dbg, block, sign, l_mode);
664 sub_l = new_rd_Eor(dbg, block, a_l, sign_l, l_mode);
665 sub_h = new_rd_Eor(dbg, block, a_h, sign, h_mode);
667 l_sub = new_bd_ia32_l_Sub(dbg, block, sub_l, sign_l, mode_T);
668 l_res = new_r_Proj(l_sub, l_mode, pn_ia32_res);
669 flags = new_r_Proj(l_sub, mode_flags, pn_ia32_flags);
670 h_res = new_bd_ia32_l_Sbb(dbg, block, sub_h, sign, flags, h_mode);
672 resolve_call(call, l_res, h_res, current_ir_graph, block);
678 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
680 static ir_entity *create_compiler_lib_entity(const char *name, ir_type *type)
682 ir_type *glob = get_glob_type();
683 ident *id = new_id_from_str(name);
686 /* Hack: we need to know the type of runtime library we use. Strictly
687 speaking it's not the same as the object-file-format. But in practice
688 the following should be enough */
689 if (be_gas_object_file_format == OBJECT_FILE_FORMAT_MACH_O
690 || be_gas_object_file_format == OBJECT_FILE_FORMAT_COFF) {
691 id = id_mangle3("___", id, "");
693 id = id_mangle3("__", id, "");
695 entity = new_entity(glob, id, type);
696 set_entity_visibility(entity, ir_visibility_local);
697 set_entity_ld_ident(entity, id);
702 * Maps a Div. Change into a library call.
704 static int map_Div(ir_node *call, void *ctx)
706 ia32_intrinsic_env_t *env = (ia32_intrinsic_env_t*)ctx;
707 ir_type *method = get_Call_type(call);
708 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
711 ir_graph *irg = get_irn_irg(call);
714 if (mode_is_signed(h_mode)) {
715 /* 64bit signed Division */
718 ent = env->divdi3 = create_compiler_lib_entity("divdi3", method);
721 /* 64bit unsigned Division */
724 /* create library entity */
725 ent = env->udivdi3 = create_compiler_lib_entity("udivdi3", method);
729 ptr = get_Call_ptr(call);
731 ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
732 set_Call_ptr(call, ptr);
738 * Maps a Mod. Change into a library call
740 static int map_Mod(ir_node *call, void *ctx)
742 ia32_intrinsic_env_t *env = (ia32_intrinsic_env_t*)ctx;
743 ir_type *method = get_Call_type(call);
744 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
747 ir_graph *irg = get_irn_irg(call);
750 if (mode_is_signed(h_mode)) {
751 /* 64bit signed Modulo */
754 /* create library entity */
755 ent = env->moddi3 = create_compiler_lib_entity("moddi3", method);
758 /* 64bit signed Modulo */
761 /* create library entity */
762 ent = env->umoddi3 = create_compiler_lib_entity("umoddi3", method);
766 ptr = get_Call_ptr(call);
768 ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
769 set_Call_ptr(call, ptr);
777 static int map_Conv(ir_node *call, void *ctx)
779 ir_graph *irg = current_ir_graph;
780 dbg_info *dbg = get_irn_dbg_info(call);
781 ir_node *block = get_nodes_block(call);
782 ir_node **params = get_Call_param_arr(call);
783 ir_type *method = get_Call_type(call);
784 int n = get_Call_n_params(call);
785 ir_node *l_res, *h_res;
789 ir_node *float_to_ll;
791 /* We have a Conv float -> long long here */
792 ir_node *a_f = params[0];
793 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
794 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
796 assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
798 if (mode_is_signed(h_res_mode)) {
799 /* convert from float to signed 64bit */
800 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, block, a_f);
802 l_res = new_r_Proj(float_to_ll, l_res_mode,
803 pn_ia32_l_FloattoLL_res_low);
804 h_res = new_r_Proj(float_to_ll, h_res_mode,
805 pn_ia32_l_FloattoLL_res_high);
807 /* convert from float to signed 64bit */
808 ir_mode *flt_mode = get_irn_mode(a_f);
809 ir_tarval *flt_tv = new_tarval_from_str("9223372036854775808", 19, flt_mode);
810 ir_node *flt_corr = new_r_Const(irg, flt_tv);
811 ir_node *lower_blk = block;
813 ir_node *cmp, *proj, *cond, *blk, *int_phi, *flt_phi;
817 upper_blk = get_nodes_block(call);
819 cmp = new_rd_Cmp(dbg, upper_blk, a_f, flt_corr, ir_relation_less);
820 cond = new_rd_Cond(dbg, upper_blk, cmp);
821 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
822 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
823 blk = new_r_Block(irg, 1, &in[1]);
824 in[1] = new_r_Jmp(blk);
826 set_irn_in(lower_blk, 2, in);
829 in[0] = new_r_Const(irg, get_mode_null(h_res_mode));
830 in[1] = new_r_Const_long(irg, h_res_mode, 0x80000000);
832 int_phi = new_r_Phi(lower_blk, 2, in, h_res_mode);
835 in[1] = new_rd_Sub(dbg, upper_blk, a_f, flt_corr, flt_mode);
837 flt_phi = new_r_Phi(lower_blk, 2, in, flt_mode);
839 /* fix Phi links for next part_block() */
840 set_Block_phis(lower_blk, int_phi);
841 set_Phi_next(int_phi, flt_phi);
842 set_Phi_next(flt_phi, NULL);
844 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi);
846 l_res = new_r_Proj(float_to_ll, l_res_mode,
847 pn_ia32_l_FloattoLL_res_low);
848 h_res = new_r_Proj(float_to_ll, h_res_mode,
849 pn_ia32_l_FloattoLL_res_high);
851 h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, h_res_mode);
853 /* move the call and its Proj's to the lower block */
854 set_nodes_block(call, lower_blk);
856 for (proj = (ir_node*)get_irn_link(call); proj != NULL;
857 proj = (ir_node*)get_irn_link(proj)) {
858 set_nodes_block(proj, lower_blk);
863 resolve_call(call, l_res, h_res, irg, block);
865 ir_node *ll_to_float;
867 /* We have a Conv long long -> float here */
868 ir_node *a_l = params[BINOP_Left_Low];
869 ir_node *a_h = params[BINOP_Left_High];
870 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
872 assert(! mode_is_float(get_irn_mode(a_l))
873 && ! mode_is_float(get_irn_mode(a_h)));
875 ll_to_float = new_bd_ia32_l_LLtoFloat(dbg, block, a_h, a_l, fres_mode);
878 resolve_call(call, ll_to_float, NULL, irg, block);
880 panic("unexpected Conv call %+F", call);
886 /* Ia32 implementation of intrinsic mapping. */
887 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
888 const ir_mode *imode, const ir_mode *omode,
892 ir_entity **ent = NULL;
893 i_mapper_func mapper;
896 intrinsics = NEW_ARR_F(i_record, 0);
898 switch (get_op_code(op)) {
900 ent = &i_ents[iro_Add];
904 ent = &i_ents[iro_Sub];
908 ent = &i_ents[iro_Shl];
912 ent = &i_ents[iro_Shr];
916 ent = &i_ents[iro_Shrs];
920 ent = &i_ents[iro_Mul];
924 ent = &i_ents[iro_Minus];
928 ent = &i_ents[iro_Div];
932 ent = &i_ents[iro_Mod];
936 ent = &i_ents[iro_Conv];
940 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
941 return def_create_intrinsic_fkt(method, op, imode, omode, context);
945 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
947 ident *id = id_mangle(IDENT("L"), get_op_ident(op));
948 *ent = new_entity(get_glob_type(), id, method);
949 set_entity_visibility(*ent, ir_visibility_private);
952 elt.i_call.kind = INTRINSIC_CALL;
953 elt.i_call.i_ent = *ent;
954 elt.i_call.i_mapper = mapper;
955 elt.i_call.ctx = context;
956 elt.i_call.link = NULL;
958 ARR_APP1(i_record, intrinsics, elt);