register allocator interface implemented
[libfirm] / ir / be / ia32 / ia32_emitter.c
1 #include "tv.h"
2 #include "iredges.h"
3 #include "ia32_emitter.h"
4 #include "ia32_nodes_attr.h"
5 #include "ia32_new_nodes.h"
6
7 #define TARVAL_SNPRINTF_BUF_LEN 1024
8
9 const char *get_dest_reg_name(ir_node *n, int num) {
10   return get_ia32_out_reg_name(n, --num);
11 }
12
13 const char *get_source_reg_name(ir_node *n, int num) {
14   return get_ia32_in_reg_name(n, --num);
15 }
16
17 char *node_const_to_str(ir_node *n) {
18   char *buf = malloc(TARVAL_SNPRINTF_BUF_LEN);
19   tarval_snprintf(buf, TARVAL_SNPRINTF_BUF_LEN, get_ia32_Immop_tarval(n));
20   return buf;
21 }
22
23 char *node_offset_to_str(ir_node *n) {
24   char *buf = malloc(TARVAL_SNPRINTF_BUF_LEN);
25   tarval_snprintf(buf, TARVAL_SNPRINTF_BUF_LEN, get_ia32_offs(n));
26   return buf;
27 }
28
29 void equalize_dest_src(FILE *F, ir_node *n) {
30   if (get_ia32_out_regnr(n, 0) != get_ia32_in_regnr(n, 0))
31     fprintf(F, "\tmovl %%%s, %%%s\t\t\t/* src -> dest for 2 address code */\n", get_source_reg_name(n, 1), get_dest_reg_name(n, 1));
32 }
33
34 /*
35  * coding of conditions
36  */
37 struct cmp2conditon_t {
38   const char *name;
39   pn_Cmp      num;
40 };
41
42 /*
43  * positive conditions for signed compares
44  */
45 static const struct cmp2conditon_t cmp2condition_s[] = {
46   { NULL,              pn_Cmp_False },  /* always false */
47   { "e",               pn_Cmp_Eq },     /* == */
48   { "l",               pn_Cmp_Lt },     /* < */
49   { "le",              pn_Cmp_Le },     /* <= */
50   { "g",               pn_Cmp_Gt },     /* > */
51   { "ge",              pn_Cmp_Ge },     /* >= */
52   { "ne",              pn_Cmp_Lg },     /* != */
53   { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
54   { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
55   { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
56   { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
57   { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
58   { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
59   { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
60   { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
61   { NULL,              pn_Cmp_True },   /* always true */
62 };
63
64 /*
65  * positive conditions for unsigned compares
66  */
67 static const struct cmp2conditon_t cmp2condition_u[] = {
68   { NULL,              pn_Cmp_False },  /* always false */
69   { "e",               pn_Cmp_Eq },     /* == */
70   { "b",               pn_Cmp_Lt },     /* < */
71   { "be",              pn_Cmp_Le },     /* <= */
72   { "a",               pn_Cmp_Gt },     /* > */
73   { "ae",              pn_Cmp_Ge },     /* >= */
74   { "ne",              pn_Cmp_Lg },     /* != */
75   { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
76   { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
77   { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
78   { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
79   { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
80   { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
81   { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
82   { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
83   { NULL,              pn_Cmp_True },   /* always true */
84 };
85
86 /*
87  * returns the condition code
88  */
89 const char *get_cmp_suffix(int cmp_code, int unsigned_cmp)
90 {
91   assert(cmp2condition_s[cmp_code].num == cmp_code);
92   assert(cmp2condition_u[cmp_code].num == cmp_code);
93
94   return unsigned_cmp ? cmp2condition_u[cmp_code & 7].name : cmp2condition_s[cmp_code & 7].name;
95 }
96
97 void emit_ia32_Proj_Cond(FILE *F, ir_node *n, ir_node *cond) {
98   ir_node *succ_block = get_edge_src_irn(get_irn_out_edge_first(n));
99   ir_node *sel        = get_Cond_selector(cond);
100   ir_mode *sel_mode   = get_irn_mode(sel);
101
102   assert(succ_block && "Target block of Proj_Cond missing!");
103
104   if (sel_mode == mode_b) { // Boolean condition
105     int label = get_irn_node_nr(succ_block);
106     int nr    = get_Proj_proj(n);
107     fprintf(F, "j%s%s Label%d\t\t\t/* if (%sCond) goto Label */\n",
108           nr == pn_Cond_true ? "" : "n",
109           get_cmp_suffix(get_Proj_proj(sel), mode_is_signed(sel_mode)),
110           label,
111           nr == pn_Cond_true ? "" : "!");
112   }
113 }