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));
174 /* h_res = SHLD a_h, a_l, cnt */
175 h_res = new_rd_ia32_l_ShlD(dbg, irg, block, a_h, a_l, cnt, l_mode);
177 /* l_res = SHL a_l, cnt */
178 l_res = new_rd_ia32_l_ShlDep(dbg, irg, block, a_l, cnt, h_res, l_mode);
181 resolve_call(call, l_res, h_res, irg, block);
186 upper = get_nodes_block(call);
188 /* h_res = SHLD a_h, a_l, cnt */
189 h1 = new_rd_ia32_l_ShlD(dbg, irg, upper, a_h, a_l, cnt, l_mode);
191 /* l_res = SHL a_l, cnt */
192 l1 = new_rd_ia32_l_ShlDep(dbg, irg, upper, a_l, cnt, h1, l_mode);
194 c_mode = get_irn_mode(cnt);
195 irn = new_r_Const_long(irg, upper, c_mode, 32);
196 irn = new_rd_And(dbg, irg, upper, cnt, irn, c_mode);
197 irn = new_rd_Cmp(dbg, irg, upper, irn, new_r_Const(irg, upper, c_mode, get_mode_null(c_mode)));
198 irn = new_r_Proj(irg, upper, irn, mode_b, pn_Cmp_Eq);
199 cond = new_rd_Cond(dbg, irg, upper, irn);
201 in[0] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_true);
202 in[1] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_false);
204 /* the block for cnt >= 32 */
205 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
207 l2 = new_r_Const(irg, n_block, l_mode, get_mode_null(l_mode));
208 in[1] = new_r_Jmp(irg, n_block);
210 set_irn_in(block, 2, in);
214 l_res = new_r_Phi(irg, block, 2, in, l_mode);
215 set_irn_link(block, l_res);
219 h_res = new_r_Phi(irg, block, 2, in, l_mode);
220 set_irn_link(l_res, h_res);
221 set_irn_link(h_res, NULL);
224 set_nodes_block(call, block);
225 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
226 set_nodes_block(irn, block);
228 resolve_call(call, l_res, h_res, irg, block);
233 * Map a Shr (a_l, a_h, count)
235 static int map_Shr(ir_node *call, void *ctx) {
236 ir_graph *irg = current_ir_graph;
237 dbg_info *dbg = get_irn_dbg_info(call);
238 ir_node *block = get_nodes_block(call);
239 ir_node **params = get_Call_param_arr(call);
240 ir_type *method = get_Call_type(call);
241 ir_node *a_l = params[BINOP_Left_Low];
242 ir_node *a_h = params[BINOP_Left_High];
243 ir_node *cnt = params[BINOP_Right_Low];
244 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
246 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
249 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
252 /* the shift count is a const, create better code */
253 tarval *tv = get_Const_tarval(cnt);
255 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
256 /* simplest case: shift only the higher bits. Note that there is no
257 need to reduce the constant here, this is done by the hardware. */
258 h_res = new_rd_Const(dbg, irg, block, l_mode, get_mode_null(l_mode));
259 l_res = new_rd_Shr(dbg, irg, block, a_h, cnt, l_mode);
261 /* l_res = SHRD a_h:a_l, cnt */
262 l_res = new_rd_ia32_l_ShrD(dbg, irg, block, a_l, a_h, cnt, l_mode);
264 /* h_res = SHR a_h, cnt */
265 h_res = new_rd_ia32_l_ShrDep(dbg, irg, block, a_h, cnt, l_res, l_mode);
267 resolve_call(call, l_res, h_res, irg, block);
272 upper = get_nodes_block(call);
274 /* l_res = SHRD a_h:a_l, cnt */
275 l1 = new_rd_ia32_l_ShrD(dbg, irg, upper, a_l, a_h, cnt, l_mode);
277 /* h_res = SHR a_h, cnt */
278 h1 = new_rd_ia32_l_ShrDep(dbg, irg, upper, a_h, cnt, l1, l_mode);
280 c_mode = get_irn_mode(cnt);
281 irn = new_r_Const_long(irg, upper, c_mode, 32);
282 irn = new_rd_And(dbg, irg, upper, cnt, irn, c_mode);
283 irn = new_rd_Cmp(dbg, irg, upper, irn, new_r_Const(irg, upper, c_mode, get_mode_null(c_mode)));
284 irn = new_r_Proj(irg, upper, irn, mode_b, pn_Cmp_Eq);
285 cond = new_rd_Cond(dbg, irg, upper, irn);
287 in[0] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_true);
288 in[1] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_false);
290 /* the block for cnt >= 32 */
291 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
293 h2 = new_r_Const(irg, n_block, l_mode, get_mode_null(l_mode));
294 in[1] = new_r_Jmp(irg, n_block);
296 set_irn_in(block, 2, in);
300 l_res = new_r_Phi(irg, block, 2, in, l_mode);
301 set_irn_link(block, l_res);
305 h_res = new_r_Phi(irg, block, 2, in, l_mode);
306 set_irn_link(l_res, h_res);
307 set_irn_link(h_res, NULL);
310 set_nodes_block(call, block);
311 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
312 set_nodes_block(irn, block);
314 resolve_call(call, l_res, h_res, irg, block);
319 * Map a Shrs (a_l, a_h, count)
321 static int map_Shrs(ir_node *call, void *ctx) {
322 ir_graph *irg = current_ir_graph;
323 dbg_info *dbg = get_irn_dbg_info(call);
324 ir_node *block = get_nodes_block(call);
325 ir_node **params = get_Call_param_arr(call);
326 ir_type *method = get_Call_type(call);
327 ir_node *a_l = params[BINOP_Left_Low];
328 ir_node *a_h = params[BINOP_Left_High];
329 ir_node *cnt = params[BINOP_Right_Low];
330 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
332 ir_node *l_res, *h_res, *irn, *cond, *upper, *n_block, *l1, *l2, *h1, *h2, *in[2];
335 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
338 /* the shift count is a const, create better code */
339 tarval *tv = get_Const_tarval(cnt);
341 if (tarval_cmp(tv, new_tarval_from_long(32, l_mode)) & (pn_Cmp_Gt|pn_Cmp_Eq)) {
342 /* simplest case: shift only the higher bits. Note that there is no
343 need to reduce the constant here, this is done by the hardware. */
344 ir_mode *c_mode = get_irn_mode(cnt);
346 h_res = new_rd_Shrs(dbg, irg, block, a_h, new_r_Const_long(irg, block, c_mode, 31), l_mode);
347 l_res = new_rd_Shrs(dbg, irg, block, a_h, cnt, l_mode);
349 /* l_res = SHRD a_h:a_l, cnt */
350 l_res = new_rd_ia32_l_ShrD(dbg, irg, block, a_l, a_h, cnt, l_mode);
352 /* h_res = SAR a_h, cnt */
353 h_res = new_rd_ia32_l_SarDep(dbg, irg, block, a_h, cnt, l_res, l_mode);
355 resolve_call(call, l_res, h_res, irg, block);
360 upper = get_nodes_block(call);
362 /* l_res = SHRD a_h:a_l, cnt */
363 l1 = new_rd_ia32_l_ShrD(dbg, irg, upper, a_l, a_h, cnt, l_mode);
365 /* h_res = SAR a_h, cnt */
366 h1 = new_rd_ia32_l_SarDep(dbg, irg, upper, a_h, cnt, l1, l_mode);
368 c_mode = get_irn_mode(cnt);
369 irn = new_r_Const_long(irg, upper, c_mode, 32);
370 irn = new_rd_And(dbg, irg, upper, cnt, irn, c_mode);
371 irn = new_rd_Cmp(dbg, irg, upper, irn, new_r_Const(irg, upper, c_mode, get_mode_null(c_mode)));
372 irn = new_r_Proj(irg, upper, irn, mode_b, pn_Cmp_Eq);
373 cond = new_rd_Cond(dbg, irg, upper, irn);
375 in[0] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_true);
376 in[1] = new_r_Proj(irg, upper, cond, mode_X, pn_Cond_false);
378 /* the block for cnt >= 32 */
379 n_block = new_rd_Block(dbg, irg, 1, &in[1]);
381 h2 = new_rd_Shrs(dbg, irg, n_block, a_h, new_r_Const_long(irg, block, c_mode, 31), l_mode);
382 in[1] = new_r_Jmp(irg, n_block);
384 set_irn_in(block, 2, in);
388 l_res = new_r_Phi(irg, block, 2, in, l_mode);
389 set_irn_link(block, l_res);
393 h_res = new_r_Phi(irg, block, 2, in, l_mode);
394 set_irn_link(l_res, h_res);
395 set_irn_link(h_res, NULL);
398 set_nodes_block(call, block);
399 for (irn = get_irn_link(call); irn != NULL; irn = get_irn_link(irn))
400 set_nodes_block(irn, block);
402 resolve_call(call, l_res, h_res, irg, block);
407 * Map a Mul (a_l, a_h, b_l, b_h)
409 static int map_Mul(ir_node *call, void *ctx) {
410 ir_graph *irg = current_ir_graph;
411 dbg_info *dbg = get_irn_dbg_info(call);
412 ir_node *block = get_nodes_block(call);
413 ir_node **params = get_Call_param_arr(call);
414 ir_type *method = get_Call_type(call);
415 ir_node *a_l = params[BINOP_Left_Low];
416 ir_node *a_h = params[BINOP_Left_High];
417 ir_node *b_l = params[BINOP_Right_Low];
418 ir_node *b_h = params[BINOP_Right_High];
419 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
420 ir_node *l_res, *h_res, *mul, *pEDX, *add;
423 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
434 if (is_Shrs(a_h) && get_Shrs_left(a_h) == a_l &&
435 is_Shrs(b_h) && get_Shrs_left(b_h) == b_l) {
436 ir_node *c1 = get_Shrs_right(a_h);
438 if (c1 == get_Shrs_right(b_h) && is_Const(c1)) {
439 tarval *tv = get_Const_tarval(c1);
441 if (tarval_is_long(tv) && get_tarval_long(tv) == 31) {
442 /* it's a 32 * 32 = 64 signed multiplication */
444 mul = new_rd_ia32_l_IMul(dbg, irg, block, a_l, b_l);
445 h_res = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EDX);
446 l_res = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EAX);
453 mul = new_rd_ia32_l_Mul(dbg, irg, block, a_l, b_l);
454 pEDX = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EDX);
455 l_res = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EAX);
457 mul = new_rd_Mul(dbg, irg, block, a_h, b_l, l_mode);
458 add = new_rd_Add(dbg, irg, block, mul, pEDX, l_mode);
459 mul = new_rd_Mul(dbg, irg, block, a_l, b_h, l_mode);
460 h_res = new_rd_Add(dbg, irg, block, add, mul, l_mode);
463 resolve_call(call, l_res, h_res, irg, block);
469 * Map a Minus (a_l, a_h)
471 static int map_Minus(ir_node *call, void *ctx) {
472 ir_graph *irg = current_ir_graph;
473 dbg_info *dbg = get_irn_dbg_info(call);
474 ir_node *block = get_nodes_block(call);
475 ir_node **params = get_Call_param_arr(call);
476 ir_type *method = get_Call_type(call);
477 ir_node *a_l = params[BINOP_Left_Low];
478 ir_node *a_h = params[BINOP_Left_High];
479 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
480 ir_node *l_res, *h_res, *cnst, *res;
483 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
485 /* too bad: we need 0 in a register here */
486 cnst = new_Const_long(l_mode, 0);
488 /* l_res = 0 - a_l */
489 /* h_res = 0 - a_h - carry */
491 res = new_rd_ia32_Minus64Bit(dbg, irg, block, cnst, a_l, a_h);
492 l_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Minus64Bit_low_res);
493 h_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Minus64Bit_high_res);
495 resolve_call(call, l_res, h_res, irg, block);
501 * Map a Abs (a_l, a_h)
503 static int map_Abs(ir_node *call, void *ctx) {
504 ir_graph *irg = current_ir_graph;
505 dbg_info *dbg = get_irn_dbg_info(call);
506 ir_node *block = get_nodes_block(call);
507 ir_node **params = get_Call_param_arr(call);
508 ir_type *method = get_Call_type(call);
509 ir_node *a_l = params[BINOP_Left_Low];
510 ir_node *a_h = params[BINOP_Left_High];
511 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
512 ir_node *l_res, *h_res, *sign, *sub_l, *sub_h, *res;
515 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
518 Code inspired by gcc output :) (although gcc doubles the
519 operation for t1 as t2 and uses t1 for operations with low part
520 and t2 for operations with high part which is actually unnecessary
521 because t1 and t2 represent the same value)
527 h_res = t3 - t1 - carry
531 sign = new_rd_ia32_l_Sar(dbg, irg, block, a_h, new_Const_long(l_mode, 31), l_mode);
532 sub_l = new_rd_ia32_l_Xor(dbg, irg, block, a_l, sign, l_mode);
533 sub_h = new_rd_ia32_l_Xor(dbg, irg, block, a_h, sign, l_mode);
534 res = new_rd_ia32_Sub64Bit(dbg, irg, block, sub_l, sub_h, sign, sign);
535 l_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_low_res);
536 h_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_high_res);
538 resolve_call(call, l_res, h_res, irg, block);
543 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
546 * Maps a Div. Change into a library call
548 static int map_Div(ir_node *call, void *ctx) {
549 ia32_intrinsic_env_t *env = ctx;
550 ir_type *method = get_Call_type(call);
551 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
556 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
558 if (mode_is_signed(l_mode)) {
559 /* 64bit signed Division */
562 /* create library entity */
563 ent = env->divdi3 = new_entity(get_glob_type(), ID("__divdi3"), method);
564 set_entity_visibility(ent, visibility_external_allocated);
565 set_entity_ld_ident(ent, ID("__divdi3"));
568 /* 64bit signed Division */
571 /* create library entity */
572 ent = env->udivdi3 = new_entity(get_glob_type(), ID("__udivdi3"), method);
573 set_entity_visibility(ent, visibility_external_allocated);
574 set_entity_ld_ident(ent, ID("__udivdi3"));
578 ptr = get_Call_ptr(call);
579 set_SymConst_symbol(ptr, sym);
584 * Maps a Mod. Change into a library call
586 static int map_Mod(ir_node *call, void *ctx) {
587 ia32_intrinsic_env_t *env = ctx;
588 ir_type *method = get_Call_type(call);
589 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
594 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
596 if (mode_is_signed(l_mode)) {
597 /* 64bit signed Modulo */
600 /* create library entity */
601 ent = env->moddi3 = new_entity(get_glob_type(), ID("__moddi3"), method);
602 set_entity_visibility(ent, visibility_external_allocated);
603 set_entity_ld_ident(ent, ID("__moddi3"));
606 /* 64bit signed Modulo */
609 /* create library entity */
610 ent = env->umoddi3 = new_entity(get_glob_type(), ID("__umoddi3"), method);
611 set_entity_visibility(ent, visibility_external_allocated);
612 set_entity_ld_ident(ent, ID("__umoddi3"));
616 ptr = get_Call_ptr(call);
617 set_SymConst_symbol(ptr, sym);
624 static int map_Conv(ir_node *call, void *ctx) {
625 ia32_intrinsic_env_t *env = ctx;
626 ir_graph *irg = current_ir_graph;
627 dbg_info *dbg = get_irn_dbg_info(call);
628 ir_node *block = get_nodes_block(call);
629 ir_node **params = get_Call_param_arr(call);
630 ir_type *method = get_Call_type(call);
631 int n = get_Call_n_params(call);
632 int gp_bytes = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode);
634 ir_node *l_res, *h_res, *frame, *fres;
635 ir_node *store_l, *store_h;
636 ir_node *op_mem[2], *mem;
639 /* We have a Conv float -> long long here */
640 ir_node *a_f = params[0];
641 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
642 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
644 assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
646 /* allocate memory on frame to store args */
647 ent = env->irg == irg ? env->d_ll_conv : NULL;
649 ent = env->d_ll_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
654 frame = get_irg_frame(irg);
657 Now we create a node to move the value from a XMM register into
658 x87 FPU because it is unknown here, which FPU is used.
659 This node is killed in transformation phase when not needed.
660 Otherwise it is split up into a movsd + fld
662 a_f = new_rd_ia32_l_SSEtoX87(dbg, irg, block, frame, a_f, get_irg_no_mem(irg), mode_D);
663 set_ia32_frame_ent(a_f, ent);
664 set_ia32_use_frame(a_f);
665 set_ia32_ls_mode(a_f, mode_D);
667 /* store from FPU as Int */
668 a_f = new_rd_ia32_l_vfist(dbg, irg, block, frame, a_f, get_irg_no_mem(irg));
669 set_ia32_frame_ent(a_f, ent);
670 set_ia32_use_frame(a_f);
671 set_ia32_ls_mode(a_f, mode_D);
674 /* load low part of the result */
675 l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
676 set_ia32_frame_ent(l_res, ent);
677 set_ia32_use_frame(l_res);
678 set_ia32_ls_mode(l_res, l_res_mode);
679 l_res = new_r_Proj(irg, block, l_res, l_res_mode, pn_ia32_l_Load_res);
681 /* load hight part of the result */
682 h_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
683 set_ia32_frame_ent(h_res, ent);
684 add_ia32_am_offs_int(h_res, gp_bytes);
685 set_ia32_use_frame(h_res);
686 set_ia32_ls_mode(h_res, h_res_mode);
687 h_res = new_r_Proj(irg, block, h_res, h_res_mode, pn_ia32_l_Load_res);
690 resolve_call(call, l_res, h_res, irg, block);
693 /* We have a Conv long long -> float here */
694 ir_node *a_l = params[BINOP_Left_Low];
695 ir_node *a_h = params[BINOP_Left_High];
696 ir_mode *mode_a_l = get_irn_mode(a_l);
697 ir_mode *mode_a_h = get_irn_mode(a_h);
698 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
700 assert(! mode_is_float(mode_a_l) && ! mode_is_float(mode_a_h) && "unexpected Conv call");
702 /* allocate memory on frame to store args */
703 ent = env->irg == irg ? env->ll_d_conv : NULL;
705 ent = env->ll_d_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
710 frame = get_irg_frame(irg);
712 /* store first arg (low part) */
713 store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, a_l, get_irg_no_mem(irg));
714 set_ia32_frame_ent(store_l, ent);
715 set_ia32_use_frame(store_l);
716 set_ia32_ls_mode(store_l, get_irn_mode(a_l));
719 /* store second arg (high part) */
720 store_h = new_rd_ia32_l_Store(dbg, irg, block, frame, a_h, get_irg_no_mem(irg));
721 set_ia32_frame_ent(store_h, ent);
722 add_ia32_am_offs_int(store_h, gp_bytes);
723 set_ia32_use_frame(store_h);
724 set_ia32_ls_mode(store_h, get_irn_mode(a_h));
727 mem = new_r_Sync(irg, block, 2, op_mem);
729 /* Load arg into x87 FPU (implicit convert) */
730 fres = new_rd_ia32_l_vfild(dbg, irg, block, frame, mem);
731 set_ia32_frame_ent(fres, ent);
732 set_ia32_use_frame(fres);
733 set_ia32_ls_mode(fres, mode_D);
734 mem = new_r_Proj(irg, block, fres, mode_M, pn_ia32_l_vfild_M);
735 fres = new_r_Proj(irg, block, fres, fres_mode, pn_ia32_l_vfild_res);
738 Now we create a node to move the loaded value into a XMM
739 register because it is unknown here, which FPU is used.
740 This node is killed in transformation phase when not needed.
741 Otherwise it is split up into a fst + movsd
743 fres = new_rd_ia32_l_X87toSSE(dbg, irg, block, frame, fres, mem, fres_mode);
744 set_ia32_frame_ent(fres, ent);
745 set_ia32_use_frame(fres);
746 set_ia32_ls_mode(fres, fres_mode);
749 resolve_call(call, fres, NULL, irg, block);
752 assert(0 && "unexpected Conv call");
758 /* Ia32 implementation of intrinsic mapping. */
759 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
760 const ir_mode *imode, const ir_mode *omode,
764 ir_entity **ent = NULL;
765 i_mapper_func mapper;
768 intrinsics = NEW_ARR_F(i_record, 0);
770 switch (get_op_code(op)) {
772 ent = &i_ents[iro_Add];
776 ent = &i_ents[iro_Sub];
780 ent = &i_ents[iro_Shl];
784 ent = &i_ents[iro_Shr];
788 ent = &i_ents[iro_Shrs];
792 ent = &i_ents[iro_Mul];
796 ent = &i_ents[iro_Minus];
800 ent = &i_ents[iro_Abs];
804 ent = &i_ents[iro_Div];
808 ent = &i_ents[iro_Mod];
812 ent = &i_ents[iro_Conv];
816 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
817 return def_create_intrinsic_fkt(method, op, imode, omode, context);
821 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
823 ident *id = mangle(IDENT("L"), get_op_ident(op));
824 *ent = new_entity(get_glob_type(), id, method);
827 elt.i_call.kind = INTRINSIC_CALL;
828 elt.i_call.i_ent = *ent;
829 elt.i_call.i_mapper = mapper;
830 elt.i_call.ctx = context;
831 elt.i_call.link = NULL;
833 ARR_APP1(i_record, intrinsics, elt);