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 = (pn_Call)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))
273 & (ir_relation_greater_equal)) {
274 /* simplest case: shift only the lower bits. Note that there is no
275 need to reduce the constant here, this is done by the hardware. */
276 ir_node *conv = new_rd_Conv(dbg, block, a_l, h_mode);
277 h_res = new_rd_Shl(dbg, block, conv, cnt, h_mode);
278 l_res = new_rd_Const(dbg, irg, get_mode_null(l_mode));
281 /* h_res = SHLD a_h, a_l, cnt */
282 h_res = new_bd_ia32_l_ShlD(dbg, block, a_h, a_l, cnt, h_mode);
284 /* l_res = SHL a_l, cnt */
285 l_res = new_bd_ia32_l_ShlDep(dbg, block, a_l, cnt, h_res, l_mode);
288 resolve_call(call, l_res, h_res, irg, block);
293 upper = get_nodes_block(call);
295 /* h_res = SHLD a_h, a_l, cnt */
296 h1 = new_bd_ia32_l_ShlD(dbg, upper, a_h, a_l, cnt, h_mode);
298 /* l_res = SHL a_l, cnt */
299 l1 = new_bd_ia32_l_ShlDep(dbg, upper, a_l, cnt, h1, l_mode);
301 c_mode = get_irn_mode(cnt);
302 irn = new_r_Const_long(irg, c_mode, 32);
303 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
304 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)), ir_relation_equal);
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 = (ir_node*)get_irn_link(call); irn != NULL;
332 irn = (ir_node*)get_irn_link(irn)) {
333 set_nodes_block(irn, block);
336 resolve_call(call, l_res, h_res, irg, block);
341 * Map a Shr (a_l, a_h, count)
343 static int map_Shr(ir_node *call, void *ctx)
345 ir_graph *irg = current_ir_graph;
346 dbg_info *dbg = get_irn_dbg_info(call);
347 ir_node *block = get_nodes_block(call);
348 ir_node **params = get_Call_param_arr(call);
349 ir_type *method = get_Call_type(call);
350 ir_node *a_l = params[BINOP_Left_Low];
351 ir_node *a_h = params[BINOP_Left_High];
352 ir_node *cnt = params[BINOP_Right_Low];
353 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
354 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
356 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
360 /* the shift count is a const, create better code */
361 ir_tarval *tv = get_Const_tarval(cnt);
363 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (ir_relation_greater_equal)) {
364 /* simplest case: shift only the higher bits. Note that there is no
365 need to reduce the constant here, this is done by the hardware. */
366 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
367 h_res = new_rd_Const(dbg, irg, get_mode_null(h_mode));
368 l_res = new_rd_Shr(dbg, block, conv, cnt, l_mode);
370 /* l_res = SHRD a_h:a_l, cnt */
371 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
373 /* h_res = SHR a_h, cnt */
374 h_res = new_bd_ia32_l_ShrDep(dbg, block, a_h, cnt, l_res, h_mode);
376 resolve_call(call, l_res, h_res, irg, block);
381 upper = get_nodes_block(call);
383 /* l_res = SHRD a_h:a_l, cnt */
384 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
386 /* h_res = SHR a_h, cnt */
387 h1 = new_bd_ia32_l_ShrDep(dbg, upper, a_h, cnt, l1, h_mode);
389 c_mode = get_irn_mode(cnt);
390 irn = new_r_Const_long(irg, c_mode, 32);
391 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
392 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)), ir_relation_equal);
393 cond = new_rd_Cond(dbg, upper, irn);
395 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
396 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
398 /* the block for cnt >= 32 */
399 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
400 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
401 h2 = new_r_Const(irg, get_mode_null(h_mode));
402 in[1] = new_r_Jmp(n_block);
404 set_irn_in(block, 2, in);
408 l_res = new_r_Phi(block, 2, in, l_mode);
409 set_Block_phis(block, l_res);
413 h_res = new_r_Phi(block, 2, in, h_mode);
414 set_Phi_next(l_res, h_res);
415 set_Phi_next(h_res, NULL);
418 set_nodes_block(call, block);
419 for (irn = (ir_node*)get_irn_link(call); irn != NULL;
420 irn = (ir_node*)get_irn_link(irn)) {
421 set_nodes_block(irn, block);
424 resolve_call(call, l_res, h_res, irg, block);
429 * Map a Shrs (a_l, a_h, count)
431 static int map_Shrs(ir_node *call, void *ctx)
433 ir_graph *irg = current_ir_graph;
434 dbg_info *dbg = get_irn_dbg_info(call);
435 ir_node *block = get_nodes_block(call);
436 ir_node **params = get_Call_param_arr(call);
437 ir_type *method = get_Call_type(call);
438 ir_node *a_l = params[BINOP_Left_Low];
439 ir_node *a_h = params[BINOP_Left_High];
440 ir_node *cnt = params[BINOP_Right_Low];
441 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
442 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
444 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
448 /* the shift count is a const, create better code */
449 ir_tarval *tv = get_Const_tarval(cnt);
451 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (ir_relation_greater_equal)) {
452 /* simplest case: shift only the higher bits. Note that there is no
453 need to reduce the constant here, this is done by the hardware. */
454 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
455 ir_mode *c_mode = get_irn_mode(cnt);
457 h_res = new_rd_Shrs(dbg, block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
458 l_res = new_rd_Shrs(dbg, block, conv, cnt, l_mode);
460 /* l_res = SHRD a_h:a_l, cnt */
461 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
463 /* h_res = SAR a_h, cnt */
464 h_res = new_bd_ia32_l_SarDep(dbg, block, a_h, cnt, l_res, h_mode);
466 resolve_call(call, l_res, h_res, irg, block);
471 upper = get_nodes_block(call);
473 /* l_res = SHRD a_h:a_l, cnt */
474 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
476 /* h_res = SAR a_h, cnt */
477 h1 = new_bd_ia32_l_SarDep(dbg, upper, a_h, cnt, l1, h_mode);
479 c_mode = get_irn_mode(cnt);
480 irn = new_r_Const_long(irg, c_mode, 32);
481 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
482 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)), ir_relation_equal);
483 cond = new_rd_Cond(dbg, upper, irn);
485 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
486 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
488 /* the block for cnt >= 32 */
489 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
490 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
491 h2 = new_rd_Shrs(dbg, n_block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
492 in[1] = new_r_Jmp(n_block);
494 set_irn_in(block, 2, in);
498 l_res = new_r_Phi(block, 2, in, l_mode);
499 set_Block_phis(block, l_res);
503 h_res = new_r_Phi(block, 2, in, h_mode);
504 set_Phi_next(l_res, h_res);
505 set_Phi_next(h_res, NULL);
508 set_nodes_block(call, block);
509 for (irn = (ir_node*)get_irn_link(call); irn != NULL;
510 irn = (ir_node*)get_irn_link(irn)) {
511 set_nodes_block(irn, block);
514 resolve_call(call, l_res, h_res, irg, block);
519 * Checks where node high is a sign extension of low.
521 static int is_sign_extend(ir_node *low, ir_node *high)
526 ir_tarval *shift_count;
528 high_r = get_Shrs_right(high);
529 if (!is_Const(high_r)) return 0;
531 shift_count = get_Const_tarval(high_r);
532 if (!tarval_is_long(shift_count)) return 0;
533 if (get_tarval_long(shift_count) != 31) return 0;
535 high_l = get_Shrs_left(high);
537 if (is_Conv(low) && get_Conv_op(low) == high_l) return 1;
538 if (is_Conv(high_l) && get_Conv_op(high_l) == low) return 1;
539 } else if (is_Const(low) && is_Const(high)) {
540 ir_tarval *tl = get_Const_tarval(low);
541 ir_tarval *th = get_Const_tarval(high);
543 if (tarval_is_long(th) && tarval_is_long(tl)) {
544 long l = get_tarval_long(tl);
545 long h = get_tarval_long(th);
547 return (h == 0 && l >= 0) || (h == -1 && l < 0);
555 * Map a Mul (a_l, a_h, b_l, b_h)
557 static int map_Mul(ir_node *call, void *ctx)
559 dbg_info *dbg = get_irn_dbg_info(call);
560 ir_node *block = get_nodes_block(call);
561 ir_node **params = get_Call_param_arr(call);
562 ir_type *method = get_Call_type(call);
563 ir_node *a_l = params[BINOP_Left_Low];
564 ir_node *a_h = params[BINOP_Left_High];
565 ir_node *b_l = params[BINOP_Right_Low];
566 ir_node *b_h = params[BINOP_Right_High];
567 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
568 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
569 ir_node *l_res, *h_res, *mul, *pEDX, *add;
582 /* handle the often used case of 32x32=64 mul */
583 if (is_sign_extend(a_l, a_h) && is_sign_extend(b_l, b_h)) {
584 mul = new_bd_ia32_l_IMul(dbg, block, a_l, b_l);
585 h_res = new_rd_Proj(dbg, mul, h_mode, pn_ia32_l_IMul_res_high);
586 l_res = new_rd_Proj(dbg, mul, l_mode, pn_ia32_l_IMul_res_low);
588 /* note that zero extension is handled hare efficiently */
589 mul = new_bd_ia32_l_Mul(dbg, block, a_l, b_l);
590 pEDX = new_rd_Proj(dbg, mul, h_mode, pn_ia32_l_Mul_res_high);
591 l_res = new_rd_Proj(dbg, mul, l_mode, pn_ia32_l_Mul_res_low);
593 b_l = new_rd_Conv(dbg, block, b_l, h_mode);
594 mul = new_rd_Mul( dbg, block, a_h, b_l, h_mode);
595 add = new_rd_Add( dbg, block, mul, pEDX, h_mode);
596 a_l = new_rd_Conv(dbg, block, a_l, h_mode);
597 mul = new_rd_Mul( dbg, block, a_l, b_h, h_mode);
598 h_res = new_rd_Add( dbg, block, add, mul, h_mode);
600 resolve_call(call, l_res, h_res, current_ir_graph, block);
606 * Map a Minus (a_l, a_h)
608 static int map_Minus(ir_node *call, void *ctx)
610 dbg_info *dbg = get_irn_dbg_info(call);
611 ir_node *block = get_nodes_block(call);
612 ir_node **params = get_Call_param_arr(call);
613 ir_type *method = get_Call_type(call);
614 ir_node *a_l = params[BINOP_Left_Low];
615 ir_node *a_h = params[BINOP_Left_High];
616 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
617 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
618 ir_node *l_res, *h_res, *res;
621 res = new_bd_ia32_Minus64Bit(dbg, block, a_l, a_h);
622 l_res = new_r_Proj(res, l_mode, pn_ia32_Minus64Bit_low_res);
623 h_res = new_r_Proj(res, h_mode, pn_ia32_Minus64Bit_high_res);
625 resolve_call(call, l_res, h_res, current_ir_graph, block);
632 * Map a Abs (a_l, a_h)
634 static int map_Abs(ir_node *call, void *ctx)
636 dbg_info *dbg = get_irn_dbg_info(call);
637 ir_node *block = get_nodes_block(call);
638 ir_node **params = get_Call_param_arr(call);
639 ir_type *method = get_Call_type(call);
640 ir_node *a_l = params[BINOP_Left_Low];
641 ir_node *a_h = params[BINOP_Left_High];
642 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
643 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
644 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
645 ir_node *l_res, *h_res, *sign, *sub_l, *sub_h;
652 Code inspired by gcc output :) (although gcc doubles the
653 operation for t1 as t2 and uses t1 for operations with low part
654 and t2 for operations with high part which is actually unnecessary
655 because t1 and t2 represent the same value)
661 h_res = t3 - t1 - carry
665 /* TODO: give a hint to the backend somehow to not create a cltd here... */
666 sign = new_rd_Shrs(dbg, block, a_h, new_r_Const_long(irg, l_mode, 31), h_mode);
667 sign_l = new_rd_Conv(dbg, block, sign, l_mode);
668 sub_l = new_rd_Eor(dbg, block, a_l, sign_l, l_mode);
669 sub_h = new_rd_Eor(dbg, block, a_h, sign, h_mode);
671 l_sub = new_bd_ia32_l_Sub(dbg, block, sub_l, sign_l, mode_T);
672 l_res = new_r_Proj(l_sub, l_mode, pn_ia32_res);
673 flags = new_r_Proj(l_sub, mode_flags, pn_ia32_flags);
674 h_res = new_bd_ia32_l_Sbb(dbg, block, sub_h, sign, flags, h_mode);
676 resolve_call(call, l_res, h_res, current_ir_graph, block);
682 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
684 static ir_entity *create_compiler_lib_entity(const char *name, ir_type *type)
686 ir_type *glob = get_glob_type();
687 ident *id = new_id_from_str(name);
690 /* Hack: we need to know the type of runtime library we use. Strictly
691 speaking it's not the same as the object-file-format. But in practice
692 the following should be enough */
693 if (be_gas_object_file_format == OBJECT_FILE_FORMAT_MACH_O
694 || be_gas_object_file_format == OBJECT_FILE_FORMAT_COFF) {
695 id = id_mangle3("___", id, "");
697 id = id_mangle3("__", id, "");
699 entity = new_entity(glob, id, type);
700 set_entity_visibility(entity, ir_visibility_local);
701 set_entity_ld_ident(entity, id);
706 * Maps a Div. Change into a library call.
708 static int map_Div(ir_node *call, void *ctx)
710 ia32_intrinsic_env_t *env = (ia32_intrinsic_env_t*)ctx;
711 ir_type *method = get_Call_type(call);
712 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
715 ir_graph *irg = get_irn_irg(call);
718 if (mode_is_signed(h_mode)) {
719 /* 64bit signed Division */
722 ent = env->divdi3 = create_compiler_lib_entity("divdi3", method);
725 /* 64bit unsigned Division */
728 /* create library entity */
729 ent = env->udivdi3 = create_compiler_lib_entity("udivdi3", method);
733 ptr = get_Call_ptr(call);
735 ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
736 set_Call_ptr(call, ptr);
742 * Maps a Mod. Change into a library call
744 static int map_Mod(ir_node *call, void *ctx)
746 ia32_intrinsic_env_t *env = (ia32_intrinsic_env_t*)ctx;
747 ir_type *method = get_Call_type(call);
748 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
751 ir_graph *irg = get_irn_irg(call);
754 if (mode_is_signed(h_mode)) {
755 /* 64bit signed Modulo */
758 /* create library entity */
759 ent = env->moddi3 = create_compiler_lib_entity("moddi3", method);
762 /* 64bit signed Modulo */
765 /* create library entity */
766 ent = env->umoddi3 = create_compiler_lib_entity("umoddi3", method);
770 ptr = get_Call_ptr(call);
772 ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
773 set_Call_ptr(call, ptr);
781 static int map_Conv(ir_node *call, void *ctx)
783 ir_graph *irg = current_ir_graph;
784 dbg_info *dbg = get_irn_dbg_info(call);
785 ir_node *block = get_nodes_block(call);
786 ir_node **params = get_Call_param_arr(call);
787 ir_type *method = get_Call_type(call);
788 int n = get_Call_n_params(call);
789 ir_node *l_res, *h_res;
793 ir_node *float_to_ll;
795 /* We have a Conv float -> long long here */
796 ir_node *a_f = params[0];
797 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
798 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
800 assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
802 if (mode_is_signed(h_res_mode)) {
803 /* convert from float to signed 64bit */
804 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, block, a_f);
806 l_res = new_r_Proj(float_to_ll, l_res_mode,
807 pn_ia32_l_FloattoLL_res_low);
808 h_res = new_r_Proj(float_to_ll, h_res_mode,
809 pn_ia32_l_FloattoLL_res_high);
811 /* convert from float to signed 64bit */
812 ir_mode *flt_mode = get_irn_mode(a_f);
813 ir_tarval *flt_tv = new_tarval_from_str("9223372036854775808", 19, flt_mode);
814 ir_node *flt_corr = new_r_Const(irg, flt_tv);
815 ir_node *lower_blk = block;
817 ir_node *cmp, *proj, *cond, *blk, *int_phi, *flt_phi;
821 upper_blk = get_nodes_block(call);
823 cmp = new_rd_Cmp(dbg, upper_blk, a_f, flt_corr, ir_relation_less);
824 cond = new_rd_Cond(dbg, upper_blk, cmp);
825 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
826 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
827 blk = new_r_Block(irg, 1, &in[1]);
828 in[1] = new_r_Jmp(blk);
830 set_irn_in(lower_blk, 2, in);
833 in[0] = new_r_Const(irg, get_mode_null(h_res_mode));
834 in[1] = new_r_Const_long(irg, h_res_mode, 0x80000000);
836 int_phi = new_r_Phi(lower_blk, 2, in, h_res_mode);
839 in[1] = new_rd_Sub(dbg, upper_blk, a_f, flt_corr, flt_mode);
841 flt_phi = new_r_Phi(lower_blk, 2, in, flt_mode);
843 /* fix Phi links for next part_block() */
844 set_Block_phis(lower_blk, int_phi);
845 set_Phi_next(int_phi, flt_phi);
846 set_Phi_next(flt_phi, NULL);
848 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi);
850 l_res = new_r_Proj(float_to_ll, l_res_mode,
851 pn_ia32_l_FloattoLL_res_low);
852 h_res = new_r_Proj(float_to_ll, h_res_mode,
853 pn_ia32_l_FloattoLL_res_high);
855 h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, h_res_mode);
857 /* move the call and its Proj's to the lower block */
858 set_nodes_block(call, lower_blk);
860 for (proj = (ir_node*)get_irn_link(call); proj != NULL;
861 proj = (ir_node*)get_irn_link(proj)) {
862 set_nodes_block(proj, lower_blk);
867 resolve_call(call, l_res, h_res, irg, block);
869 ir_node *ll_to_float;
871 /* We have a Conv long long -> float here */
872 ir_node *a_l = params[BINOP_Left_Low];
873 ir_node *a_h = params[BINOP_Left_High];
874 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
876 assert(! mode_is_float(get_irn_mode(a_l))
877 && ! mode_is_float(get_irn_mode(a_h)));
879 ll_to_float = new_bd_ia32_l_LLtoFloat(dbg, block, a_h, a_l, fres_mode);
882 resolve_call(call, ll_to_float, NULL, irg, block);
884 panic("unexpected Conv call %+F", call);
890 /* Ia32 implementation of intrinsic mapping. */
891 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
892 const ir_mode *imode, const ir_mode *omode,
896 ir_entity **ent = NULL;
897 i_mapper_func mapper;
900 intrinsics = NEW_ARR_F(i_record, 0);
902 switch (get_op_code(op)) {
904 ent = &i_ents[iro_Add];
908 ent = &i_ents[iro_Sub];
912 ent = &i_ents[iro_Shl];
916 ent = &i_ents[iro_Shr];
920 ent = &i_ents[iro_Shrs];
924 ent = &i_ents[iro_Mul];
928 ent = &i_ents[iro_Minus];
932 ent = &i_ents[iro_Div];
936 ent = &i_ents[iro_Mod];
940 ent = &i_ents[iro_Conv];
944 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
945 return def_create_intrinsic_fkt(method, op, imode, omode, context);
949 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
951 ident *id = id_mangle(IDENT("L"), get_op_ident(op));
952 *ent = new_entity(get_glob_type(), id, method);
953 set_entity_visibility(*ent, ir_visibility_private);
956 elt.i_call.kind = INTRINSIC_CALL;
957 elt.i_call.i_ent = *ent;
958 elt.i_call.i_mapper = mapper;
959 elt.i_call.ctx = context;
960 elt.i_call.link = NULL;
962 ARR_APP1(i_record, intrinsics, elt);