2 * This file implements the mapping of 64Bit intrinsic functions to
3 * code or library calls.
17 #include "lower_intrinsics.h"
22 #include "ia32_new_nodes.h"
24 /** The array of all intrinsics that must be mapped. */
25 static i_record *intrinsics;
27 /** An array to cache all entities */
28 static entity *i_ents[iro_MaxOpcode];
31 * Maps all intrinsic calls that the backend support
32 * and map all instructions the backend did not support
35 void ia32_handle_intrinsics(void) {
36 if (intrinsics && ARR_LEN(intrinsics) > 0)
37 lower_intrinsics(intrinsics, ARR_LEN(intrinsics));
40 #define BINOP_Left_Low 0
41 #define BINOP_Left_High 1
42 #define BINOP_Right_Low 2
43 #define BINOP_Right_High 3
45 static void resolve_call(ir_node *call, ir_node *l_res, ir_node *h_res, ir_graph *irg, ir_node *block) {
50 res = new_r_Tuple(irg, block, 2, in);
52 turn_into_tuple(call, pn_Call_max);
53 set_Tuple_pred(call, pn_Call_M_regular, get_irg_no_mem(irg));
54 set_Tuple_pred(call, pn_Call_X_except, get_irg_bad(irg));
55 set_Tuple_pred(call, pn_Call_T_result, res);
56 set_Tuple_pred(call, pn_Call_M_except, get_irg_bad(irg));
57 set_Tuple_pred(call, pn_Call_P_value_res_base, get_irg_bad(irg));
61 * Map an Add (a_l, a_h, b_l, b_h)
63 static int map_Add(ir_node *call, void *ctx) {
64 ir_graph *irg = current_ir_graph;
65 dbg_info *dbg = get_irn_dbg_info(call);
66 ir_node *block = get_nodes_block(call);
67 ir_node **params = get_Call_param_arr(call);
68 ir_type *method = get_Call_type(call);
69 ir_node *a_l = params[BINOP_Left_Low];
70 ir_node *a_h = params[BINOP_Left_High];
71 ir_node *b_l = params[BINOP_Right_Low];
72 ir_node *b_h = params[BINOP_Right_High];
73 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
74 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
75 ir_node *l_res, *h_res;
77 /* l_res = a_l + b_l */
78 l_res = new_rd_ia32_l_Add(dbg, irg, block, a_l, b_l, l_res_mode);
80 /* h_res = a_h + b_h + carry */
81 h_res = new_rd_ia32_l_AddC(dbg, irg, block, a_h, b_h, h_res_mode);
83 resolve_call(call, l_res, h_res, irg, block);
88 * Map a Sub (a_l, a_h, b_l, b_h)
90 static int map_Sub(ir_node *call, void *ctx) {
91 ir_graph *irg = current_ir_graph;
92 dbg_info *dbg = get_irn_dbg_info(call);
93 ir_node *block = get_nodes_block(call);
94 ir_node **params = get_Call_param_arr(call);
95 ir_type *method = get_Call_type(call);
96 ir_node *a_l = params[BINOP_Left_Low];
97 ir_node *a_h = params[BINOP_Left_High];
98 ir_node *b_l = params[BINOP_Right_Low];
99 ir_node *b_h = params[BINOP_Right_High];
100 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
101 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
102 ir_node *l_res, *h_res;
104 /* l_res = a_l - b_l */
105 l_res = new_rd_ia32_l_Sub(dbg, irg, block, a_l, b_l, l_res_mode);
107 /* h_res = a_h - b_h - carry */
108 h_res = new_rd_ia32_l_SubC(dbg, irg, block, a_h, b_h, h_res_mode);
110 resolve_call(call, l_res, h_res, irg, block);
116 * Map a Shl (a_l, a_h, count)
118 static int map_Shl(ir_node *call, void *ctx) {
119 ir_graph *irg = current_ir_graph;
120 dbg_info *dbg = get_irn_dbg_info(call);
121 ir_node *block = get_nodes_block(call);
122 ir_node **params = get_Call_param_arr(call);
123 ir_type *method = get_Call_type(call);
124 ir_node *a_l = params[BINOP_Left_Low];
125 ir_node *a_h = params[BINOP_Left_High];
126 ir_node *cnt = params[BINOP_Right_Low];
127 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
128 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
129 ir_node *l_res, *h_res;
131 /* h_res = SHLD a_h, a_l, cnt */
132 l_res = new_rd_ia32_l_ShlD(dbg, irg, block, a_h, a_l, cnt, l_res_mode);
134 /* l_res = SHL a_l, cnt */
135 h_res = new_rd_ia32_l_Shl(dbg, irg, block, a_l, cnt, h_res_mode);
137 resolve_call(call, l_res, h_res, irg, block);
143 * Map a Shr (a_l, a_h, count)
145 static int map_Shr(ir_node *call, void *ctx) {
146 ir_graph *irg = current_ir_graph;
147 dbg_info *dbg = get_irn_dbg_info(call);
148 ir_node *block = get_nodes_block(call);
149 ir_node **params = get_Call_param_arr(call);
150 ir_type *method = get_Call_type(call);
151 ir_node *a_l = params[BINOP_Left_Low];
152 ir_node *a_h = params[BINOP_Left_High];
153 ir_node *cnt = params[BINOP_Right_Low];
154 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
155 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
156 ir_node *l_res, *h_res;
158 /* l_res = SHRD a_l, a_h, cnt */
159 l_res = new_rd_ia32_l_ShrD(dbg, irg, block, a_l, a_h, cnt, l_res_mode);
161 /* h_res = SHR a_h, cnt */
162 h_res = new_rd_ia32_l_Shr(dbg, irg, block, a_h, cnt, h_res_mode);
164 resolve_call(call, l_res, h_res, irg, block);
170 * Map a Shrs (a_l, a_h, count)
172 static int map_Shrs(ir_node *call, void *ctx) {
173 ir_graph *irg = current_ir_graph;
174 dbg_info *dbg = get_irn_dbg_info(call);
175 ir_node *block = get_nodes_block(call);
176 ir_node **params = get_Call_param_arr(call);
177 ir_type *method = get_Call_type(call);
178 ir_node *a_l = params[BINOP_Left_Low];
179 ir_node *a_h = params[BINOP_Left_High];
180 ir_node *cnt = params[BINOP_Right_Low];
181 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
182 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
183 ir_node *l_res, *h_res;
185 /* l_res = SHRD a_l, a_h, cnt */
186 l_res = new_rd_ia32_l_ShrD(dbg, irg, block, a_l, a_h, cnt, l_res_mode);
188 /* h_res = SAR a_h, cnt */
189 h_res = new_rd_ia32_l_Shrs(dbg, irg, block, a_h, cnt, h_res_mode);
191 resolve_call(call, l_res, h_res, irg, block);
197 * Map a Mul (a_l, a_h, b_l, b_h)
199 static int map_Mul(ir_node *call, void *ctx) {
200 ir_graph *irg = current_ir_graph;
201 dbg_info *dbg = get_irn_dbg_info(call);
202 ir_node *block = get_nodes_block(call);
203 ir_node **params = get_Call_param_arr(call);
204 ir_type *method = get_Call_type(call);
205 ir_node *a_l = params[BINOP_Left_Low];
206 ir_node *a_h = params[BINOP_Left_High];
207 ir_node *b_l = params[BINOP_Right_Low];
208 ir_node *b_h = params[BINOP_Right_High];
209 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
210 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
211 ir_node *l_res, *h_res, *mul, *pEDX, *add;
222 mul = new_rd_ia32_l_MulS(dbg, irg, block, a_l, b_l);
223 pEDX = new_rd_Proj(dbg, irg, block, mul, l_res_mode, pn_ia32_l_MulS_EDX);
224 l_res = new_rd_Proj(dbg, irg, block, mul, l_res_mode, pn_ia32_l_MulS_EAX);
226 mul = new_rd_ia32_l_Mul(dbg, irg, block, a_h, b_l, h_res_mode);
227 add = new_rd_ia32_l_Add(dbg, irg, block, mul, pEDX, h_res_mode);
228 mul = new_rd_ia32_l_Mul(dbg, irg, block, a_l, b_h, h_res_mode);
229 h_res = new_rd_ia32_l_Add(dbg, irg, block, add, mul, h_res_mode);
231 resolve_call(call, l_res, h_res, irg, block);
237 * Map a Minus (a_l, a_h)
239 static int map_Minus(ir_node *call, void *ctx) {
240 ir_graph *irg = current_ir_graph;
241 dbg_info *dbg = get_irn_dbg_info(call);
242 ir_node *block = get_nodes_block(call);
243 ir_node **params = get_Call_param_arr(call);
244 ir_type *method = get_Call_type(call);
245 ir_node *a_l = params[BINOP_Left_Low];
246 ir_node *a_h = params[BINOP_Left_High];
247 ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0));
248 ir_mode *h_res_mode = get_type_mode(get_method_res_type(method, 1));
249 ir_node *l_res, *h_res, *cnst;
251 /* l_res = 0 - a_l */
252 l_res = new_rd_ia32_l_Minus(dbg, irg, block, a_l, l_res_mode);
254 /* h_res = 0 - a_h - carry */
256 /* too bad: we need 0 in a register here */
257 cnst = new_Const_long(h_res_mode, 0);
258 h_res = new_rd_ia32_l_SubC(dbg, irg, block, cnst, a_h, h_res_mode);
260 resolve_call(call, l_res, h_res, irg, block);
265 /* Ia32 implementation of intrinsic mapping. */
266 entity *ia32_create_intrinsic_fkt(ir_type *method, const ir_op *op,
267 const ir_mode *imode, const ir_mode *omode,
272 i_mapper_func mapper;
275 intrinsics = NEW_ARR_F(i_record, 0);
277 switch (get_op_code(op)) {
279 ent = &i_ents[iro_Add];
283 ent = &i_ents[iro_Sub];
287 ent = &i_ents[iro_Shl];
291 ent = &i_ents[iro_Shr];
295 ent = &i_ents[iro_Shrs];
299 ent = &i_ents[iro_Mul];
303 fprintf(stderr, "FIXME: unhandled op for ia32 intrinsic function %s\n", get_id_str(op->name));
304 return def_create_intrinsic_fkt(method, op, imode, omode, context);
308 #define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
310 ident *id = mangle(IDENT("L"), get_op_ident(op));
311 *ent = new_entity(get_glob_type(), id, method);
314 elt.i_call.kind = INTRINSIC_CALL;
315 elt.i_call.i_ent = *ent;
316 elt.i_call.i_mapper = mapper;
317 elt.i_call.ctx = context;
318 elt.i_call.link = NULL;
320 ARR_APP1(i_record, intrinsics, elt);