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 mul = new_rd_ia32_l_Mul(dbg, irg, block, a_l, b_l);
435 pEDX = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EDX);
436 l_res = new_rd_Proj(dbg, irg, block, mul, l_mode, pn_ia32_l_Mul_EAX);
438 mul = new_rd_Mul(dbg, irg, block, a_h, b_l, l_mode);
439 add = new_rd_Add(dbg, irg, block, mul, pEDX, l_mode);
440 mul = new_rd_Mul(dbg, irg, block, a_l, b_h, l_mode);
441 h_res = new_rd_Add(dbg, irg, block, add, mul, l_mode);
443 resolve_call(call, l_res, h_res, irg, block);
449 * Map a Minus (a_l, a_h)
451 static int map_Minus(ir_node *call, void *ctx) {
452 ir_graph *irg = current_ir_graph;
453 dbg_info *dbg = get_irn_dbg_info(call);
454 ir_node *block = get_nodes_block(call);
455 ir_node **params = get_Call_param_arr(call);
456 ir_type *method = get_Call_type(call);
457 ir_node *a_l = params[BINOP_Left_Low];
458 ir_node *a_h = params[BINOP_Left_High];
459 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
460 ir_node *l_res, *h_res, *cnst, *res;
463 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
465 /* too bad: we need 0 in a register here */
466 cnst = new_Const_long(l_mode, 0);
468 /* l_res = 0 - a_l */
469 /* h_res = 0 - a_h - carry */
471 res = new_rd_ia32_Minus64Bit(dbg, irg, block, cnst, a_l, a_h);
472 l_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Minus64Bit_low_res);
473 h_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Minus64Bit_high_res);
475 resolve_call(call, l_res, h_res, irg, block);
481 * Map a Abs (a_l, a_h)
483 static int map_Abs(ir_node *call, void *ctx) {
484 ir_graph *irg = current_ir_graph;
485 dbg_info *dbg = get_irn_dbg_info(call);
486 ir_node *block = get_nodes_block(call);
487 ir_node **params = get_Call_param_arr(call);
488 ir_type *method = get_Call_type(call);
489 ir_node *a_l = params[BINOP_Left_Low];
490 ir_node *a_h = params[BINOP_Left_High];
491 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
492 ir_node *l_res, *h_res, *sign, *sub_l, *sub_h, *res;
495 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
498 Code inspired by gcc output :) (although gcc doubles the
499 operation for t1 as t2 and uses t1 for operations with low part
500 and t2 for operations with high part which is actually unnecessary
501 because t1 and t2 represent the same value)
507 h_res = t3 - t1 - carry
511 sign = new_rd_ia32_l_Sar(dbg, irg, block, a_h, new_Const_long(l_mode, 31), l_mode);
512 sub_l = new_rd_ia32_l_Xor(dbg, irg, block, a_l, sign, l_mode);
513 sub_h = new_rd_ia32_l_Xor(dbg, irg, block, a_h, sign, l_mode);
514 res = new_rd_ia32_Sub64Bit(dbg, irg, block, sub_l, sub_h, sign, sign);
515 l_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_low_res);
516 h_res = new_r_Proj(irg, block, res, l_mode, pn_ia32_Sub64Bit_high_res);
518 resolve_call(call, l_res, h_res, irg, block);
523 #define ID(x) new_id_from_chars(x, sizeof(x)-1)
526 * Maps a Div. Change into a library call
528 static int map_Div(ir_node *call, void *ctx) {
529 ia32_intrinsic_env_t *env = ctx;
530 ir_type *method = get_Call_type(call);
531 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
536 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
538 if (mode_is_signed(l_mode)) {
539 /* 64bit signed Division */
542 /* create library entity */
543 ent = env->divdi3 = new_entity(get_glob_type(), ID("__divdi3"), method);
544 set_entity_visibility(ent, visibility_external_allocated);
545 set_entity_ld_ident(ent, ID("__divdi3"));
548 /* 64bit signed Division */
551 /* create library entity */
552 ent = env->udivdi3 = new_entity(get_glob_type(), ID("__udivdi3"), method);
553 set_entity_visibility(ent, visibility_external_allocated);
554 set_entity_ld_ident(ent, ID("__udivdi3"));
558 ptr = get_Call_ptr(call);
559 set_SymConst_symbol(ptr, sym);
564 * Maps a Mod. Change into a library call
566 static int map_Mod(ir_node *call, void *ctx) {
567 ia32_intrinsic_env_t *env = ctx;
568 ir_type *method = get_Call_type(call);
569 ir_mode *l_mode = get_type_mode(get_method_res_type(method, 0));
574 assert(l_mode == get_type_mode(get_method_res_type(method, 1)) && "64bit lowered into different modes");
576 if (mode_is_signed(l_mode)) {
577 /* 64bit signed Modulo */
580 /* create library entity */
581 ent = env->moddi3 = new_entity(get_glob_type(), ID("__moddi3"), method);
582 set_entity_visibility(ent, visibility_external_allocated);
583 set_entity_ld_ident(ent, ID("__moddi3"));
586 /* 64bit signed Modulo */
589 /* create library entity */
590 ent = env->umoddi3 = new_entity(get_glob_type(), ID("__umoddi3"), method);
591 set_entity_visibility(ent, visibility_external_allocated);
592 set_entity_ld_ident(ent, ID("__umoddi3"));
596 ptr = get_Call_ptr(call);
597 set_SymConst_symbol(ptr, sym);
604 static int map_Conv(ir_node *call, void *ctx) {
605 ia32_intrinsic_env_t *env = ctx;
606 ir_graph *irg = current_ir_graph;
607 dbg_info *dbg = get_irn_dbg_info(call);
608 ir_node *block = get_nodes_block(call);
609 ir_node **params = get_Call_param_arr(call);
610 ir_type *method = get_Call_type(call);
611 int n = get_Call_n_params(call);
612 int gp_bytes = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode);
614 ir_node *l_res, *h_res, *frame, *fres;
615 ir_node *store_l, *store_h;
616 ir_node *op_mem[2], *mem;
619 /* We have a Conv float -> long long here */
620 ir_node *a_f = params[0];
621 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
622 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
624 assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call");
626 /* allocate memory on frame to store args */
627 ent = env->irg == irg ? env->d_ll_conv : NULL;
629 ent = env->d_ll_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
634 frame = get_irg_frame(irg);
637 Now we create a node to move the value from a XMM register into
638 x87 FPU because it is unknown here, which FPU is used.
639 This node is killed in transformation phase when not needed.
640 Otherwise it is split up into a movsd + fld
642 a_f = new_rd_ia32_l_SSEtoX87(dbg, irg, block, frame, a_f, get_irg_no_mem(irg), mode_D);
643 set_ia32_frame_ent(a_f, ent);
644 set_ia32_use_frame(a_f);
645 set_ia32_ls_mode(a_f, mode_D);
647 /* store from FPU as Int */
648 a_f = new_rd_ia32_l_vfist(dbg, irg, block, frame, a_f, get_irg_no_mem(irg));
649 set_ia32_frame_ent(a_f, ent);
650 set_ia32_use_frame(a_f);
651 set_ia32_ls_mode(a_f, mode_D);
654 /* load low part of the result */
655 l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
656 set_ia32_frame_ent(l_res, ent);
657 set_ia32_use_frame(l_res);
658 set_ia32_ls_mode(l_res, l_res_mode);
659 l_res = new_r_Proj(irg, block, l_res, l_res_mode, pn_ia32_l_Load_res);
661 /* load hight part of the result */
662 h_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem);
663 set_ia32_frame_ent(h_res, ent);
664 add_ia32_am_offs_int(h_res, gp_bytes);
665 set_ia32_use_frame(h_res);
666 set_ia32_ls_mode(h_res, h_res_mode);
667 h_res = new_r_Proj(irg, block, h_res, h_res_mode, pn_ia32_l_Load_res);
670 resolve_call(call, l_res, h_res, irg, block);
673 /* We have a Conv long long -> float here */
674 ir_node *a_l = params[BINOP_Left_Low];
675 ir_node *a_h = params[BINOP_Left_High];
676 ir_mode *mode_a_l = get_irn_mode(a_l);
677 ir_mode *mode_a_h = get_irn_mode(a_h);
678 ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0));
680 assert(! mode_is_float(mode_a_l) && ! mode_is_float(mode_a_h) && "unexpected Conv call");
682 /* allocate memory on frame to store args */
683 ent = env->irg == irg ? env->ll_d_conv : NULL;
685 ent = env->ll_d_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0);
690 frame = get_irg_frame(irg);
692 /* store first arg (low part) */
693 store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, a_l, get_irg_no_mem(irg));
694 set_ia32_frame_ent(store_l, ent);
695 set_ia32_use_frame(store_l);
696 set_ia32_ls_mode(store_l, get_irn_mode(a_l));
699 /* store second arg (high part) */
700 store_h = new_rd_ia32_l_Store(dbg, irg, block, frame, a_h, get_irg_no_mem(irg));
701 set_ia32_frame_ent(store_h, ent);
702 add_ia32_am_offs_int(store_h, gp_bytes);
703 set_ia32_use_frame(store_h);
704 set_ia32_ls_mode(store_h, get_irn_mode(a_h));
707 mem = new_r_Sync(irg, block, 2, op_mem);
709 /* Load arg into x87 FPU (implicit convert) */
710 fres = new_rd_ia32_l_vfild(dbg, irg, block, frame, mem);
711 set_ia32_frame_ent(fres, ent);
712 set_ia32_use_frame(fres);
713 set_ia32_ls_mode(fres, mode_D);
714 mem = new_r_Proj(irg, block, fres, mode_M, pn_ia32_l_vfild_M);
715 fres = new_r_Proj(irg, block, fres, fres_mode, pn_ia32_l_vfild_res);
718 Now we create a node to move the loaded value into a XMM
719 register because it is unknown here, which FPU is used.
720 This node is killed in transformation phase when not needed.
721 Otherwise it is split up into a fst + movsd
723 fres = new_rd_ia32_l_X87toSSE(dbg, irg, block, frame, fres, mem, fres_mode);
724 set_ia32_frame_ent(fres, ent);
725 set_ia32_use_frame(fres);
726 set_ia32_ls_mode(fres, fres_mode);
729 resolve_call(call, fres, NULL, irg, block);
732 assert(0 && "unexpected Conv call");
738 /* Ia32 implementation of intrinsic mapping. */
739 ir_entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
740 const ir_mode *imode, const ir_mode *omode,
744 ir_entity **ent = NULL;
745 i_mapper_func mapper;
748 intrinsics = NEW_ARR_F(i_record, 0);
750 switch (get_op_code(op)) {
752 ent = &i_ents[iro_Add];
756 ent = &i_ents[iro_Sub];
760 ent = &i_ents[iro_Shl];
764 ent = &i_ents[iro_Shr];
768 ent = &i_ents[iro_Shrs];
772 ent = &i_ents[iro_Mul];
776 ent = &i_ents[iro_Minus];
780 ent = &i_ents[iro_Abs];
784 ent = &i_ents[iro_Div];
788 ent = &i_ents[iro_Mod];
792 ent = &i_ents[iro_Conv];
796 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
797 return def_create_intrinsic_fkt(method, op, imode, omode, context);
801 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
803 ident *id = mangle(IDENT("L"), get_op_ident(op));
804 *ent = new_entity(get_glob_type(), id, method);
807 elt.i_call.kind = INTRINSIC_CALL;
808 elt.i_call.i_ent = *ent;
809 elt.i_call.i_mapper = mapper;
810 elt.i_call.ctx = context;
811 elt.i_call.link = NULL;
813 ARR_APP1(i_record, intrinsics, elt);