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
73 * @param irg the graph to replace on
75 static void reroute_result(ir_node *proj, ir_node *l_res, ir_node *h_res, ir_graph *irg)
77 const ir_edge_t *edge, *next;
79 foreach_out_edge_safe(proj, edge, next) {
80 ir_node *proj = get_edge_src_irn(edge);
81 long pn = get_Proj_proj(proj);
84 edges_reroute(proj, l_res, irg);
85 } else if (pn == 1 && h_res != NULL) {
86 edges_reroute(proj, h_res, irg);
88 panic("Unsupported Result-Proj from Call found");
94 * Replace a call be a tuple of l_res, h_res.
96 * @param call the call node to replace
97 * @param l_res the lower 32 bit result
98 * @param h_res the upper 32 bit result or NULL
99 * @param irg the graph to replace on
100 * @param block the block to replace on (always the call block)
102 static void resolve_call(ir_node *call, ir_node *l_res, ir_node *h_res, ir_graph *irg, ir_node *block)
104 ir_node *jmp, *res, *in[2];
105 ir_node *bad = get_irg_bad(irg);
106 ir_node *nomem = get_irg_no_mem(irg);
109 if (edges_activated(irg)) {
110 /* use rerouting to prevent some warning in the backend */
111 const ir_edge_t *edge, *next;
113 foreach_out_edge_safe(call, edge, next) {
114 ir_node *proj = get_edge_src_irn(edge);
115 pn_Call pn = get_Proj_proj(proj);
118 case pn_Call_X_regular:
120 * We do not check here if this call really has exception and regular Proj's.
121 * new_r_Jmp might than be CSEd with the real exit jmp and then bad things happen
122 * (in movgen.c from 186.crafty for example).
123 * So be sure the newly created Jmp cannot CSE.
125 old_cse = get_opt_cse();
127 jmp = new_r_Jmp(block);
128 set_opt_cse(old_cse);
129 edges_reroute(proj, jmp, irg);
132 case pn_Call_X_except:
133 case pn_Call_P_value_res_base:
134 /* should not happen here */
135 edges_reroute(proj, bad, irg);
138 /* should not happen here */
139 edges_reroute(proj, nomem, irg);
141 case pn_Call_T_result:
142 reroute_result(proj, l_res, h_res, irg);
145 panic("Wrong Proj from Call");
151 /* no edges, build Tuple */
157 res = new_r_Tuple(block, 2, in);
160 turn_into_tuple(call, pn_Call_max);
163 * We do not check here if this call really has exception and regular Proj's.
164 * new_r_Jmp might than be CSEd with the real exit jmp and then bad things happen
165 * (in movgen.c from 186.crafty for example).
166 * So be sure the newly created Jmp cannot CSE.
168 old_cse = get_opt_cse();
170 jmp = new_r_Jmp(block);
171 set_opt_cse(old_cse);
173 set_Tuple_pred(call, pn_Call_M, nomem);
174 set_Tuple_pred(call, pn_Call_X_regular, jmp);
175 set_Tuple_pred(call, pn_Call_X_except, bad);
176 set_Tuple_pred(call, pn_Call_T_result, res);
177 set_Tuple_pred(call, pn_Call_P_value_res_base, bad);
182 * Map an Add (a_l, a_h, b_l, b_h)
184 static int map_Add(ir_node *call, void *ctx)
186 dbg_info *dbg = get_irn_dbg_info(call);
187 ir_node *block = get_nodes_block(call);
188 ir_node **params = get_Call_param_arr(call);
189 ir_type *method = get_Call_type(call);
190 ir_node *a_l = params[BINOP_Left_Low];
191 ir_node *a_h = params[BINOP_Left_High];
192 ir_node *b_l = params[BINOP_Right_Low];
193 ir_node *b_h = params[BINOP_Right_High];
194 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
195 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
196 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
197 ir_node *add_low, *add_high, *flags;
198 ir_node *l_res, *h_res;
201 /* l_res = a_l + b_l */
202 /* h_res = a_h + b_h + carry */
204 add_low = new_bd_ia32_l_Add(dbg, block, a_l, b_l, mode_T);
205 flags = new_r_Proj(add_low, mode_flags, pn_ia32_flags);
206 add_high = new_bd_ia32_l_Adc(dbg, block, a_h, b_h, flags, h_mode);
208 l_res = new_r_Proj(add_low, l_mode, pn_ia32_res);
211 resolve_call(call, l_res, h_res, current_ir_graph, block);
216 * Map a Sub (a_l, a_h, b_l, b_h)
218 static int map_Sub(ir_node *call, void *ctx)
220 dbg_info *dbg = get_irn_dbg_info(call);
221 ir_node *block = get_nodes_block(call);
222 ir_node **params = get_Call_param_arr(call);
223 ir_type *method = get_Call_type(call);
224 ir_node *a_l = params[BINOP_Left_Low];
225 ir_node *a_h = params[BINOP_Left_High];
226 ir_node *b_l = params[BINOP_Right_Low];
227 ir_node *b_h = params[BINOP_Right_High];
228 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
229 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
230 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
231 ir_node *sub_low, *sub_high, *flags;
232 ir_node *l_res, *h_res;
235 /* l_res = a_l - b_l */
236 /* h_res = a_h - b_h - carry */
238 sub_low = new_bd_ia32_l_Sub(dbg, block, a_l, b_l, mode_T);
239 flags = new_r_Proj(sub_low, mode_flags, pn_ia32_flags);
240 sub_high = new_bd_ia32_l_Sbb(dbg, block, a_h, b_h, flags, h_mode);
242 l_res = new_r_Proj(sub_low, l_mode, pn_ia32_res);
245 resolve_call(call, l_res, h_res, current_ir_graph, block);
250 * Map a Shl (a_l, a_h, count)
252 static int map_Shl(ir_node *call, void *ctx)
254 ir_graph *irg = current_ir_graph;
255 dbg_info *dbg = get_irn_dbg_info(call);
256 ir_node *block = get_nodes_block(call);
257 ir_node **params = get_Call_param_arr(call);
258 ir_type *method = get_Call_type(call);
259 ir_node *a_l = params[BINOP_Left_Low];
260 ir_node *a_h = params[BINOP_Left_High];
261 ir_node *cnt = params[BINOP_Right_Low];
262 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
263 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
265 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
269 /* the shift count is a const, create better code */
270 ir_tarval *tv = get_Const_tarval(cnt);
272 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
273 /* simplest case: shift only the lower bits. Note that there is no
274 need to reduce the constant here, this is done by the hardware. */
275 ir_node *conv = new_rd_Conv(dbg, block, a_l, h_mode);
276 h_res = new_rd_Shl(dbg, block, conv, cnt, h_mode);
277 l_res = new_rd_Const(dbg, irg, get_mode_null(l_mode));
280 /* h_res = SHLD a_h, a_l, cnt */
281 h_res = new_bd_ia32_l_ShlD(dbg, block, a_h, a_l, cnt, h_mode);
283 /* l_res = SHL a_l, cnt */
284 l_res = new_bd_ia32_l_ShlDep(dbg, block, a_l, cnt, h_res, l_mode);
287 resolve_call(call, l_res, h_res, irg, block);
292 upper = get_nodes_block(call);
294 /* h_res = SHLD a_h, a_l, cnt */
295 h1 = new_bd_ia32_l_ShlD(dbg, upper, a_h, a_l, cnt, h_mode);
297 /* l_res = SHL a_l, cnt */
298 l1 = new_bd_ia32_l_ShlDep(dbg, upper, a_l, cnt, h1, l_mode);
300 c_mode = get_irn_mode(cnt);
301 irn = new_r_Const_long(irg, c_mode, 32);
302 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
303 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
304 irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
305 cond = new_rd_Cond(dbg, upper, irn);
307 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
308 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
310 /* the block for cnt >= 32 */
311 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
312 h2 = new_rd_Conv(dbg, n_block, l1, h_mode);
313 l2 = new_r_Const(irg, get_mode_null(l_mode));
314 in[1] = new_r_Jmp(n_block);
316 set_irn_in(block, 2, in);
320 l_res = new_r_Phi(block, 2, in, l_mode);
321 set_Block_phis(block, l_res);
325 h_res = new_r_Phi(block, 2, in, h_mode);
326 set_Phi_next(l_res, h_res);
327 set_Phi_next(h_res, NULL);
330 set_nodes_block(call, block);
331 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
332 set_nodes_block(irn, block);
334 resolve_call(call, l_res, h_res, irg, block);
339 * Map a Shr (a_l, a_h, count)
341 static int map_Shr(ir_node *call, void *ctx)
343 ir_graph *irg = current_ir_graph;
344 dbg_info *dbg = get_irn_dbg_info(call);
345 ir_node *block = get_nodes_block(call);
346 ir_node **params = get_Call_param_arr(call);
347 ir_type *method = get_Call_type(call);
348 ir_node *a_l = params[BINOP_Left_Low];
349 ir_node *a_h = params[BINOP_Left_High];
350 ir_node *cnt = params[BINOP_Right_Low];
351 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
352 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
354 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
358 /* the shift count is a const, create better code */
359 ir_tarval *tv = get_Const_tarval(cnt);
361 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
362 /* simplest case: shift only the higher bits. Note that there is no
363 need to reduce the constant here, this is done by the hardware. */
364 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
365 h_res = new_rd_Const(dbg, irg, get_mode_null(h_mode));
366 l_res = new_rd_Shr(dbg, block, conv, cnt, l_mode);
368 /* l_res = SHRD a_h:a_l, cnt */
369 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
371 /* h_res = SHR a_h, cnt */
372 h_res = new_bd_ia32_l_ShrDep(dbg, block, a_h, cnt, l_res, h_mode);
374 resolve_call(call, l_res, h_res, irg, block);
379 upper = get_nodes_block(call);
381 /* l_res = SHRD a_h:a_l, cnt */
382 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
384 /* h_res = SHR a_h, cnt */
385 h1 = new_bd_ia32_l_ShrDep(dbg, upper, a_h, cnt, l1, h_mode);
387 c_mode = get_irn_mode(cnt);
388 irn = new_r_Const_long(irg, c_mode, 32);
389 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
390 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
391 irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
392 cond = new_rd_Cond(dbg, upper, irn);
394 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
395 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
397 /* the block for cnt >= 32 */
398 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
399 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
400 h2 = new_r_Const(irg, get_mode_null(h_mode));
401 in[1] = new_r_Jmp(n_block);
403 set_irn_in(block, 2, in);
407 l_res = new_r_Phi(block, 2, in, l_mode);
408 set_Block_phis(block, l_res);
412 h_res = new_r_Phi(block, 2, in, h_mode);
413 set_Phi_next(l_res, h_res);
414 set_Phi_next(h_res, NULL);
417 set_nodes_block(call, block);
418 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
419 set_nodes_block(irn, block);
421 resolve_call(call, l_res, h_res, irg, block);
426 * Map a Shrs (a_l, a_h, count)
428 static int map_Shrs(ir_node *call, void *ctx)
430 ir_graph *irg = current_ir_graph;
431 dbg_info *dbg = get_irn_dbg_info(call);
432 ir_node *block = get_nodes_block(call);
433 ir_node **params = get_Call_param_arr(call);
434 ir_type *method = get_Call_type(call);
435 ir_node *a_l = params[BINOP_Left_Low];
436 ir_node *a_h = params[BINOP_Left_High];
437 ir_node *cnt = params[BINOP_Right_Low];
438 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
439 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
441 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
445 /* the shift count is a const, create better code */
446 ir_tarval *tv = get_Const_tarval(cnt);
448 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
449 /* simplest case: shift only the higher bits. Note that there is no
450 need to reduce the constant here, this is done by the hardware. */
451 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
452 ir_mode *c_mode = get_irn_mode(cnt);
454 h_res = new_rd_Shrs(dbg, block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
455 l_res = new_rd_Shrs(dbg, block, conv, cnt, l_mode);
457 /* l_res = SHRD a_h:a_l, cnt */
458 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
460 /* h_res = SAR a_h, cnt */
461 h_res = new_bd_ia32_l_SarDep(dbg, block, a_h, cnt, l_res, h_mode);
463 resolve_call(call, l_res, h_res, irg, block);
468 upper = get_nodes_block(call);
470 /* l_res = SHRD a_h:a_l, cnt */
471 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
473 /* h_res = SAR a_h, cnt */
474 h1 = new_bd_ia32_l_SarDep(dbg, upper, a_h, cnt, l1, h_mode);
476 c_mode = get_irn_mode(cnt);
477 irn = new_r_Const_long(irg, c_mode, 32);
478 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
479 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
480 irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
481 cond = new_rd_Cond(dbg, upper, irn);
483 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
484 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
486 /* the block for cnt >= 32 */
487 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
488 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
489 h2 = new_rd_Shrs(dbg, n_block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
490 in[1] = new_r_Jmp(n_block);
492 set_irn_in(block, 2, in);
496 l_res = new_r_Phi(block, 2, in, l_mode);
497 set_Block_phis(block, l_res);
501 h_res = new_r_Phi(block, 2, in, h_mode);
502 set_Phi_next(l_res, h_res);
503 set_Phi_next(h_res, NULL);
506 set_nodes_block(call, block);
507 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
508 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 = 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 = 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);
820 proj = new_r_Proj(cmp, mode_b, pn_Cmp_Lt);
821 cond = new_rd_Cond(dbg, upper_blk, proj);
822 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
823 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
824 blk = new_r_Block(irg, 1, &in[1]);
825 in[1] = new_r_Jmp(blk);
827 set_irn_in(lower_blk, 2, in);
830 in[0] = new_r_Const(irg, get_mode_null(h_res_mode));
831 in[1] = new_r_Const_long(irg, h_res_mode, 0x80000000);
833 int_phi = new_r_Phi(lower_blk, 2, in, h_res_mode);
836 in[1] = new_rd_Sub(dbg, upper_blk, a_f, flt_corr, flt_mode);
838 flt_phi = new_r_Phi(lower_blk, 2, in, flt_mode);
840 /* fix Phi links for next part_block() */
841 set_Block_phis(lower_blk, int_phi);
842 set_Phi_next(int_phi, flt_phi);
843 set_Phi_next(flt_phi, NULL);
845 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi);
847 l_res = new_r_Proj(float_to_ll, l_res_mode,
848 pn_ia32_l_FloattoLL_res_low);
849 h_res = new_r_Proj(float_to_ll, h_res_mode,
850 pn_ia32_l_FloattoLL_res_high);
852 h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, h_res_mode);
854 /* move the call and its Proj's to the lower block */
855 set_nodes_block(call, lower_blk);
857 for (proj = get_irn_link(call); proj != NULL; proj = get_irn_link(proj))
858 set_nodes_block(proj, lower_blk);
862 resolve_call(call, l_res, h_res, irg, block);
864 ir_node *ll_to_float;
866 /* We have a Conv long long -> float here */
867 ir_node *a_l = params[BINOP_Left_Low];
868 ir_node *a_h = params[BINOP_Left_High];
869 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
871 assert(! mode_is_float(get_irn_mode(a_l))
872 && ! mode_is_float(get_irn_mode(a_h)));
874 ll_to_float = new_bd_ia32_l_LLtoFloat(dbg, block, a_h, a_l, fres_mode);
877 resolve_call(call, ll_to_float, NULL, irg, block);
879 panic("unexpected Conv call %+F", call);
885 /* Ia32 implementation of intrinsic mapping. */
886 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
887 const ir_mode *imode, const ir_mode *omode,
891 ir_entity **ent = NULL;
892 i_mapper_func mapper;
895 intrinsics = NEW_ARR_F(i_record, 0);
897 switch (get_op_code(op)) {
899 ent = &i_ents[iro_Add];
903 ent = &i_ents[iro_Sub];
907 ent = &i_ents[iro_Shl];
911 ent = &i_ents[iro_Shr];
915 ent = &i_ents[iro_Shrs];
919 ent = &i_ents[iro_Mul];
923 ent = &i_ents[iro_Minus];
927 ent = &i_ents[iro_Div];
931 ent = &i_ents[iro_Mod];
935 ent = &i_ents[iro_Conv];
939 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
940 return def_create_intrinsic_fkt(method, op, imode, omode, context);
944 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
946 ident *id = id_mangle(IDENT("L"), get_op_ident(op));
947 *ent = new_entity(get_glob_type(), id, method);
948 set_entity_visibility(*ent, ir_visibility_private);
951 elt.i_call.kind = INTRINSIC_CALL;
952 elt.i_call.i_ent = *ent;
953 elt.i_call.i_mapper = mapper;
954 elt.i_call.ctx = context;
955 elt.i_call.link = NULL;
957 ARR_APP1(i_record, intrinsics, elt);