16 #include "ia32_nodes_attr.h"
17 #include "../arch/archop.h" /* we need this for Min and Max nodes */
18 #include "ia32_transform.h"
19 #include "ia32_new_nodes.h"
21 #include "gen_ia32_regalloc_if.h"
23 extern ir_op *get_op_Mulh(void);
25 static int maxnum_gpreg_args = 3; /* maximum number of int arguments passed in registers; default 3 */
26 static int maxnum_fpreg_args = 5; /* maximum number of float arguments passed in registers; default 5 */
28 static const arch_register_req_t **current_gpreg_param_req;
29 static const arch_register_req_t **current_fpreg_param_req;
31 /* this is the order of the assigned registers usesd for parameter passing */
33 const arch_register_req_t *gpreg_param_req_std[] = {
34 &ia32_default_req_ia32_general_purpose_eax,
35 &ia32_default_req_ia32_general_purpose_ecx,
36 &ia32_default_req_ia32_general_purpose_edx,
37 &ia32_default_req_ia32_general_purpose_ebx,
38 &ia32_default_req_ia32_general_purpose_edi,
39 &ia32_default_req_ia32_general_purpose_esi
42 const arch_register_req_t *gpreg_param_req_this[] = {
43 &ia32_default_req_ia32_general_purpose_ecx,
44 &ia32_default_req_ia32_general_purpose_eax,
45 &ia32_default_req_ia32_general_purpose_edx,
46 &ia32_default_req_ia32_general_purpose_ebx,
47 &ia32_default_req_ia32_general_purpose_edi,
48 &ia32_default_req_ia32_general_purpose_esi
51 const arch_register_req_t *fpreg_param_req_std[] = {
52 &ia32_default_req_ia32_floating_point_xmm0,
53 &ia32_default_req_ia32_floating_point_xmm1,
54 &ia32_default_req_ia32_floating_point_xmm2,
55 &ia32_default_req_ia32_floating_point_xmm3,
56 &ia32_default_req_ia32_floating_point_xmm4,
57 &ia32_default_req_ia32_floating_point_xmm5,
58 &ia32_default_req_ia32_floating_point_xmm6,
59 &ia32_default_req_ia32_floating_point_xmm7
62 const arch_register_req_t *fpreg_param_req_this[] = {
63 NULL, /* in case of a "this" pointer, the first parameter must not be a float */
64 &ia32_default_req_ia32_floating_point_xmm0,
65 &ia32_default_req_ia32_floating_point_xmm1,
66 &ia32_default_req_ia32_floating_point_xmm2,
67 &ia32_default_req_ia32_floating_point_xmm3,
68 &ia32_default_req_ia32_floating_point_xmm4,
69 &ia32_default_req_ia32_floating_point_xmm5,
70 &ia32_default_req_ia32_floating_point_xmm6,
71 &ia32_default_req_ia32_floating_point_xmm7
76 /****************************************************************************************************
78 * | | | | / _| | | (_)
79 * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
80 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
81 * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
82 * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
84 ****************************************************************************************************/
88 /* determine if one operator is an Imm */
89 static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
91 return is_ia32_Const(op1) ? op1 : (is_ia32_Const(op2) ? op2 : NULL);
92 else return is_ia32_Const(op2) ? op2 : NULL;
95 /* determine if one operator is not an Imm */
96 static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
97 return !is_ia32_Const(op1) ? op1 : (!is_ia32_Const(op2) ? op2 : NULL);
103 * Creates an ia32 Add with immediate.
105 * @param dbg firm dbg
106 * @param block the block the new node should belong to
107 * @param expr_op operator
108 * @param mode node mode
109 * @return the created ia23 Add_i node
111 static ir_node *gen_imm_Add(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
113 tarval *tv = get_ia32_Immop_tarval(const_op);
115 tarval_classification_t class_tv, class_negtv;
117 /* const_op: tarval or SymConst? */
119 /* optimize tarvals */
120 class_tv = classify_tarval(tv);
121 class_negtv = classify_tarval(tarval_neg(tv));
123 if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
124 DBG((mod, LEVEL_2, "optimizing Add(1) to Inc ... "));
125 new_op = new_rd_ia32_Inc(dbg, current_ir_graph, block, expr_op, mode);
127 else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
128 DBG((mod, LEVEL_2, "optimizing Add(-1) to Dec ... "));
129 new_op = new_rd_ia32_Dec(dbg, current_ir_graph, block, expr_op, mode);
138 new_op = new_rd_ia32_Lea_i(dbg, current_ir_graph, block, expr_op, mode);
144 * Creates an ia32 Add.
146 * @param dbg firm node dbg
147 * @param block the block the new node should belong to
148 * @param op1 first operator
149 * @param op2 second operator
150 * @param mode node mode
151 * @return the created ia32 Add node
153 static ir_node *gen_Add(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
159 if (mode_is_float(mode)) {
160 return new_rd_ia32_fAdd(dbg, current_ir_graph, block, op1, op2, mode);
163 /* try to optimize with LEA */
165 shli_op = is_ia32_Shl_i(op1) ? op1 : (is_ia32_Shl_i(op2) ? op2 : NULL);
166 expr_op = shli_op == op1 ? op2 : (shli_op == op2 ? op1 : NULL);
169 tarval *tv = get_ia32_Immop_tarval(shli_op);
172 switch (get_tarval_long(tv)) {
176 // If the other operand of the LEA is an LEA_i (that means LEA ofs(%regop1)),
177 // we can skip it and transform the whole sequence into LEA ofs(%regop1, %regop2, shl_val),
178 if (is_ia32_Lea_i(expr_op)) {
179 offs = get_ia32_Immop_tarval(expr_op);
180 expr_op = get_irn_n(expr_op, 0);
183 new_op = new_rd_ia32_Lea(dbg, current_ir_graph, block, expr_op, get_irn_n(shli_op, 0), mode);
184 set_ia32_Immop_tarval(new_op, tv);
185 set_ia32_offs(new_op, offs);
200 new_op = new_rd_ia32_Lea(dbg, current_ir_graph, block, op1, op2, mode);
201 set_ia32_Immop_tarval(new_op, get_tarval_one(mode_Iu));
202 set_ia32_offs(new_op, NULL);
211 * Creates an ia32 Mul with immediate.
213 * @param dbg firm dbg
214 * @param block the block the new node should belong to
215 * @param expr_op operator
216 * @param mode node mode
217 * @return the created ia23 Mul_i node
219 static ir_node *gen_imm_Mul(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
220 return new_rd_ia32_Mul_i(dbg, current_ir_graph, block, expr_op, mode);
224 * Creates an ia32 Mul.
226 * @param dbg firm node dbg
227 * @param block the block the new node should belong to
228 * @param op1 first operator
229 * @param op2 second operator
230 * @param mode node mode
231 * @return the created ia32 Mul node
233 ir_node *gen_Mul(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
234 if (mode_is_float(mode)) {
235 return new_rd_ia32_fMul(dbg, current_ir_graph, block, op1, op2, mode);
237 return new_rd_ia32_Mul(dbg, current_ir_graph, block, op1, op2, mode);
243 * Creates an ia32 Mulh with immediate.
244 * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
245 * this result while Mul returns the lower 32 bit.
247 * @param dbg firm dbg
248 * @param block the block the new node should belong to
249 * @param expr_op operator
250 * @param mode node mode
251 * @return the created ia23 Mulh_i node
253 static ir_node *gen_imm_Mulh(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
254 return new_rd_ia32_Mulh_i(dbg, current_ir_graph, block, expr_op, mode);
258 * Creates an ia32 Mulh.
259 * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
260 * this result while Mul returns the lower 32 bit.
262 * @param dbg firm node dbg
263 * @param block the block the new node should belong to
264 * @param op1 first operator
265 * @param op2 second operator
266 * @param mode node mode
267 * @return the created ia32 Mulh node
269 static ir_node *gen_Mulh(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
270 return new_rd_ia32_Mulh(dbg, current_ir_graph, block, op1, op2, mode);
276 * Creates an ia32 And with immediate.
278 * @param dbg firm dbg
279 * @param block the block the new node should belong to
280 * @param expr_op operator
281 * @param mode node mode
282 * @return the created ia23 And_i node
284 static ir_node *gen_imm_And(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
285 return new_rd_ia32_And_i(dbg, current_ir_graph, block, expr_op, mode);
289 * Creates an ia32 And.
291 * @param dbg firm node dbg
292 * @param block the block the new node should belong to
293 * @param op1 first operator
294 * @param op2 second operator
295 * @param mode node mode
296 * @return the created ia32 And node
298 static ir_node *gen_And(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
299 return new_rd_ia32_And(dbg, current_ir_graph, block, op1, op2, mode);
305 * Creates an ia32 Or with immediate.
307 * @param dbg firm dbg
308 * @param block the block the new node should belong to
309 * @param expr_op operator
310 * @param mode node mode
311 * @return the created ia23 Or_i node
313 static ir_node *gen_imm_Or(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
314 return new_rd_ia32_Or_i(dbg, current_ir_graph, block, expr_op, mode);
318 * Creates an ia32 Or.
320 * @param dbg firm node dbg
321 * @param block the block the new node should belong to
322 * @param op1 first operator
323 * @param op2 second operator
324 * @param mode node mode
325 * @return the created ia32 Or node
327 static ir_node *gen_Or(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
328 return new_rd_ia32_Or(dbg, current_ir_graph, block, op1, op2, mode);
334 * Creates an ia32 Eor with immediate.
336 * @param dbg firm dbg
337 * @param block the block the new node should belong to
338 * @param expr_op operator
339 * @param mode node mode
340 * @return the created ia23 Eor_i node
342 static ir_node *gen_imm_Eor(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
343 return new_rd_ia32_Eor_i(dbg, current_ir_graph, block, expr_op, mode);
347 * Creates an ia32 Eor.
349 * @param dbg firm node dbg
350 * @param block the block the new node should belong to
351 * @param op1 first operator
352 * @param op2 second operator
353 * @param mode node mode
354 * @return the created ia32 Eor node
356 static ir_node *gen_Eor(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
357 return new_rd_ia32_Eor(dbg, current_ir_graph, block, op1, op2, mode);
363 * Creates an ia32 Max.
365 * @param dbg firm dbg
366 * @param block the block the new node should belong to
367 * @param expr_op operator
368 * @param mode node mode
369 * @return the created ia23 Max node
371 static ir_node *gen_Max(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
372 return new_rd_ia32_Max(dbg, current_ir_graph, block, op1, op2, mode);
378 * Creates an ia32 Min.
380 * @param dbg firm dbg
381 * @param block the block the new node should belong to
382 * @param expr_op operator
383 * @param mode node mode
384 * @return the created ia23 Min node
386 static ir_node *gen_Min(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
387 return new_rd_ia32_Min(dbg, current_ir_graph, block, op1, op2, mode);
393 * Creates an ia32 Sub with immediate.
395 * @param dbg firm dbg
396 * @param block the block the new node should belong to
397 * @param expr_op operator
398 * @param mode node mode
399 * @return the created ia23 Sub_i node
401 static ir_node *gen_imm_Sub(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
403 tarval *tv = get_ia32_Immop_tarval(const_op);
405 tarval_classification_t class_tv, class_negtv;
407 /* const_op: tarval or SymConst? */
409 /* optimize tarvals */
410 class_tv = classify_tarval(tv);
411 class_negtv = classify_tarval(tarval_neg(tv));
413 if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
414 DBG((mod, LEVEL_2, "optimizing Sub(1) to Dec ... "));
415 new_op = new_rd_ia32_Dec(dbg, current_ir_graph, block, expr_op, mode);
417 else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
418 DBG((mod, LEVEL_2, "optimizing Sub(-1) to Inc ... "));
419 new_op = new_rd_ia32_Inc(dbg, current_ir_graph, block, expr_op, mode);
428 new_op = new_rd_ia32_Sub_i(dbg, current_ir_graph, block, expr_op, mode);
434 * Creates an ia32 Sub.
436 * @param dbg firm node dbg
437 * @param block the block the new node should belong to
438 * @param op1 first operator
439 * @param op2 second operator
440 * @param mode node mode
441 * @return the created ia32 Sub node
443 static ir_node *gen_Sub(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
444 if (mode_is_float(mode)) {
445 return new_rd_ia32_fSub(dbg, current_ir_graph, block, op1, op2, mode);
447 return new_rd_ia32_Sub(dbg, current_ir_graph, block, op1, op2, mode);
453 * Creates an ia32 Mod.
455 * @param dbg firm node dbg
456 * @param block the block the new node should belong to
457 * @param op1 first operator
458 * @param op2 second operator
459 * @param mode node mode
460 * @return the created ia32 Mod node
462 static ir_node *gen_Mod(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *mem, ir_node *op1, ir_node *op2, ir_mode *mode) {
463 return new_rd_ia32_DivMod(dbg, current_ir_graph, block, op1, op2, mem, flavour_Mod, mode);
469 * Creates an ia32 Div.
471 * @param dbg firm node dbg
472 * @param block the block the new node should belong to
473 * @param op1 first operator
474 * @param op2 second operator
475 * @param mode node mode
476 * @return the created ia32 Div node
478 static ir_node *gen_Div(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *mem, ir_node *op1, ir_node *op2, ir_mode *mode) {
479 return new_rd_ia32_DivMod(dbg, current_ir_graph, block, op1, op2, mem, flavour_Div, mode);
485 * Creates an ia32 DivMod.
487 * @param dbg firm node dbg
488 * @param block the block the new node should belong to
489 * @param op1 first operator
490 * @param op2 second operator
491 * @param mode node mode
492 * @return the created ia32 DivMod node
494 static ir_node *gen_DivMod(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *mem, ir_node *op1, ir_node *op2, ir_mode *mode) {
495 return new_rd_ia32_DivMod(dbg, current_ir_graph, block, op1, op2, mem, flavour_DivMod, mode);
501 * Creates an ia32 floating Div.
503 * @param dbg firm node dbg
504 * @param block the block the new node should belong to
505 * @param op1 first operator
506 * @param op2 second operator
507 * @param mode node mode
508 * @return the created ia32 fDiv node
510 static ir_node *gen_Quot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
511 return new_rd_ia32_fDiv(dbg, current_ir_graph, block, op1, op2, mode);
517 * Creates an ia32 Shl with immediate.
519 * @param dbg firm dbg
520 * @param block the block the new node should belong to
521 * @param expr_op operator
522 * @param mode node mode
523 * @return the created ia23 Shl_i node
525 static ir_node *gen_imm_Shl(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
526 return new_rd_ia32_Shl_i(dbg, current_ir_graph, block, expr_op, mode);
530 * Creates an ia32 Shl.
532 * @param dbg firm node dbg
533 * @param block the block the new node should belong to
534 * @param op1 first operator
535 * @param op2 second operator
536 * @param mode node mode
537 * @return the created ia32 Shl node
539 static ir_node *gen_Shl(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
540 return new_rd_ia32_Shl(dbg, current_ir_graph, block, op1, op2, mode);
546 * Creates an ia32 Shr with immediate.
548 * @param dbg firm dbg
549 * @param block the block the new node should belong to
550 * @param expr_op operator
551 * @param mode node mode
552 * @return the created ia23 Shr_i node
554 static ir_node *gen_imm_Shr(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
555 return new_rd_ia32_Shr_i(dbg, current_ir_graph, block, expr_op, mode);
559 * Creates an ia32 Shr.
561 * @param dbg firm node dbg
562 * @param block the block the new node should belong to
563 * @param op1 first operator
564 * @param op2 second operator
565 * @param mode node mode
566 * @return the created ia32 Shr node
568 static ir_node *gen_Shr(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
569 return new_rd_ia32_Shr(dbg, current_ir_graph, block, op1, op2, mode);
575 * Creates an ia32 Shrs with immediate.
577 * @param dbg firm dbg
578 * @param block the block the new node should belong to
579 * @param expr_op operator
580 * @param mode node mode
581 * @return the created ia23 Shrs_i node
583 static ir_node *gen_imm_Shrs(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
584 return new_rd_ia32_Shrs_i(dbg, current_ir_graph, block, expr_op, mode);
588 * Creates an ia32 Shrs.
590 * @param dbg firm node dbg
591 * @param block the block the new node should belong to
592 * @param op1 first operator
593 * @param op2 second operator
594 * @param mode node mode
595 * @return the created ia32 Shrs node
597 static ir_node *gen_Shrs(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
598 return new_rd_ia32_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
604 * Creates an ia32 RotL.
606 * @param dbg firm node dbg
607 * @param block the block the new node should belong to
608 * @param op1 first operator
609 * @param op2 second operator
610 * @param mode node mode
611 * @return the created ia32 RotL node
613 static ir_node *gen_RotL(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
614 return new_rd_ia32_RotL(dbg, current_ir_graph, block, op1, op2, mode);
620 * Creates an ia32 RotR.
621 * NOTE: There is no RotR with immediate because this would always be a RotL
622 * "imm-mode_size_bits" which can be pre-calculated.
624 * @param dbg firm node dbg
625 * @param block the block the new node should belong to
626 * @param op1 first operator
627 * @param op2 second operator
628 * @param mode node mode
629 * @return the created ia32 RotR node
631 static ir_node *gen_RotR(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
632 return new_rd_ia32_RotR(dbg, current_ir_graph, block, op1, op2, mode);
638 * Transforms a Rot with immediate into an ia32 RotL with immediate
639 * as the Firm Rot is a RotL (see NOTE on RotR with immediate above).
641 * @param dbg firm node dbg
642 * @param block the block the new node should belong to
643 * @param op1 first operator
644 * @param op2 second operator
645 * @param mode node mode
646 * @return the created ia32 RotL node
648 static ir_node *gen_imm_Rot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
649 return new_rd_ia32_RotL_i(dbg, current_ir_graph, block, expr_op, mode);
653 * Creates an ia32 RotR or RotL (depending on the found pattern).
655 * @param dbg firm node dbg
656 * @param block the block the new node should belong to
657 * @param op1 first operator
658 * @param op2 second operator
659 * @param mode node mode
660 * @return the created ia32 RotL or RotR node
662 static ir_node *gen_Rot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
663 ir_node *rotate = NULL;
665 /* Firm has only Rot (which is a RotL), so we are looking for a right (op2)
666 operand "-e+mode_size_bits" (it's an already modified "mode_size_bits-e",
667 that means we can create a RotR instead of an Add and a RotL */
669 if (is_ia32_Add_i(op2)) {
670 ir_node *minus = get_irn_n(op2, 0); // is there an op_Minus?
672 if (is_ia32_Minus(minus)) {
673 tarval *tv = get_ia32_Immop_tarval(op2);
674 long bits = get_mode_size_bits(mode);
676 if (tarval_is_long(tv) && get_tarval_long(tv) == bits) {
677 DBG((mod, LEVEL_1, "optimizing RotL into RotR ... "));
678 rotate = gen_RotR(mod, dbg, block, op1, get_irn_n(minus, 0), mode);
684 rotate = gen_RotL(mod, dbg, block, op1, op2, mode);
692 * Transforms commutative operations (op_Add, op_Mul, op_And, op_Or, op_Eor)
693 * and non-commutative operations with com == 0 (op_Sub, op_Shl, op_Shr, op_Shrs, op_Rot)
695 * @param mod the debug module
696 * @param block the block node belongs to
697 * @param node the node to transform
698 * @param op1 first operator
699 * @param op2 second operator
700 * @param mode node mode
701 * @param com flag if op is commutative
702 * @return the created assembler node
704 static ir_node *gen_arith_Op(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op1, ir_node *op2, ir_mode *mode, int com) {
705 dbg_info *dbg = get_irn_dbg_info(node);
706 ir_node *imm_op = NULL;
707 ir_node *expr_op = NULL;
708 ir_node *asm_node = NULL;
709 opcode opc = get_irn_opcode(node);
710 ir_op *op = get_irn_op(node);
712 #define GENOP(a) case iro_##a: asm_node = gen_##a(mod, dbg, block, op1, op2, mode); break
713 #define GENOPI(a) case iro_##a: asm_node = gen_imm_##a(mod, dbg, block, expr_op, imm_op, mode); break
716 imm_op = get_immediate_op(op1, op2);
718 imm_op = get_immediate_op(NULL, op2);
720 expr_op = get_expr_op(op1, op2);
722 /* TODO: Op(Const, Const) support */
723 if (is_ia32_Const(op1) && is_ia32_Const(op2)) {
724 DBG((mod, LEVEL_2, "found unexpected %s(Const, Const), creating binop ... ", get_irn_opname(node)));
728 if (op == get_op_Min() || op == get_op_Max()) {
729 DBG((mod, LEVEL_2, "MIN/MAX imm not available, creating binop ... "));
733 DBG((mod, LEVEL_1, "(op1: %s -- op2: %s) ... ", get_irn_opname(op1), get_irn_opname(op2)));
735 if (!mode_is_float(mode) && imm_op) {
736 DBG((mod, LEVEL_1, "%s with imm ... ", get_irn_opname(node)));
751 if (op == get_op_Mulh()) {
752 asm_node = gen_imm_Mulh(mod, dbg, block, expr_op, imm_op, mode);
755 assert("binop_i: THIS SHOULD NOT HAPPEN");
758 set_ia32_Immop_attr(asm_node, imm_op);
761 DBG((mod, LEVEL_1, "%s as binop ... ", get_irn_opname(node)));
778 if (op == get_op_Mulh()) {
779 asm_node = gen_Mulh(mod, dbg, block, op1, op2, mode);
781 else if (op == get_op_Max()) {
782 asm_node = gen_Max(mod, dbg, block, op1, op2, mode);
784 else if (op == get_op_Min()) {
785 asm_node = gen_Min(mod, dbg, block, op1, op2, mode);
788 assert("binop: THIS SHOULD NOT HAPPEN");
798 * Transforms a Minus node.
800 * @param mod the debug module
801 * @param block the block the new node should belong to
802 * @param node the ir Minus node
804 * @param mode node mode
805 * @return the created ia32 Minus node
807 static ir_node *gen_Minus(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
808 if (is_ia32_Minus(op) || is_ia32_fMinus(op)) {
809 DBG((mod, LEVEL_1, "optimizing --(e) to e ..."));
810 return get_irn_n(op, 0);
813 if (mode_is_float(mode)) {
814 return new_rd_ia32_fMinus(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
816 return new_rd_ia32_Minus(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
823 * Transforms a Conv node.
825 * @param mod the debug module
826 * @param block the block the new node should belong to
827 * @param node the ir Conv node
829 * @param mode node mode
830 * @return the created ia32 Conv node
832 static ir_node *gen_Conv(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
833 return new_rd_ia32_Conv(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
839 * Transforms a Not node.
841 * @param mod the debug module
842 * @param block the block the new node should belong to
843 * @param node the ir Not node
845 * @param mode node mode
846 * @return the created ia32 Not node
848 static ir_node *gen_Not(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
849 return new_rd_ia32_Not(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
855 * Transforms an Abs node.
857 * @param mod the debug module
858 * @param block the block the new node should belong to
859 * @param node the ir Abs node
861 * @param mode node mode
862 * @return the created ia32 Abs node
864 static ir_node *gen_Abs(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
865 ir_node *res, *p_eax, *p_edx;
866 dbg_info *dbg = get_irn_dbg_info(node);
868 res = new_rd_ia32_Cltd(dbg, current_ir_graph, block, op, mode_T);
869 p_eax = new_rd_Proj(dbg, current_ir_graph, block, res, mode, pn_EAX);
870 p_edx = new_rd_Proj(dbg, current_ir_graph, block, res, mode, pn_EDX);
871 res = new_rd_ia32_Eor(dbg, current_ir_graph, block, p_eax, p_edx, mode);
872 res = new_rd_ia32_Sub(dbg, current_ir_graph, block, res, p_edx, mode);
882 * @param mod the debug module
883 * @param block the block the new node should belong to
884 * @param node the ir Load node
885 * @param mode node mode
886 * @return the created ia32 Load node
888 static ir_node *gen_Load(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
889 if (mode_is_float(mode)) {
890 return new_rd_ia32_fLoad(get_irn_dbg_info(node), current_ir_graph, block, get_Load_ptr(node), get_Load_mem(node), mode);
892 return new_rd_ia32_Load(get_irn_dbg_info(node), current_ir_graph, block, get_Load_ptr(node), get_Load_mem(node), mode);
898 * Transforms a Store.
900 * @param mod the debug module
901 * @param block the block the new node should belong to
902 * @param node the ir Store node
903 * @param mode node mode
904 * @return the created ia32 Store node
906 ir_node *gen_Store(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
907 if (mode_is_float(mode)) {
908 return new_rd_ia32_fStore(get_irn_dbg_info(node), current_ir_graph, block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), mode);
910 return new_rd_ia32_Store(get_irn_dbg_info(node), current_ir_graph, block, get_Store_ptr(node), get_Store_value(node), get_Store_mem(node), mode);
916 * Check all parameters and determine the maximum number of parameters
917 * to pass in gp regs resp. in fp regs.
919 static void get_n_regparam_class(int n, ir_node **param, int *n_int, int *n_float) {
922 for (i = 0; i < n; i++) {
923 if (mode_is_int(get_irn_mode(param[i])))
925 else if (mode_is_float(get_irn_mode(param[i])))
926 *n_float = *n_float + 1;
928 /* test for maximum */
929 if (*n_int == maxnum_gpreg_args)
932 if (*n_float == maxnum_fpreg_args)
938 * Transforms a Call and its arguments corresponding to the calling convention.
940 * @param mod the debug module
941 * @param block the block the new node should belong to
942 * @param node the ir Call node
943 * @param dummy mode doesn't matter
944 * @return the created ia32 Call node
946 static ir_node *gen_Call(firm_dbg_module_t *mod, ir_node *block, ir_node *call, ir_mode *dummy) {
947 const arch_register_req_t **in_req;
949 ir_node *new_call, *sync;
951 int i, j, n_new_call_in;
953 ir_node **stack_param = NULL;
954 ir_node **param = get_Call_param_arr(call);
955 ir_node *call_Mem = get_Call_mem(call);
956 unsigned cc = get_method_calling_convention(get_Call_type(call));
957 int n = get_Call_n_params(call);
958 int n_gpregparam = 0;
959 int n_fpregparam = 0;
965 if (cc & cc_reg_param)
966 get_n_regparam_class(n, param, &n_gpregparam, &n_fpregparam);
968 /* do we need to pass arguments on stack? */
969 if (n - n_gpregparam - n_fpregparam > 0)
970 stack_param = calloc(n - n_gpregparam - n_fpregparam, sizeof(ir_node *));
972 /* we need at least one in, either for the stack params or the call_Mem */
973 n_new_call_in = 1 + n_gpregparam + n_fpregparam;
975 current_gpreg_param_req = gpreg_param_req_std;
976 current_fpreg_param_req = fpreg_param_req_std;
978 if (cc & cc_this_call) {
979 current_gpreg_param_req = gpreg_param_req_this;
980 current_fpreg_param_req = fpreg_param_req_this;
983 /* the call has one IN for all stack parameter and one IN for each reg param */
984 in = calloc(n_new_call_in, sizeof(ir_node *));
985 in_req = calloc(n_new_call_in, sizeof(arch_register_req_t *));
987 /* loop over all parameters and determine whether its a int or float register parameter */
988 for (i = 0; i < n && !done && (cc & cc_reg_param); i++) {
989 mode = get_irn_mode(param[i]);
991 if (mode_is_int(mode) && cur_gp_idx < maxnum_gpreg_args) {
992 /* param can be passed in general purpose register and we have some registers left */
993 in[cur_gp_idx + cur_fp_idx] = param[i];
994 in_req[cur_gp_idx] = current_gpreg_param_req[cur_gp_idx];
997 else if (mode_is_float(mode) && cur_fp_idx < maxnum_fpreg_args) {
998 /* param can be passed in floating point register and we have some registers left */
999 assert(current_gpreg_param_req[cur_fp_idx] && "'this' pointer cannot be passed as float");
1000 in[cur_gp_idx + cur_fp_idx] = param[i];
1001 in_req[cur_fp_idx] = current_gpreg_param_req[cur_fp_idx];
1005 /* maximum number of register parameters in one class reached? */
1006 if (cur_gp_idx >= maxnum_gpreg_args || cur_fp_idx >= maxnum_fpreg_args) {
1012 /* create remaining stack parameters */
1013 if (cc & cc_last_on_top) {
1014 for (i = stack_idx; i < n; i++) {
1015 /* pass it on stack */
1016 if (mode_is_float(get_irn_mode(param[i]))) {
1017 stack_param[i] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), current_ir_graph,
1018 block, call_Mem, param[i], mode_M);
1021 stack_param[i] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), current_ir_graph,
1022 block, call_Mem, param[i], mode_M);
1027 for (i = n - 1, j = stack_idx; i >= stack_idx; i--, j++) {
1028 /* pass it on stack */
1029 if (mode_is_float(get_irn_mode(param[i]))) {
1030 stack_param[i] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), current_ir_graph,
1031 block, call_Mem, param[i], mode_M);
1034 stack_param[i] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), current_ir_graph,
1035 block, call_Mem, param[i], mode_M);
1041 sync = new_r_Sync(current_ir_graph, block, n - n_gpregparam - n_fpregparam, stack_param);
1042 in[n_new_call_in - 1] = sync;
1045 in[n_new_call_in - 1] = call_Mem;
1048 /* create the new node */
1049 new_call = new_rd_ia32_Call(get_irn_dbg_info(call), current_ir_graph, block, n_new_call_in, in);
1050 set_ia32_Immop_attr(new_call, get_Call_ptr(call));
1051 set_ia32_n_res(new_call, 1);
1053 /* set register requirements for in and out */
1054 attr = get_ia32_attr(new_call);
1055 attr->in_req = in_req;
1056 attr->out_req = calloc(1, sizeof(arch_register_req_t *));
1057 attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax;
1058 attr->slots = calloc(1, sizeof(arch_register_t *));
1060 /* stack parameter has no OUT register */
1061 attr->in_req[n_new_call_in - 1] = &ia32_default_req_none;
1069 * creates a unique ident by adding a number to a tag
1071 * @param tag the tag string, must contain a %d if a number
1074 static ident *unique_id(const char *tag)
1076 static unsigned id = 0;
1079 snprintf(str, sizeof(str), tag, ++id);
1080 return new_id_from_str(str);
1084 * Transforms a SymConst.
1086 * @param mod the debug module
1087 * @param block the block the new node should belong to
1088 * @param node the ir SymConst node
1089 * @param mode mode of the SymConst
1090 * @return the created ia32 Const node
1092 static ir_node *gen_SymConst(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
1095 if (mode_is_float(mode)) {
1096 cnst = new_rd_ia32_fConst(get_irn_dbg_info(node), current_ir_graph, block, mode);
1100 cnst = new_rd_ia32_Const(get_irn_dbg_info(node), current_ir_graph, block, mode);
1103 set_ia32_Const_attr(cnst, node);
1108 * Transforms a Const.
1110 * @param mod the debug module
1111 * @param block the block the new node should belong to
1112 * @param node the ir Const node
1113 * @param mode mode of the Const
1114 * @return the created ia32 Const node
1116 static ir_node *gen_Const(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
1120 symconst_symbol sym;
1122 if (mode_is_float(mode)) {
1123 tp = get_Const_type(node);
1124 if (tp == firm_unknown_type) {
1125 tp = new_type_primitive(unique_id("tp_ia32_float_%u"), mode);
1128 ent = new_entity(get_glob_type(), unique_id("ia32FloatCnst_%u"), tp);
1130 set_entity_ld_ident(ent, get_entity_ident(ent));
1131 set_entity_visibility(ent, visibility_local);
1132 set_entity_variability(ent, variability_constant);
1133 set_entity_allocation(ent, allocation_static);
1135 set_atomic_ent_value(ent, node);
1139 cnst = new_rd_SymConst(get_irn_dbg_info(node), current_ir_graph, block, sym, symconst_addr_ent);
1140 cnst = gen_SymConst(mod, block, cnst, mode);
1143 cnst = new_rd_ia32_Const(get_irn_dbg_info(node), current_ir_graph, block, mode);
1144 set_ia32_Const_attr(cnst, node);
1153 * Transforms a Cond -> Proj[b] -> Cmp into a CondJmp or CondJmp_i
1155 * @param mod the debug module
1156 * @param block the block the new node should belong to
1157 * @param node the ir Cond node
1158 * @param mode mode of the Cond
1159 * @return The transformed node.
1161 static ir_node *gen_Cond(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
1162 ir_node *sel = get_Cond_selector(node);
1163 ir_mode *sel_mode = get_irn_mode(sel);
1164 ir_node *res = NULL;
1165 ir_node *pred = NULL;
1166 ir_node *cmp_a, *cmp_b, *cnst, *expr;
1168 if (is_Proj(sel) && sel_mode == mode_b) {
1169 pred = get_Proj_pred(sel);
1171 /* get both compare operators */
1172 cmp_a = get_Cmp_left(pred);
1173 cmp_b = get_Cmp_right(pred);
1175 /* check if we can use a CondJmp with immediate */
1176 cnst = get_immediate_op(cmp_a, cmp_b);
1177 expr = get_expr_op(cmp_a, cmp_b);
1180 res = new_rd_ia32_CondJmp_i(get_irn_dbg_info(node), current_ir_graph, block, expr, mode_T);
1181 set_ia32_Immop_attr(res, cnst);
1184 res = new_rd_ia32_CondJmp(get_irn_dbg_info(node), current_ir_graph, block, cmp_a, cmp_b, mode_T);
1187 set_ia32_pncode(res, get_Proj_proj(sel));
1190 res = new_rd_ia32_SwitchJmp(get_irn_dbg_info(node), current_ir_graph, block, sel, mode_T);
1191 set_ia32_pncode(res, get_Cond_defaultProj(node));
1200 * Transform the argument projs from a start node corresponding to the
1201 * calling convention.
1202 * It transforms "Proj Arg x -> ProjT -> Start <- ProjM" into
1203 * "RegParam x -> ProjT -> Start" OR
1204 * "StackParam x -> ProjM -> Start"
1205 * whether parameter is passed in register or on stack.
1207 * @param mod the debug module
1208 * @param block the block the nodes should belong to
1209 * @param proj the ProjT node which points to Start
1210 * @param start the Start node
1211 * @return Should be always NULL
1213 static ir_node *gen_Proj_Start(firm_dbg_module_t *mod, ir_node *block, ir_node *proj, ir_node *start) {
1214 const ir_edge_t *edge;
1215 ir_node *succ, *irn;
1220 ir_node *proj_M = get_irg_initial_mem(current_ir_graph);
1221 entity *irg_ent = get_irg_entity(current_ir_graph);
1222 type *tp = get_entity_type(irg_ent);
1228 assert(is_Method_type(tp) && "irg type is not a method");
1230 switch(get_Proj_proj(proj)) {
1231 case pn_Start_T_args:
1232 /* We cannot use get_method_n_params here as the function might
1233 be variadic or one argument is not used. */
1234 n = get_irn_n_edges(proj);
1236 /* we are done here when there are no parameters */
1240 /* temporary remember all proj arg x */
1241 projargs = calloc(n, sizeof(ir_node *));
1243 foreach_out_edge((const ir_node *)proj, edge) {
1244 succ = get_edge_src_irn(edge);
1245 assert(is_Proj(succ) && "non-Proj from a Proj_T (pn_Start_T_args).");
1246 projargs[get_Proj_proj(succ)] = succ;
1249 cc = get_method_calling_convention(tp);
1251 /* get the correct order in case of 'this' call */
1252 current_gpreg_param_req = gpreg_param_req_std;
1253 current_fpreg_param_req = fpreg_param_req_std;
1254 if (cc & cc_this_call) {
1255 current_gpreg_param_req = gpreg_param_req_this;
1256 current_fpreg_param_req = fpreg_param_req_this;
1259 /* loop over all parameters and check whether its a int or float */
1260 for (i = 0; i < n && !done && (cc & cc_reg_param); i++) {
1261 mode = get_irn_mode(projargs[i]);
1263 if (mode_is_int(mode) && cur_gp_idx < maxnum_gpreg_args) {
1264 /* parameter got passed in general purpose register */
1265 irn = new_rd_ia32_RegParam(get_irn_dbg_info(proj), current_ir_graph, block, proj, mode);
1266 set_ia32_pncode(irn, i);
1267 set_ia32_regreq_out(irn, current_gpreg_param_req[cur_gp_idx], 0);
1270 else if (mode_is_float(mode) && cur_fp_idx < maxnum_fpreg_args) {
1271 /* parameter got passed in floating point register*/
1272 irn = new_rd_ia32_RegParam(get_irn_dbg_info(proj), current_ir_graph, block, proj, mode);
1273 set_ia32_pncode(irn, i);
1274 set_ia32_regreq_out(irn, current_fpreg_param_req[cur_fp_idx], 0);
1278 /* kill the old "Proj Arg" and replace with the new Arg */
1279 exchange(projargs[i], irn);
1281 if (cur_gp_idx >= maxnum_gpreg_args || cur_fp_idx >= maxnum_fpreg_args) {
1287 /* create all remaining stack parameters */
1288 if (cc & cc_last_on_top) {
1289 for (i = stack_idx; i < n; i++) {
1290 mode = get_irn_mode(projargs[i]);
1292 if (mode_is_float(mode))
1293 irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
1295 irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
1297 set_ia32_pncode(irn, i);
1299 /* kill the old "Proj Arg" and replace with the new stack param */
1300 exchange(projargs[i], irn);
1304 for (i = n - 1, j = stack_idx; i >= stack_idx; i--, j++) {
1305 mode = get_irn_mode(projargs[i]);
1307 if (mode_is_float(mode))
1308 irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
1310 irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), current_ir_graph, block, proj_M, mode);
1312 set_ia32_pncode(irn, j);
1314 /* kill the old "Proj Arg" and replace with the new stack param */
1315 exchange(projargs[i], irn);
1322 case pn_Start_X_initial_exec:
1324 case pn_Start_P_frame_base:
1325 case pn_Start_P_globals:
1326 case pn_Start_P_value_arg_base:
1329 assert(0 && "unsupported Proj(Start)");
1336 * Transform some Proj's (Proj_Proj, Proj_Start, Proj_Cmp, Proj_Cond, Proj_Call).
1337 * All others are ignored.
1339 * @param mod the debug module
1340 * @param block the block the new node should belong to
1341 * @param node the ir Proj node
1342 * @param mode mode of the Proj
1343 * @return The transformed node.
1345 static ir_node *gen_Proj(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
1346 ir_node *new_node = NULL;
1347 ir_node *pred = get_Proj_pred(node);
1352 if (get_irn_op(pred) == op_Start) {
1353 new_node = gen_Proj_Start(mod, block, node, pred);
1361 /*********************************************************
1364 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
1365 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
1366 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
1367 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
1369 *********************************************************/
1374 * Transforms the given firm node (and maybe some other related nodes)
1375 * into one or more assembler nodes.
1377 * @param node the firm node
1378 * @param env the debug module
1380 void ia32_transform_node(ir_node *node, void *env) {
1381 firm_dbg_module_t *mod = (firm_dbg_module_t *)env;
1382 opcode code = get_irn_opcode(node);
1383 ir_node *asm_node = NULL;
1390 block = get_nodes_block(node);
1391 mode = get_irn_mode(node);
1393 #define BINOP_COM(a) case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 1); break
1394 #define BINOP_NCOM(a) case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 0); break
1395 #define TRIOP(a) case iro_##a: asm_node = gen_##a(mod, get_irn_dbg_info(node), block, get_irn_n(node, 0), get_irn_n(node, 1), get_irn_n(node, 2), mode); break
1396 #define UNOP(a) case iro_##a: asm_node = gen_##a(mod, block, node, get_irn_n(node, 0), mode); break
1397 #define GEN(a) case iro_##a: asm_node = gen_##a(mod, block, node, mode); break
1398 #define IGN(a) case iro_##a: break
1399 #define BAD(a) case iro_##a: goto bad
1401 DBG((mod, LEVEL_1, "transforming node %s (%ld) ... ", get_irn_opname(node), get_irn_node_nr(node)));
1462 if (get_irn_op(node) == get_op_Mulh() ||
1463 get_irn_op(node) == get_op_Max() ||
1464 get_irn_op(node) == get_op_Min())
1466 asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 1);
1470 fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node));
1475 exchange(node, asm_node);
1476 DBG((mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
1479 DBG((mod, LEVEL_1, "ignored\n"));