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)) & (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 = (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)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
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)));
393 irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
394 cond = new_rd_Cond(dbg, upper, irn);
396 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
397 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
399 /* the block for cnt >= 32 */
400 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
401 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
402 h2 = new_r_Const(irg, get_mode_null(h_mode));
403 in[1] = new_r_Jmp(n_block);
405 set_irn_in(block, 2, in);
409 l_res = new_r_Phi(block, 2, in, l_mode);
410 set_Block_phis(block, l_res);
414 h_res = new_r_Phi(block, 2, in, h_mode);
415 set_Phi_next(l_res, h_res);
416 set_Phi_next(h_res, NULL);
419 set_nodes_block(call, block);
420 for (irn = (ir_node*)get_irn_link(call); irn != NULL;
421 irn = (ir_node*)get_irn_link(irn)) {
422 set_nodes_block(irn, block);
425 resolve_call(call, l_res, h_res, irg, block);
430 * Map a Shrs (a_l, a_h, count)
432 static int map_Shrs(ir_node *call, void *ctx)
434 ir_graph *irg = current_ir_graph;
435 dbg_info *dbg = get_irn_dbg_info(call);
436 ir_node *block = get_nodes_block(call);
437 ir_node **params = get_Call_param_arr(call);
438 ir_type *method = get_Call_type(call);
439 ir_node *a_l = params[BINOP_Left_Low];
440 ir_node *a_h = params[BINOP_Left_High];
441 ir_node *cnt = params[BINOP_Right_Low];
442 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
443 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
445 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
449 /* the shift count is a const, create better code */
450 ir_tarval *tv = get_Const_tarval(cnt);
452 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
453 /* simplest case: shift only the higher bits. Note that there is no
454 need to reduce the constant here, this is done by the hardware. */
455 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
456 ir_mode *c_mode = get_irn_mode(cnt);
458 h_res = new_rd_Shrs(dbg, block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
459 l_res = new_rd_Shrs(dbg, block, conv, cnt, l_mode);
461 /* l_res = SHRD a_h:a_l, cnt */
462 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
464 /* h_res = SAR a_h, cnt */
465 h_res = new_bd_ia32_l_SarDep(dbg, block, a_h, cnt, l_res, h_mode);
467 resolve_call(call, l_res, h_res, irg, block);
472 upper = get_nodes_block(call);
474 /* l_res = SHRD a_h:a_l, cnt */
475 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
477 /* h_res = SAR a_h, cnt */
478 h1 = new_bd_ia32_l_SarDep(dbg, upper, a_h, cnt, l1, h_mode);
480 c_mode = get_irn_mode(cnt);
481 irn = new_r_Const_long(irg, c_mode, 32);
482 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
483 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
484 irn = new_r_Proj(irn, mode_b, pn_Cmp_Eq);
485 cond = new_rd_Cond(dbg, upper, irn);
487 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
488 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
490 /* the block for cnt >= 32 */
491 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
492 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
493 h2 = new_rd_Shrs(dbg, n_block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
494 in[1] = new_r_Jmp(n_block);
496 set_irn_in(block, 2, in);
500 l_res = new_r_Phi(block, 2, in, l_mode);
501 set_Block_phis(block, l_res);
505 h_res = new_r_Phi(block, 2, in, h_mode);
506 set_Phi_next(l_res, h_res);
507 set_Phi_next(h_res, NULL);
510 set_nodes_block(call, block);
511 for (irn = (ir_node*)get_irn_link(call); irn != NULL;
512 irn = (ir_node*)get_irn_link(irn)) {
513 set_nodes_block(irn, block);
516 resolve_call(call, l_res, h_res, irg, block);
521 * Checks where node high is a sign extension of low.
523 static int is_sign_extend(ir_node *low, ir_node *high)
528 ir_tarval *shift_count;
530 high_r = get_Shrs_right(high);
531 if (!is_Const(high_r)) return 0;
533 shift_count = get_Const_tarval(high_r);
534 if (!tarval_is_long(shift_count)) return 0;
535 if (get_tarval_long(shift_count) != 31) return 0;
537 high_l = get_Shrs_left(high);
539 if (is_Conv(low) && get_Conv_op(low) == high_l) return 1;
540 if (is_Conv(high_l) && get_Conv_op(high_l) == low) return 1;
541 } else if (is_Const(low) && is_Const(high)) {
542 ir_tarval *tl = get_Const_tarval(low);
543 ir_tarval *th = get_Const_tarval(high);
545 if (tarval_is_long(th) && tarval_is_long(tl)) {
546 long l = get_tarval_long(tl);
547 long h = get_tarval_long(th);
549 return (h == 0 && l >= 0) || (h == -1 && l < 0);
557 * Map a Mul (a_l, a_h, b_l, b_h)
559 static int map_Mul(ir_node *call, void *ctx)
561 dbg_info *dbg = get_irn_dbg_info(call);
562 ir_node *block = get_nodes_block(call);
563 ir_node **params = get_Call_param_arr(call);
564 ir_type *method = get_Call_type(call);
565 ir_node *a_l = params[BINOP_Left_Low];
566 ir_node *a_h = params[BINOP_Left_High];
567 ir_node *b_l = params[BINOP_Right_Low];
568 ir_node *b_h = params[BINOP_Right_High];
569 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
570 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
571 ir_node *l_res, *h_res, *mul, *pEDX, *add;
584 /* handle the often used case of 32x32=64 mul */
585 if (is_sign_extend(a_l, a_h) && is_sign_extend(b_l, b_h)) {
586 mul = new_bd_ia32_l_IMul(dbg, block, a_l, b_l);
587 h_res = new_rd_Proj(dbg, mul, h_mode, pn_ia32_l_IMul_res_high);
588 l_res = new_rd_Proj(dbg, mul, l_mode, pn_ia32_l_IMul_res_low);
590 /* note that zero extension is handled hare efficiently */
591 mul = new_bd_ia32_l_Mul(dbg, block, a_l, b_l);
592 pEDX = new_rd_Proj(dbg, mul, h_mode, pn_ia32_l_Mul_res_high);
593 l_res = new_rd_Proj(dbg, mul, l_mode, pn_ia32_l_Mul_res_low);
595 b_l = new_rd_Conv(dbg, block, b_l, h_mode);
596 mul = new_rd_Mul( dbg, block, a_h, b_l, h_mode);
597 add = new_rd_Add( dbg, block, mul, pEDX, h_mode);
598 a_l = new_rd_Conv(dbg, block, a_l, h_mode);
599 mul = new_rd_Mul( dbg, block, a_l, b_h, h_mode);
600 h_res = new_rd_Add( dbg, block, add, mul, h_mode);
602 resolve_call(call, l_res, h_res, current_ir_graph, block);
608 * Map a Minus (a_l, a_h)
610 static int map_Minus(ir_node *call, void *ctx)
612 dbg_info *dbg = get_irn_dbg_info(call);
613 ir_node *block = get_nodes_block(call);
614 ir_node **params = get_Call_param_arr(call);
615 ir_type *method = get_Call_type(call);
616 ir_node *a_l = params[BINOP_Left_Low];
617 ir_node *a_h = params[BINOP_Left_High];
618 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
619 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
620 ir_node *l_res, *h_res, *res;
623 res = new_bd_ia32_Minus64Bit(dbg, block, a_l, a_h);
624 l_res = new_r_Proj(res, l_mode, pn_ia32_Minus64Bit_low_res);
625 h_res = new_r_Proj(res, h_mode, pn_ia32_Minus64Bit_high_res);
627 resolve_call(call, l_res, h_res, current_ir_graph, block);
634 * Map a Abs (a_l, a_h)
636 static int map_Abs(ir_node *call, void *ctx)
638 dbg_info *dbg = get_irn_dbg_info(call);
639 ir_node *block = get_nodes_block(call);
640 ir_node **params = get_Call_param_arr(call);
641 ir_type *method = get_Call_type(call);
642 ir_node *a_l = params[BINOP_Left_Low];
643 ir_node *a_h = params[BINOP_Left_High];
644 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
645 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
646 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
647 ir_node *l_res, *h_res, *sign, *sub_l, *sub_h;
654 Code inspired by gcc output :) (although gcc doubles the
655 operation for t1 as t2 and uses t1 for operations with low part
656 and t2 for operations with high part which is actually unnecessary
657 because t1 and t2 represent the same value)
663 h_res = t3 - t1 - carry
667 /* TODO: give a hint to the backend somehow to not create a cltd here... */
668 sign = new_rd_Shrs(dbg, block, a_h, new_r_Const_long(irg, l_mode, 31), h_mode);
669 sign_l = new_rd_Conv(dbg, block, sign, l_mode);
670 sub_l = new_rd_Eor(dbg, block, a_l, sign_l, l_mode);
671 sub_h = new_rd_Eor(dbg, block, a_h, sign, h_mode);
673 l_sub = new_bd_ia32_l_Sub(dbg, block, sub_l, sign_l, mode_T);
674 l_res = new_r_Proj(l_sub, l_mode, pn_ia32_res);
675 flags = new_r_Proj(l_sub, mode_flags, pn_ia32_flags);
676 h_res = new_bd_ia32_l_Sbb(dbg, block, sub_h, sign, flags, h_mode);
678 resolve_call(call, l_res, h_res, current_ir_graph, block);
684 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
686 static ir_entity *create_compiler_lib_entity(const char *name, ir_type *type)
688 ir_type *glob = get_glob_type();
689 ident *id = new_id_from_str(name);
692 /* Hack: we need to know the type of runtime library we use. Strictly
693 speaking it's not the same as the object-file-format. But in practice
694 the following should be enough */
695 if (be_gas_object_file_format == OBJECT_FILE_FORMAT_MACH_O
696 || be_gas_object_file_format == OBJECT_FILE_FORMAT_COFF) {
697 id = id_mangle3("___", id, "");
699 id = id_mangle3("__", id, "");
701 entity = new_entity(glob, id, type);
702 set_entity_visibility(entity, ir_visibility_local);
703 set_entity_ld_ident(entity, id);
708 * Maps a Div. Change into a library call.
710 static int map_Div(ir_node *call, void *ctx)
712 ia32_intrinsic_env_t *env = (ia32_intrinsic_env_t*)ctx;
713 ir_type *method = get_Call_type(call);
714 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
717 ir_graph *irg = get_irn_irg(call);
720 if (mode_is_signed(h_mode)) {
721 /* 64bit signed Division */
724 ent = env->divdi3 = create_compiler_lib_entity("divdi3", method);
727 /* 64bit unsigned Division */
730 /* create library entity */
731 ent = env->udivdi3 = create_compiler_lib_entity("udivdi3", method);
735 ptr = get_Call_ptr(call);
737 ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
738 set_Call_ptr(call, ptr);
744 * Maps a Mod. Change into a library call
746 static int map_Mod(ir_node *call, void *ctx)
748 ia32_intrinsic_env_t *env = (ia32_intrinsic_env_t*)ctx;
749 ir_type *method = get_Call_type(call);
750 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
753 ir_graph *irg = get_irn_irg(call);
756 if (mode_is_signed(h_mode)) {
757 /* 64bit signed Modulo */
760 /* create library entity */
761 ent = env->moddi3 = create_compiler_lib_entity("moddi3", method);
764 /* 64bit signed Modulo */
767 /* create library entity */
768 ent = env->umoddi3 = create_compiler_lib_entity("umoddi3", method);
772 ptr = get_Call_ptr(call);
774 ptr = new_r_SymConst(irg, get_irn_mode(ptr), sym, symconst_addr_ent);
775 set_Call_ptr(call, ptr);
783 static int map_Conv(ir_node *call, void *ctx)
785 ir_graph *irg = current_ir_graph;
786 dbg_info *dbg = get_irn_dbg_info(call);
787 ir_node *block = get_nodes_block(call);
788 ir_node **params = get_Call_param_arr(call);
789 ir_type *method = get_Call_type(call);
790 int n = get_Call_n_params(call);
791 ir_node *l_res, *h_res;
795 ir_node *float_to_ll;
797 /* We have a Conv float -> long long here */
798 ir_node *a_f = params[0];
799 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
800 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
802 assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
804 if (mode_is_signed(h_res_mode)) {
805 /* convert from float to signed 64bit */
806 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, block, a_f);
808 l_res = new_r_Proj(float_to_ll, l_res_mode,
809 pn_ia32_l_FloattoLL_res_low);
810 h_res = new_r_Proj(float_to_ll, h_res_mode,
811 pn_ia32_l_FloattoLL_res_high);
813 /* convert from float to signed 64bit */
814 ir_mode *flt_mode = get_irn_mode(a_f);
815 ir_tarval *flt_tv = new_tarval_from_str("9223372036854775808", 19, flt_mode);
816 ir_node *flt_corr = new_r_Const(irg, flt_tv);
817 ir_node *lower_blk = block;
819 ir_node *cmp, *proj, *cond, *blk, *int_phi, *flt_phi;
823 upper_blk = get_nodes_block(call);
825 cmp = new_rd_Cmp(dbg, upper_blk, a_f, flt_corr);
826 proj = new_r_Proj(cmp, mode_b, pn_Cmp_Lt);
827 cond = new_rd_Cond(dbg, upper_blk, proj);
828 in[0] = new_r_Proj(cond, mode_X, pn_Cond_true);
829 in[1] = new_r_Proj(cond, mode_X, pn_Cond_false);
830 blk = new_r_Block(irg, 1, &in[1]);
831 in[1] = new_r_Jmp(blk);
833 set_irn_in(lower_blk, 2, in);
836 in[0] = new_r_Const(irg, get_mode_null(h_res_mode));
837 in[1] = new_r_Const_long(irg, h_res_mode, 0x80000000);
839 int_phi = new_r_Phi(lower_blk, 2, in, h_res_mode);
842 in[1] = new_rd_Sub(dbg, upper_blk, a_f, flt_corr, flt_mode);
844 flt_phi = new_r_Phi(lower_blk, 2, in, flt_mode);
846 /* fix Phi links for next part_block() */
847 set_Block_phis(lower_blk, int_phi);
848 set_Phi_next(int_phi, flt_phi);
849 set_Phi_next(flt_phi, NULL);
851 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi);
853 l_res = new_r_Proj(float_to_ll, l_res_mode,
854 pn_ia32_l_FloattoLL_res_low);
855 h_res = new_r_Proj(float_to_ll, h_res_mode,
856 pn_ia32_l_FloattoLL_res_high);
858 h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, h_res_mode);
860 /* move the call and its Proj's to the lower block */
861 set_nodes_block(call, lower_blk);
863 for (proj = (ir_node*)get_irn_link(call); proj != NULL;
864 proj = (ir_node*)get_irn_link(proj)) {
865 set_nodes_block(proj, lower_blk);
870 resolve_call(call, l_res, h_res, irg, block);
872 ir_node *ll_to_float;
874 /* We have a Conv long long -> float here */
875 ir_node *a_l = params[BINOP_Left_Low];
876 ir_node *a_h = params[BINOP_Left_High];
877 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
879 assert(! mode_is_float(get_irn_mode(a_l))
880 && ! mode_is_float(get_irn_mode(a_h)));
882 ll_to_float = new_bd_ia32_l_LLtoFloat(dbg, block, a_h, a_l, fres_mode);
885 resolve_call(call, ll_to_float, NULL, irg, block);
887 panic("unexpected Conv call %+F", call);
893 /* Ia32 implementation of intrinsic mapping. */
894 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
895 const ir_mode *imode, const ir_mode *omode,
899 ir_entity **ent = NULL;
900 i_mapper_func mapper;
903 intrinsics = NEW_ARR_F(i_record, 0);
905 switch (get_op_code(op)) {
907 ent = &i_ents[iro_Add];
911 ent = &i_ents[iro_Sub];
915 ent = &i_ents[iro_Shl];
919 ent = &i_ents[iro_Shr];
923 ent = &i_ents[iro_Shrs];
927 ent = &i_ents[iro_Mul];
931 ent = &i_ents[iro_Minus];
935 ent = &i_ents[iro_Div];
939 ent = &i_ents[iro_Mod];
943 ent = &i_ents[iro_Conv];
947 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
948 return def_create_intrinsic_fkt(method, op, imode, omode, context);
952 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
954 ident *id = id_mangle(IDENT("L"), get_op_ident(op));
955 *ent = new_entity(get_glob_type(), id, method);
956 set_entity_visibility(*ent, ir_visibility_private);
959 elt.i_call.kind = INTRINSIC_CALL;
960 elt.i_call.i_ent = *ent;
961 elt.i_call.i_mapper = mapper;
962 elt.i_call.ctx = context;
963 elt.i_call.link = NULL;
965 ARR_APP1(i_record, intrinsics, elt);