2 * Copyright (C) 1995-2007 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_MaxOpcode];
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 * Replace a call be a tuple of l_res, h_res.
68 static void resolve_call(ir_node *call, ir_node *l_res, ir_node *h_res, ir_graph *irg, ir_node *block) {
73 res = new_r_Tuple(irg, block, h_res == NULL ? 1 : 2, in);
75 turn_into_tuple(call, pn_Call_max);
76 set_Tuple_pred(call, pn_Call_M_regular, get_irg_no_mem(irg));
77 set_Tuple_pred(call, pn_Call_X_regular, new_r_Jmp(irg, block));
78 set_Tuple_pred(call, pn_Call_X_except, get_irg_bad(irg));
79 set_Tuple_pred(call, pn_Call_T_result, res);
80 set_Tuple_pred(call, pn_Call_M_except, get_irg_no_mem(irg));
81 set_Tuple_pred(call, pn_Call_P_value_res_base, get_irg_bad(irg));
85 * Map an Add (a_l, a_h, b_l, b_h)
87 static int map_Add(ir_node *call, void *ctx) {
88 ir_graph *irg = current_ir_graph;
89 dbg_info *dbg = get_irn_dbg_info(call);
90 ir_node *block = get_nodes_block(call);
91 ir_node **params = get_Call_param_arr(call);
92 ir_type *method = get_Call_type(call);
93 ir_node *a_l = params[BINOP_Left_Low];
94 ir_node *a_h = params[BINOP_Left_High];
95 ir_node *b_l = params[BINOP_Right_Low];
96 ir_node *b_h = params[BINOP_Right_High];
97 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
98 ir_node *l_res, *h_res, *add;
101 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
103 /* l_res = a_l + b_l */
104 /* h_res = a_h + b_h + carry */
106 add = new_rd_ia32_Add64Bit(dbg, irg, block, a_l, a_h, b_l, b_h);
107 l_res = new_r_Proj(irg, block, add, l_mode, pn_ia32_Add64Bit_low_res);
108 h_res = new_r_Proj(irg, block, add, l_mode, pn_ia32_Add64Bit_high_res);
110 resolve_call(call, l_res, h_res, irg, block);
115 * Map a Sub (a_l, a_h, b_l, b_h)
117 static int map_Sub(ir_node *call, void *ctx) {
118 ir_graph *irg = current_ir_graph;
119 dbg_info *dbg = get_irn_dbg_info(call);
120 ir_node *block = get_nodes_block(call);
121 ir_node **params = get_Call_param_arr(call);
122 ir_type *method = get_Call_type(call);
123 ir_node *a_l = params[BINOP_Left_Low];
124 ir_node *a_h = params[BINOP_Left_High];
125 ir_node *b_l = params[BINOP_Right_Low];
126 ir_node *b_h = params[BINOP_Right_High];
127 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
128 ir_node *l_res, *h_res, *res;
131 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
133 /* l_res = a_l - b_l */
134 /* h_res = a_h - b_h - carry */
136 res = new_rd_ia32_Sub64Bit(dbg, irg, block, a_l, a_h, b_l, b_h);
137 l_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_low_res);
138 h_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_high_res);
140 resolve_call(call, l_res, h_res, irg, block);
145 * Map a Shl (a_l, a_h, count)
147 static int map_Shl(ir_node *call, void *ctx) {
148 ir_graph *irg = current_ir_graph;
149 dbg_info *dbg = get_irn_dbg_info(call);
150 ir_node *block = get_nodes_block(call);
151 ir_node **params = get_Call_param_arr(call);
152 ir_type *method = get_Call_type(call);
153 ir_node *a_l = params[BINOP_Left_Low];
154 ir_node *a_h = params[BINOP_Left_High];
155 ir_node *cnt = params[BINOP_Right_Low];
156 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
158 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
161 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
164 /* the shift count is a const, create better code */
165 tarval *tv = get_Const_tarval(cnt);
167 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
168 /* simplest case: shift only the lower bits. Note that there is no
169 need to reduce the constant here, this is done by the hardware. */
170 h_res = new_rd_Shl(dbg, irg, block, a_l, cnt, l_mode);
171 l_res = new_rd_Const(dbg, irg, block, l_mode, get_mode_null(l_mode));
173 resolve_call(call, l_res, h_res, irg, block);
179 upper = get_nodes_block(call);
181 /* h_res = SHLD a_h, a_l, cnt */
182 h1 = new_rd_ia32_l_ShlD(dbg, irg, upper, a_h, a_l, cnt, l_mode);
184 /* l_res = SHL a_l, cnt */
185 l1 = new_rd_ia32_l_ShlDep(dbg, irg, upper, a_l, cnt, h1, l_mode);
187 c_mode = get_irn_mode(cnt);
188 irn = new_r_Const_long(irg, upper, c_mode, 32);
189 irn = new_rd_And(dbg, irg, upper, cnt, irn, c_mode);
190 irn = new_rd_Cmp(dbg, irg, upper, irn, new_r_Const(irg, upper, c_mode, get_mode_null(c_mode)));
191 irn = new_r_Proj(irg, upper, irn, mode_b, pn_Cmp_Eq);
192 cond = new_rd_Cond(dbg, irg, upper, irn);
194 in[0] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_true);
195 in[1] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_false);
197 /* the block for cnt >= 32 */
198 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
200 l2 = new_r_Const(irg, n_block, l_mode, get_mode_null(l_mode));
201 in[1] = new_r_Jmp(irg, n_block);
203 set_irn_in(block, 2, in);
207 l_res = new_r_Phi(irg, block, 2, in, l_mode);
208 set_irn_link(block, l_res);
212 h_res = new_r_Phi(irg, block, 2, in, l_mode);
213 set_irn_link(l_res, h_res);
214 set_irn_link(h_res, NULL);
217 set_nodes_block(call, block);
218 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
219 set_nodes_block(irn, block);
221 resolve_call(call, l_res, h_res, irg, block);
226 * Map a Shr (a_l, a_h, count)
228 static int map_Shr(ir_node *call, void *ctx) {
229 ir_graph *irg = current_ir_graph;
230 dbg_info *dbg = get_irn_dbg_info(call);
231 ir_node *block = get_nodes_block(call);
232 ir_node **params = get_Call_param_arr(call);
233 ir_type *method = get_Call_type(call);
234 ir_node *a_l = params[BINOP_Left_Low];
235 ir_node *a_h = params[BINOP_Left_High];
236 ir_node *cnt = params[BINOP_Right_Low];
237 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
239 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
242 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
245 /* the shift count is a const, create better code */
246 tarval *tv = get_Const_tarval(cnt);
248 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
249 /* simplest case: shift only the higher bits. Note that there is no
250 need to reduce the constant here, this is done by the hardware. */
251 h_res = new_rd_Const(dbg, irg, block, l_mode, get_mode_null(l_mode));
252 l_res = new_rd_Shr(dbg, irg, block, a_h, cnt, l_mode);
254 resolve_call(call, l_res, h_res, irg, block);
260 upper = get_nodes_block(call);
262 /* l_res = SHRD a_h:a_l, cnt */
263 l1 = new_rd_ia32_l_ShrD(dbg, irg, upper, a_l, a_h, cnt, l_mode);
265 /* h_res = SHR a_h, cnt */
266 h1 = new_rd_ia32_l_ShrDep(dbg, irg, upper, a_h, cnt, l1, l_mode);
268 c_mode = get_irn_mode(cnt);
269 irn = new_r_Const_long(irg, upper, c_mode, 32);
270 irn = new_rd_And(dbg, irg, upper, cnt, irn, c_mode);
271 irn = new_rd_Cmp(dbg, irg, upper, irn, new_r_Const(irg, upper, c_mode, get_mode_null(c_mode)));
272 irn = new_r_Proj(irg, upper, irn, mode_b, pn_Cmp_Eq);
273 cond = new_rd_Cond(dbg, irg, upper, irn);
275 in[0] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_true);
276 in[1] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_false);
278 /* the block for cnt >= 32 */
279 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
281 h2 = new_r_Const(irg, n_block, l_mode, get_mode_null(l_mode));
282 in[1] = new_r_Jmp(irg, n_block);
284 set_irn_in(block, 2, in);
288 l_res = new_r_Phi(irg, block, 2, in, l_mode);
289 set_irn_link(block, l_res);
293 h_res = new_r_Phi(irg, block, 2, in, l_mode);
294 set_irn_link(l_res, h_res);
295 set_irn_link(h_res, NULL);
298 set_nodes_block(call, block);
299 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
300 set_nodes_block(irn, block);
302 resolve_call(call, l_res, h_res, irg, block);
307 * Map a Shrs (a_l, a_h, count)
309 static int map_Shrs(ir_node *call, void *ctx) {
310 ir_graph *irg = current_ir_graph;
311 dbg_info *dbg = get_irn_dbg_info(call);
312 ir_node *block = get_nodes_block(call);
313 ir_node **params = get_Call_param_arr(call);
314 ir_type *method = get_Call_type(call);
315 ir_node *a_l = params[BINOP_Left_Low];
316 ir_node *a_h = params[BINOP_Left_High];
317 ir_node *cnt = params[BINOP_Right_Low];
318 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
320 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
323 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
326 /* the shift count is a const, create better code */
327 tarval *tv = get_Const_tarval(cnt);
329 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
330 /* simplest case: shift only the higher bits. Note that there is no
331 need to reduce the constant here, this is done by the hardware. */
332 ir_mode *c_mode = get_irn_mode(cnt);
334 h_res = new_rd_Shrs(dbg, irg, block, a_h, new_r_Const_long(irg, block, c_mode, 31), l_mode);
335 l_res = new_rd_Shrs(dbg, irg, block, a_h, cnt, l_mode);
337 resolve_call(call, l_res, h_res, irg, block);
343 upper = get_nodes_block(call);
345 /* l_res = SHRD a_h:a_l, cnt */
346 l1 = new_rd_ia32_l_ShrD(dbg, irg, upper, a_l, a_h, cnt, l_mode);
348 /* h_res = SAR a_h, cnt */
349 h1 = new_rd_ia32_l_SarDep(dbg, irg, upper, a_h, cnt, l1, l_mode);
351 c_mode = get_irn_mode(cnt);
352 irn = new_r_Const_long(irg, upper, c_mode, 32);
353 irn = new_rd_And(dbg, irg, upper, cnt, irn, c_mode);
354 irn = new_rd_Cmp(dbg, irg, upper, irn, new_r_Const(irg, upper, c_mode, get_mode_null(c_mode)));
355 irn = new_r_Proj(irg, upper, irn, mode_b, pn_Cmp_Eq);
356 cond = new_rd_Cond(dbg, irg, upper, irn);
358 in[0] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_true);
359 in[1] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_false);
361 /* the block for cnt >= 32 */
362 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
364 h2 = new_rd_Shrs(dbg, irg, n_block, a_h, new_r_Const_long(irg, block, c_mode, 31), l_mode);
365 in[1] = new_r_Jmp(irg, n_block);
367 set_irn_in(block, 2, in);
371 l_res = new_r_Phi(irg, block, 2, in, l_mode);
372 set_irn_link(block, l_res);
376 h_res = new_r_Phi(irg, block, 2, in, l_mode);
377 set_irn_link(l_res, h_res);
378 set_irn_link(h_res, NULL);
381 set_nodes_block(call, block);
382 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
383 set_nodes_block(irn, block);
385 resolve_call(call, l_res, h_res, irg, block);
390 * Map a Mul (a_l, a_h, b_l, b_h)
392 static int map_Mul(ir_node *call, void *ctx) {
393 ir_graph *irg = current_ir_graph;
394 dbg_info *dbg = get_irn_dbg_info(call);
395 ir_node *block = get_nodes_block(call);
396 ir_node **params = get_Call_param_arr(call);
397 ir_type *method = get_Call_type(call);
398 ir_node *a_l = params[BINOP_Left_Low];
399 ir_node *a_h = params[BINOP_Left_High];
400 ir_node *b_l = params[BINOP_Right_Low];
401 ir_node *b_h = params[BINOP_Right_High];
402 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
403 ir_node *l_res, *h_res, *mul, *pEDX, *add;
406 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
417 mul = new_rd_ia32_l_Mul(dbg, irg, block, a_l, b_l);
418 pEDX = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EDX);
419 l_res = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EAX);
421 mul = new_rd_Mul(dbg, irg, block, a_h, b_l, l_mode);
422 add = new_rd_Add(dbg, irg, block, mul, pEDX, l_mode);
423 mul = new_rd_Mul(dbg, irg, block, a_l, b_h, l_mode);
424 h_res = new_rd_Add(dbg, irg, block, add, mul, l_mode);
426 resolve_call(call, l_res, h_res, irg, block);
432 * Map a Minus (a_l, a_h)
434 static int map_Minus(ir_node *call, void *ctx) {
435 ir_graph *irg = current_ir_graph;
436 dbg_info *dbg = get_irn_dbg_info(call);
437 ir_node *block = get_nodes_block(call);
438 ir_node **params = get_Call_param_arr(call);
439 ir_type *method = get_Call_type(call);
440 ir_node *a_l = params[BINOP_Left_Low];
441 ir_node *a_h = params[BINOP_Left_High];
442 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
443 ir_node *l_res, *h_res, *cnst, *res;
446 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
448 /* too bad: we need 0 in a register here */
449 cnst = new_Const_long(l_mode, 0);
451 /* l_res = 0 - a_l */
452 /* h_res = 0 - a_h - carry */
454 res = new_rd_ia32_Minus64Bit(dbg, irg, block, cnst, a_l, a_h);
455 l_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Minus64Bit_low_res);
456 h_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Minus64Bit_high_res);
458 resolve_call(call, l_res, h_res, irg, block);
464 * Map a Abs (a_l, a_h)
466 static int map_Abs(ir_node *call, void *ctx) {
467 ir_graph *irg = current_ir_graph;
468 dbg_info *dbg = get_irn_dbg_info(call);
469 ir_node *block = get_nodes_block(call);
470 ir_node **params = get_Call_param_arr(call);
471 ir_type *method = get_Call_type(call);
472 ir_node *a_l = params[BINOP_Left_Low];
473 ir_node *a_h = params[BINOP_Left_High];
474 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
475 ir_node *l_res, *h_res, *sign, *sub_l, *sub_h, *res;
478 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
481 Code inspired by gcc output :) (although gcc doubles the
482 operation for t1 as t2 and uses t1 for operations with low part
483 and t2 for operations with high part which is actually unnecessary
484 because t1 and t2 represent the same value)
490 h_res = t3 - t1 - carry
494 sign = new_rd_ia32_l_Sar(dbg, irg, block, a_h, new_Const_long(l_mode, 31), l_mode);
495 sub_l = new_rd_ia32_l_Xor(dbg, irg, block, a_l, sign, l_mode);
496 sub_h = new_rd_ia32_l_Xor(dbg, irg, block, a_h, sign, l_mode);
497 res = new_rd_ia32_Sub64Bit(dbg, irg, block, sub_l, sub_h, sign, sign);
498 l_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_low_res);
499 h_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_high_res);
501 resolve_call(call, l_res, h_res, irg, block);
506 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
509 * Maps a Div. Change into a library call
511 static int map_Div(ir_node *call, void *ctx) {
512 ia32_intrinsic_env_t *env = ctx;
513 ir_type *method = get_Call_type(call);
514 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
519 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
521 if (mode_is_signed(l_mode)) {
522 /* 64bit signed Division */
525 /* create library entity */
526 ent = env->divdi3 = new_entity(get_glob_type(), ID("__divdi3"), method);
527 set_entity_visibility(ent, visibility_external_allocated);
528 set_entity_ld_ident(ent, ID("__divdi3"));
531 /* 64bit signed Division */
534 /* create library entity */
535 ent = env->udivdi3 = new_entity(get_glob_type(), ID("__udivdi3"), method);
536 set_entity_visibility(ent, visibility_external_allocated);
537 set_entity_ld_ident(ent, ID("__udivdi3"));
541 ptr = get_Call_ptr(call);
542 set_SymConst_symbol(ptr, sym);
547 * Maps a Mod. Change into a library call
549 static int map_Mod(ir_node *call, void *ctx) {
550 ia32_intrinsic_env_t *env = ctx;
551 ir_type *method = get_Call_type(call);
552 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
557 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
559 if (mode_is_signed(l_mode)) {
560 /* 64bit signed Modulo */
563 /* create library entity */
564 ent = env->moddi3 = new_entity(get_glob_type(), ID("__moddi3"), method);
565 set_entity_visibility(ent, visibility_external_allocated);
566 set_entity_ld_ident(ent, ID("__moddi3"));
569 /* 64bit signed Modulo */
572 /* create library entity */
573 ent = env->umoddi3 = new_entity(get_glob_type(), ID("__umoddi3"), method);
574 set_entity_visibility(ent, visibility_external_allocated);
575 set_entity_ld_ident(ent, ID("__umoddi3"));
579 ptr = get_Call_ptr(call);
580 set_SymConst_symbol(ptr, sym);
587 static int map_Conv(ir_node *call, void *ctx) {
588 ia32_intrinsic_env_t *env = ctx;
589 ir_graph *irg = current_ir_graph;
590 dbg_info *dbg = get_irn_dbg_info(call);
591 ir_node *block = get_nodes_block(call);
592 ir_node **params = get_Call_param_arr(call);
593 ir_type *method = get_Call_type(call);
594 int n = get_Call_n_params(call);
595 int gp_bytes = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode);
597 ir_node *l_res, *h_res, *frame, *fres;
598 ir_node *store_l, *store_h;
599 ir_node *op_mem[2], *mem;
602 /* We have a Conv float -> long long here */
603 ir_node *a_f = params[0];
604 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
605 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
607 assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
609 /* allocate memory on frame to store args */
610 ent = env->irg == irg ? env->d_ll_conv : NULL;
612 ent = env->d_ll_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
617 frame = get_irg_frame(irg);
620 Now we create a node to move the value from a XMM register into
621 x87 FPU because it is unknown here, which FPU is used.
622 This node is killed in transformation phase when not needed.
623 Otherwise it is split up into a movsd + fld
625 a_f = new_rd_ia32_l_SSEtoX87(dbg, irg, block, frame, a_f, get_irg_no_mem(irg), mode_D);
626 set_ia32_frame_ent(a_f, ent);
627 set_ia32_use_frame(a_f);
628 set_ia32_ls_mode(a_f, mode_D);
630 /* store from FPU as Int */
631 a_f = new_rd_ia32_l_vfist(dbg, irg, block, frame, a_f, get_irg_no_mem(irg));
632 set_ia32_frame_ent(a_f, ent);
633 set_ia32_use_frame(a_f);
634 set_ia32_ls_mode(a_f, mode_D);
637 /* load low part of the result */
638 l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
639 set_ia32_frame_ent(l_res, ent);
640 set_ia32_use_frame(l_res);
641 set_ia32_ls_mode(l_res, l_res_mode);
642 l_res = new_r_Proj(irg, block, l_res, l_res_mode, pn_ia32_l_Load_res);
644 /* load hight part of the result */
645 h_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
646 set_ia32_frame_ent(h_res, ent);
647 add_ia32_am_offs_int(h_res, gp_bytes);
648 set_ia32_use_frame(h_res);
649 set_ia32_ls_mode(h_res, h_res_mode);
650 h_res = new_r_Proj(irg, block, h_res, h_res_mode, pn_ia32_l_Load_res);
653 resolve_call(call, l_res, h_res, irg, block);
656 /* We have a Conv long long -> float here */
657 ir_node *a_l = params[BINOP_Left_Low];
658 ir_node *a_h = params[BINOP_Left_High];
659 ir_mode *mode_a_l = get_irn_mode(a_l);
660 ir_mode *mode_a_h = get_irn_mode(a_h);
661 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
663 assert(! mode_is_float(mode_a_l) && ! mode_is_float(mode_a_h) && "unexpected Conv call");
665 /* allocate memory on frame to store args */
666 ent = env->irg == irg ? env->ll_d_conv : NULL;
668 ent = env->ll_d_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
673 frame = get_irg_frame(irg);
675 /* store first arg (low part) */
676 store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, a_l, get_irg_no_mem(irg));
677 set_ia32_frame_ent(store_l, ent);
678 set_ia32_use_frame(store_l);
679 set_ia32_ls_mode(store_l, get_irn_mode(a_l));
682 /* store second arg (high part) */
683 store_h = new_rd_ia32_l_Store(dbg, irg, block, frame, a_h, get_irg_no_mem(irg));
684 set_ia32_frame_ent(store_h, ent);
685 add_ia32_am_offs_int(store_h, gp_bytes);
686 set_ia32_use_frame(store_h);
687 set_ia32_ls_mode(store_h, get_irn_mode(a_h));
690 mem = new_r_Sync(irg, block, 2, op_mem);
692 /* Load arg into x87 FPU (implicit convert) */
693 fres = new_rd_ia32_l_vfild(dbg, irg, block, frame, mem);
694 set_ia32_frame_ent(fres, ent);
695 set_ia32_use_frame(fres);
696 set_ia32_ls_mode(fres, mode_D);
697 mem = new_r_Proj(irg, block, fres, mode_M, pn_ia32_l_vfild_M);
698 fres = new_r_Proj(irg, block, fres, fres_mode, pn_ia32_l_vfild_res);
701 Now we create a node to move the loaded value into a XMM
702 register because it is unknown here, which FPU is used.
703 This node is killed in transformation phase when not needed.
704 Otherwise it is split up into a fst + movsd
706 fres = new_rd_ia32_l_X87toSSE(dbg, irg, block, frame, fres, mem, fres_mode);
707 set_ia32_frame_ent(fres, ent);
708 set_ia32_use_frame(fres);
709 set_ia32_ls_mode(fres, fres_mode);
712 resolve_call(call, fres, NULL, irg, block);
715 assert(0 && "unexpected Conv call");
721 /* Ia32 implementation of intrinsic mapping. */
722 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
723 const ir_mode *imode, const ir_mode *omode,
727 ir_entity **ent = NULL;
728 i_mapper_func mapper;
731 intrinsics = NEW_ARR_F(i_record, 0);
733 switch (get_op_code(op)) {
735 ent = &i_ents[iro_Add];
739 ent = &i_ents[iro_Sub];
743 ent = &i_ents[iro_Shl];
747 ent = &i_ents[iro_Shr];
751 ent = &i_ents[iro_Shrs];
755 ent = &i_ents[iro_Mul];
759 ent = &i_ents[iro_Minus];
763 ent = &i_ents[iro_Abs];
767 ent = &i_ents[iro_Div];
771 ent = &i_ents[iro_Mod];
775 ent = &i_ents[iro_Conv];
779 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
780 return def_create_intrinsic_fkt(method, op, imode, omode, context);
784 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
786 ident *id = mangle(IDENT("L"), get_op_ident(op));
787 *ent = new_entity(get_glob_type(), id, method);
790 elt.i_call.kind = INTRINSIC_CALL;
791 elt.i_call.i_ent = *ent;
792 elt.i_call.i_mapper = mapper;
793 elt.i_call.ctx = context;
794 elt.i_call.link = NULL;
796 ARR_APP1(i_record, intrinsics, elt);