2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief This file implements the mapping of 64Bit intrinsic
23 * functions to code or library calls.
24 * @author Michael Beck
39 #include "ia32_new_nodes.h"
40 #include "bearch_ia32_t.h"
41 #include "gen_ia32_regalloc_if.h"
43 /** The array of all intrinsics that must be mapped. */
44 static i_record *intrinsics;
46 /** An array to cache all entities. */
47 static ir_entity *i_ents[iro_Last + 1];
50 * Maps all intrinsic calls that the backend support
51 * and map all instructions the backend did not support
54 void ia32_handle_intrinsics(void) {
55 if (intrinsics && ARR_LEN(intrinsics) > 0) {
56 lower_intrinsics(intrinsics, ARR_LEN(intrinsics), /*part_block_used=*/1);
60 #define BINOP_Left_Low 0
61 #define BINOP_Left_High 1
62 #define BINOP_Right_Low 2
63 #define BINOP_Right_High 3
66 * Reroute edges from the pn_Call_T_result proj of a call.
68 * @param proj the pn_Call_T_result Proj
69 * @param l_res the lower 32 bit result
70 * @param h_res the upper 32 bit result or NULL
71 * @param irg the graph to replace on
73 static void reroute_result(ir_node *proj, ir_node *l_res, ir_node *h_res, ir_graph *irg) {
74 const ir_edge_t *edge, *next;
76 foreach_out_edge_safe(proj, edge, next) {
77 ir_node *proj = get_edge_src_irn(edge);
78 long pn = get_Proj_proj(proj);
81 edges_reroute(proj, l_res, irg);
82 } else if (pn == 1 && h_res != NULL) {
83 edges_reroute(proj, h_res, irg);
85 panic("Unsupported Result-Proj from Call found");
91 * Replace a call be a tuple of l_res, h_res.
93 * @param call the call node to replace
94 * @param l_res the lower 32 bit result
95 * @param h_res the upper 32 bit result or NULL
96 * @param irg the graph to replace on
97 * @param block the block to replace on (always the call block)
99 static void resolve_call(ir_node *call, ir_node *l_res, ir_node *h_res, ir_graph *irg, ir_node *block) {
100 ir_node *jmp, *res, *in[2];
101 ir_node *bad = get_irg_bad(irg);
102 ir_node *nomem = get_irg_no_mem(irg);
105 if (edges_activated(irg)) {
106 /* use rerouting to prevent some warning in the backend */
107 const ir_edge_t *edge, *next;
109 foreach_out_edge_safe(call, edge, next) {
110 ir_node *proj = get_edge_src_irn(edge);
111 pn_Call pn = get_Proj_proj(proj);
114 case pn_Call_X_regular:
116 * We do not check here if this call really has exception and regular Proj's.
117 * new_r_Jmp might than be CSEd with the real exit jmp and then bad things happen
118 * (in movgen.c from 186.crafty for example).
119 * So be sure the newly created Jmp cannot CSE.
121 old_cse = get_opt_cse();
123 jmp = new_r_Jmp(block);
124 set_opt_cse(old_cse);
125 edges_reroute(proj, jmp, irg);
128 case pn_Call_X_except:
129 case pn_Call_P_value_res_base:
130 /* should not happen here */
131 edges_reroute(proj, bad, irg);
133 case pn_Call_M_except:
134 /* should not happen here */
135 edges_reroute(proj, nomem, irg);
137 case pn_Call_T_result:
138 reroute_result(proj, l_res, h_res, irg);
141 panic("Wrong Proj from Call");
147 /* no edges, build Tuple */
153 res = new_r_Tuple(block, 2, in);
156 turn_into_tuple(call, pn_Call_max);
157 set_Tuple_pred(call, pn_Call_M_regular, nomem);
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_X_regular, jmp);
171 set_Tuple_pred(call, pn_Call_X_except, bad);
172 set_Tuple_pred(call, pn_Call_T_result, res);
173 set_Tuple_pred(call, pn_Call_M_except, nomem);
174 set_Tuple_pred(call, pn_Call_P_value_res_base, bad);
179 * Map an Add (a_l, a_h, b_l, b_h)
181 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(block, 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(block, 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(block, 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( block, 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) {
249 ir_graph *irg = current_ir_graph;
250 dbg_info *dbg = get_irn_dbg_info(call);
251 ir_node *block = get_nodes_block(call);
252 ir_node **params = get_Call_param_arr(call);
253 ir_type *method = get_Call_type(call);
254 ir_node *a_l = params[BINOP_Left_Low];
255 ir_node *a_h = params[BINOP_Left_High];
256 ir_node *cnt = params[BINOP_Right_Low];
257 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
258 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
260 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
264 /* the shift count is a const, create better code */
265 tarval *tv = get_Const_tarval(cnt);
267 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
268 /* simplest case: shift only the lower bits. Note that there is no
269 need to reduce the constant here, this is done by the hardware. */
270 ir_node *conv = new_rd_Conv(dbg, block, a_l, h_mode);
271 h_res = new_rd_Shl(dbg, block, conv, cnt, h_mode);
272 l_res = new_rd_Const(dbg, irg, get_mode_null(l_mode));
275 /* h_res = SHLD a_h, a_l, cnt */
276 h_res = new_bd_ia32_l_ShlD(dbg, block, a_h, a_l, cnt, h_mode);
278 /* l_res = SHL a_l, cnt */
279 l_res = new_bd_ia32_l_ShlDep(dbg, block, a_l, cnt, h_res, l_mode);
282 resolve_call(call, l_res, h_res, irg, block);
287 upper = get_nodes_block(call);
289 /* h_res = SHLD a_h, a_l, cnt */
290 h1 = new_bd_ia32_l_ShlD(dbg, upper, a_h, a_l, cnt, h_mode);
292 /* l_res = SHL a_l, cnt */
293 l1 = new_bd_ia32_l_ShlDep(dbg, upper, a_l, cnt, h1, l_mode);
295 c_mode = get_irn_mode(cnt);
296 irn = new_r_Const_long(irg, c_mode, 32);
297 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
298 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
299 irn = new_r_Proj(upper, irn, mode_b, pn_Cmp_Eq);
300 cond = new_rd_Cond(dbg, upper, irn);
302 in[0] = new_r_Proj(upper, cond, mode_X, pn_Cond_true);
303 in[1] = new_r_Proj(upper, cond, mode_X, pn_Cond_false);
305 /* the block for cnt >= 32 */
306 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
307 h2 = new_rd_Conv(dbg, n_block, l1, h_mode);
308 l2 = new_r_Const(irg, get_mode_null(l_mode));
309 in[1] = new_r_Jmp(n_block);
311 set_irn_in(block, 2, in);
315 l_res = new_r_Phi(block, 2, in, l_mode);
316 set_Block_phis(block, l_res);
320 h_res = new_r_Phi(block, 2, in, h_mode);
321 set_Phi_next(l_res, h_res);
322 set_Phi_next(h_res, NULL);
325 set_nodes_block(call, block);
326 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
327 set_nodes_block(irn, block);
329 resolve_call(call, l_res, h_res, irg, block);
334 * Map a Shr (a_l, a_h, count)
336 static int map_Shr(ir_node *call, void *ctx) {
337 ir_graph *irg = current_ir_graph;
338 dbg_info *dbg = get_irn_dbg_info(call);
339 ir_node *block = get_nodes_block(call);
340 ir_node **params = get_Call_param_arr(call);
341 ir_type *method = get_Call_type(call);
342 ir_node *a_l = params[BINOP_Left_Low];
343 ir_node *a_h = params[BINOP_Left_High];
344 ir_node *cnt = params[BINOP_Right_Low];
345 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
346 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
348 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
352 /* the shift count is a const, create better code */
353 tarval *tv = get_Const_tarval(cnt);
355 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
356 /* simplest case: shift only the higher bits. Note that there is no
357 need to reduce the constant here, this is done by the hardware. */
358 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
359 h_res = new_rd_Const(dbg, irg, get_mode_null(h_mode));
360 l_res = new_rd_Shr(dbg, block, conv, cnt, l_mode);
362 /* l_res = SHRD a_h:a_l, cnt */
363 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
365 /* h_res = SHR a_h, cnt */
366 h_res = new_bd_ia32_l_ShrDep(dbg, block, a_h, cnt, l_res, h_mode);
368 resolve_call(call, l_res, h_res, irg, block);
373 upper = get_nodes_block(call);
375 /* l_res = SHRD a_h:a_l, cnt */
376 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
378 /* h_res = SHR a_h, cnt */
379 h1 = new_bd_ia32_l_ShrDep(dbg, upper, a_h, cnt, l1, h_mode);
381 c_mode = get_irn_mode(cnt);
382 irn = new_r_Const_long(irg, c_mode, 32);
383 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
384 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
385 irn = new_r_Proj(upper, irn, mode_b, pn_Cmp_Eq);
386 cond = new_rd_Cond(dbg, upper, irn);
388 in[0] = new_r_Proj(upper, cond, mode_X, pn_Cond_true);
389 in[1] = new_r_Proj(upper, cond, mode_X, pn_Cond_false);
391 /* the block for cnt >= 32 */
392 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
393 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
394 h2 = new_r_Const(irg, get_mode_null(h_mode));
395 in[1] = new_r_Jmp(n_block);
397 set_irn_in(block, 2, in);
401 l_res = new_r_Phi(block, 2, in, l_mode);
402 set_Block_phis(block, l_res);
406 h_res = new_r_Phi(block, 2, in, h_mode);
407 set_Phi_next(l_res, h_res);
408 set_Phi_next(h_res, NULL);
411 set_nodes_block(call, block);
412 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
413 set_nodes_block(irn, block);
415 resolve_call(call, l_res, h_res, irg, block);
420 * Map a Shrs (a_l, a_h, count)
422 static int map_Shrs(ir_node *call, void *ctx) {
423 ir_graph *irg = current_ir_graph;
424 dbg_info *dbg = get_irn_dbg_info(call);
425 ir_node *block = get_nodes_block(call);
426 ir_node **params = get_Call_param_arr(call);
427 ir_type *method = get_Call_type(call);
428 ir_node *a_l = params[BINOP_Left_Low];
429 ir_node *a_h = params[BINOP_Left_High];
430 ir_node *cnt = params[BINOP_Right_Low];
431 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
432 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
434 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
438 /* the shift count is a const, create better code */
439 tarval *tv = get_Const_tarval(cnt);
441 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
442 /* simplest case: shift only the higher bits. Note that there is no
443 need to reduce the constant here, this is done by the hardware. */
444 ir_node *conv = new_rd_Conv(dbg, block, a_h, l_mode);
445 ir_mode *c_mode = get_irn_mode(cnt);
447 h_res = new_rd_Shrs(dbg, block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
448 l_res = new_rd_Shrs(dbg, block, conv, cnt, l_mode);
450 /* l_res = SHRD a_h:a_l, cnt */
451 l_res = new_bd_ia32_l_ShrD(dbg, block, a_l, a_h, cnt, l_mode);
453 /* h_res = SAR a_h, cnt */
454 h_res = new_bd_ia32_l_SarDep(dbg, block, a_h, cnt, l_res, h_mode);
456 resolve_call(call, l_res, h_res, irg, block);
461 upper = get_nodes_block(call);
463 /* l_res = SHRD a_h:a_l, cnt */
464 l1 = new_bd_ia32_l_ShrD(dbg, upper, a_l, a_h, cnt, l_mode);
466 /* h_res = SAR a_h, cnt */
467 h1 = new_bd_ia32_l_SarDep(dbg, upper, a_h, cnt, l1, h_mode);
469 c_mode = get_irn_mode(cnt);
470 irn = new_r_Const_long(irg, c_mode, 32);
471 irn = new_rd_And(dbg, upper, cnt, irn, c_mode);
472 irn = new_rd_Cmp(dbg, upper, irn, new_r_Const(irg, get_mode_null(c_mode)));
473 irn = new_r_Proj(upper, irn, mode_b, pn_Cmp_Eq);
474 cond = new_rd_Cond(dbg, upper, irn);
476 in[0] = new_r_Proj(upper, cond, mode_X, pn_Cond_true);
477 in[1] = new_r_Proj(upper, cond, mode_X, pn_Cond_false);
479 /* the block for cnt >= 32 */
480 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
481 l2 = new_rd_Conv(dbg, n_block, h1, l_mode);
482 h2 = new_rd_Shrs(dbg, n_block, a_h, new_r_Const_long(irg, c_mode, 31), h_mode);
483 in[1] = new_r_Jmp(n_block);
485 set_irn_in(block, 2, in);
489 l_res = new_r_Phi(block, 2, in, l_mode);
490 set_Block_phis(block, l_res);
494 h_res = new_r_Phi(block, 2, in, h_mode);
495 set_Phi_next(l_res, h_res);
496 set_Phi_next(h_res, NULL);
499 set_nodes_block(call, block);
500 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
501 set_nodes_block(irn, block);
503 resolve_call(call, l_res, h_res, irg, block);
508 * Checks where node high is a sign extension of low.
510 static int is_sign_extend(ir_node *low, ir_node *high)
517 high_r = get_Shrs_right(high);
518 if (!is_Const(high_r)) return 0;
520 shift_count = get_Const_tarval(high_r);
521 if (!tarval_is_long(shift_count)) return 0;
522 if (get_tarval_long(shift_count) != 31) return 0;
524 high_l = get_Shrs_left(high);
526 if (is_Conv(low) && get_Conv_op(low) == high_l) return 1;
527 if (is_Conv(high_l) && get_Conv_op(high_l) == low) return 1;
528 } else if (is_Const(low) && is_Const(high)) {
529 tarval *tl = get_Const_tarval(low);
530 tarval *th = get_Const_tarval(high);
532 if (tarval_is_long(th) && tarval_is_long(tl)) {
533 long l = get_tarval_long(tl);
534 long h = get_tarval_long(th);
536 return (h == 0 && l >= 0) || (h == -1 && l < 0);
544 * Map a Mul (a_l, a_h, b_l, b_h)
546 static int map_Mul(ir_node *call, void *ctx) {
547 dbg_info *dbg = get_irn_dbg_info(call);
548 ir_node *block = get_nodes_block(call);
549 ir_node **params = get_Call_param_arr(call);
550 ir_type *method = get_Call_type(call);
551 ir_node *a_l = params[BINOP_Left_Low];
552 ir_node *a_h = params[BINOP_Left_High];
553 ir_node *b_l = params[BINOP_Right_Low];
554 ir_node *b_h = params[BINOP_Right_High];
555 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
556 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
557 ir_node *l_res, *h_res, *mul, *pEDX, *add;
570 /* handle the often used case of 32x32=64 mul */
571 if (is_sign_extend(a_l, a_h) && is_sign_extend(b_l, b_h)) {
572 mul = new_bd_ia32_l_IMul(dbg, block, a_l, b_l);
573 h_res = new_rd_Proj(dbg, block, mul, h_mode, pn_ia32_l_Mul_EDX);
574 l_res = new_rd_Proj(dbg, block, mul, l_mode, pn_ia32_l_Mul_EAX);
576 /* note that zero extension is handled hare efficiently */
577 mul = new_bd_ia32_l_Mul(dbg, block, a_l, b_l);
578 pEDX = new_rd_Proj(dbg, block, mul, h_mode, pn_ia32_l_Mul_EDX);
579 l_res = new_rd_Proj(dbg, block, mul, l_mode, pn_ia32_l_Mul_EAX);
581 b_l = new_rd_Conv(dbg, block, b_l, h_mode);
582 mul = new_rd_Mul( dbg, block, a_h, b_l, h_mode);
583 add = new_rd_Add( dbg, block, mul, pEDX, h_mode);
584 a_l = new_rd_Conv(dbg, block, a_l, h_mode);
585 mul = new_rd_Mul( dbg, block, a_l, b_h, h_mode);
586 h_res = new_rd_Add( dbg, block, add, mul, h_mode);
588 resolve_call(call, l_res, h_res, current_ir_graph, block);
594 * Map a Minus (a_l, a_h)
596 static int map_Minus(ir_node *call, void *ctx) {
597 dbg_info *dbg = get_irn_dbg_info(call);
598 ir_node *block = get_nodes_block(call);
599 ir_node **params = get_Call_param_arr(call);
600 ir_type *method = get_Call_type(call);
601 ir_node *a_l = params[BINOP_Left_Low];
602 ir_node *a_h = params[BINOP_Left_High];
603 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
604 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
605 ir_node *l_res, *h_res, *res;
608 res = new_bd_ia32_Minus64Bit(dbg, block, a_l, a_h);
609 l_res = new_r_Proj(block, res, l_mode, pn_ia32_Minus64Bit_low_res);
610 h_res = new_r_Proj(block, res, h_mode, pn_ia32_Minus64Bit_high_res);
612 resolve_call(call, l_res, h_res, current_ir_graph, block);
618 * Map a Abs (a_l, a_h)
620 static int map_Abs(ir_node *call, void *ctx) {
621 dbg_info *dbg = get_irn_dbg_info(call);
622 ir_node *block = get_nodes_block(call);
623 ir_node **params = get_Call_param_arr(call);
624 ir_type *method = get_Call_type(call);
625 ir_node *a_l = params[BINOP_Left_Low];
626 ir_node *a_h = params[BINOP_Left_High];
627 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
628 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
629 ir_mode *mode_flags = ia32_reg_classes[CLASS_ia32_flags].mode;
630 ir_node *l_res, *h_res, *sign, *sub_l, *sub_h;
637 Code inspired by gcc output :) (although gcc doubles the
638 operation for t1 as t2 and uses t1 for operations with low part
639 and t2 for operations with high part which is actually unnecessary
640 because t1 and t2 represent the same value)
646 h_res = t3 - t1 - carry
650 /* TODO: give a hint to the backend somehow to not create a cltd here... */
651 sign = new_rd_Shrs(dbg, block, a_h, new_Const_long(l_mode, 31), h_mode);
652 sign_l = new_rd_Conv(dbg, block, sign, l_mode);
653 sub_l = new_rd_Eor(dbg, block, a_l, sign_l, l_mode);
654 sub_h = new_rd_Eor(dbg, block, a_h, sign, h_mode);
656 l_sub = new_bd_ia32_l_Sub(dbg, block, sub_l, sign_l, mode_T);
657 l_res = new_r_Proj(block, l_sub, l_mode, pn_ia32_res);
658 flags = new_r_Proj(block, l_sub, mode_flags, pn_ia32_flags);
659 h_res = new_bd_ia32_l_Sbb(dbg, block, sub_h, sign, flags, h_mode);
661 resolve_call(call, l_res, h_res, current_ir_graph, block);
666 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
669 * Maps a Div. Change into a library call.
671 static int map_Div(ir_node *call, void *ctx) {
672 ia32_intrinsic_env_t *env = ctx;
673 ir_type *method = get_Call_type(call);
674 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
679 if (mode_is_signed(h_mode)) {
680 /* 64bit signed Division */
683 /* create library entity */
684 ent = env->divdi3 = new_entity(get_glob_type(), ID("__divdi3"), method);
685 set_entity_visibility(ent, visibility_external_allocated);
686 set_entity_ld_ident(ent, ID("__divdi3"));
689 /* 64bit unsigned Division */
692 /* create library entity */
693 ent = env->udivdi3 = new_entity(get_glob_type(), ID("__udivdi3"), method);
694 set_entity_visibility(ent, visibility_external_allocated);
695 set_entity_ld_ident(ent, ID("__udivdi3"));
699 ptr = get_Call_ptr(call);
700 set_SymConst_symbol(ptr, sym);
705 * Maps a Mod. Change into a library call
707 static int map_Mod(ir_node *call, void *ctx) {
708 ia32_intrinsic_env_t *env = ctx;
709 ir_type *method = get_Call_type(call);
710 ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1));
715 if (mode_is_signed(h_mode)) {
716 /* 64bit signed Modulo */
719 /* create library entity */
720 ent = env->moddi3 = new_entity(get_glob_type(), ID("__moddi3"), method);
721 set_entity_visibility(ent, visibility_external_allocated);
722 set_entity_ld_ident(ent, ID("__moddi3"));
725 /* 64bit signed Modulo */
728 /* create library entity */
729 ent = env->umoddi3 = new_entity(get_glob_type(), ID("__umoddi3"), method);
730 set_entity_visibility(ent, visibility_external_allocated);
731 set_entity_ld_ident(ent, ID("__umoddi3"));
735 ptr = get_Call_ptr(call);
736 set_SymConst_symbol(ptr, sym);
743 static int map_Conv(ir_node *call, void *ctx) {
744 ir_graph *irg = current_ir_graph;
745 dbg_info *dbg = get_irn_dbg_info(call);
746 ir_node *block = get_nodes_block(call);
747 ir_node **params = get_Call_param_arr(call);
748 ir_type *method = get_Call_type(call);
749 int n = get_Call_n_params(call);
750 ir_node *l_res, *h_res;
754 ir_node *float_to_ll;
756 /* We have a Conv float -> long long here */
757 ir_node *a_f = params[0];
758 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
759 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
761 assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
763 if (mode_is_signed(h_res_mode)) {
764 /* convert from float to signed 64bit */
765 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, block, a_f);
767 l_res = new_r_Proj(block, float_to_ll, l_res_mode,
768 pn_ia32_l_FloattoLL_res_low);
769 h_res = new_r_Proj(block, float_to_ll, h_res_mode,
770 pn_ia32_l_FloattoLL_res_high);
772 /* convert from float to signed 64bit */
773 ir_mode *flt_mode = get_irn_mode(a_f);
774 tarval *flt_tv = new_tarval_from_str("9223372036854775808", 19, flt_mode);
775 ir_node *flt_corr = new_Const(flt_tv);
776 ir_node *lower_blk = block;
778 ir_node *cmp, *proj, *cond, *blk, *int_phi, *flt_phi;
782 upper_blk = get_nodes_block(call);
784 cmp = new_rd_Cmp(dbg, upper_blk, a_f, flt_corr);
785 proj = new_r_Proj(upper_blk, cmp, mode_b, pn_Cmp_Lt);
786 cond = new_rd_Cond(dbg, upper_blk, proj);
787 in[0] = new_r_Proj(upper_blk, cond, mode_X, pn_Cond_true);
788 in[1] = new_r_Proj(upper_blk, cond, mode_X, pn_Cond_false);
789 blk = new_r_Block(irg, 1, &in[1]);
790 in[1] = new_r_Jmp(blk);
792 set_irn_in(lower_blk, 2, in);
795 in[0] = new_Const(get_mode_null(h_res_mode));
796 in[1] = new_Const_long(h_res_mode, 0x80000000);
798 int_phi = new_r_Phi(lower_blk, 2, in, h_res_mode);
801 in[1] = new_rd_Sub(dbg, upper_blk, a_f, flt_corr, flt_mode);
803 flt_phi = new_r_Phi(lower_blk, 2, in, flt_mode);
805 /* fix Phi links for next part_block() */
806 set_Block_phis(lower_blk, int_phi);
807 set_Phi_next(int_phi, flt_phi);
808 set_Phi_next(flt_phi, NULL);
810 float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi);
812 l_res = new_r_Proj(lower_blk, float_to_ll, l_res_mode,
813 pn_ia32_l_FloattoLL_res_low);
814 h_res = new_r_Proj(lower_blk, float_to_ll, h_res_mode,
815 pn_ia32_l_FloattoLL_res_high);
817 h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, h_res_mode);
819 /* move the call and its Proj's to the lower block */
820 set_nodes_block(call, lower_blk);
822 for (proj = get_irn_link(call); proj != NULL; proj = get_irn_link(proj))
823 set_nodes_block(proj, lower_blk);
827 resolve_call(call, l_res, h_res, irg, block);
829 ir_node *ll_to_float;
831 /* We have a Conv long long -> float here */
832 ir_node *a_l = params[BINOP_Left_Low];
833 ir_node *a_h = params[BINOP_Left_High];
834 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
836 assert(! mode_is_float(get_irn_mode(a_l))
837 && ! mode_is_float(get_irn_mode(a_h)));
839 ll_to_float = new_bd_ia32_l_LLtoFloat(dbg, block, a_h, a_l, fres_mode);
842 resolve_call(call, ll_to_float, NULL, irg, block);
844 panic("unexpected Conv call %+F", call);
850 /* Ia32 implementation of intrinsic mapping. */
851 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
852 const ir_mode *imode, const ir_mode *omode,
856 ir_entity **ent = NULL;
857 i_mapper_func mapper;
860 intrinsics = NEW_ARR_F(i_record, 0);
862 switch (get_op_code(op)) {
864 ent = &i_ents[iro_Add];
868 ent = &i_ents[iro_Sub];
872 ent = &i_ents[iro_Shl];
876 ent = &i_ents[iro_Shr];
880 ent = &i_ents[iro_Shrs];
884 ent = &i_ents[iro_Mul];
888 ent = &i_ents[iro_Minus];
892 ent = &i_ents[iro_Abs];
896 ent = &i_ents[iro_Div];
900 ent = &i_ents[iro_Mod];
904 ent = &i_ents[iro_Conv];
908 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
909 return def_create_intrinsic_fkt(method, op, imode, omode, context);
913 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
915 ident *id = id_mangle(IDENT("L"), get_op_ident(op));
916 *ent = new_entity(get_glob_type(), id, method);
919 elt.i_call.kind = INTRINSIC_CALL;
920 elt.i_call.i_ent = *ent;
921 elt.i_call.i_mapper = mapper;
922 elt.i_call.ctx = context;
923 elt.i_call.link = NULL;
925 ARR_APP1(i_record, intrinsics, elt);