added call-projnum-requirement magic
[libfirm] / ir / be / ia32 / ia32_map_regs.c
1 /**
2  * Register mapping for firm nodes. Stolen from bearch_firm :)
3  * $Id$
4  */
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif
8
9 #include <stdlib.h>
10
11 #include "ia32_map_regs.h"
12 #include "ia32_new_nodes.h"
13
14
15 /* Mapping to store registers in firm nodes */
16
17 struct ia32_irn_reg_assoc {
18         const ir_node *irn;
19         const arch_register_t *reg;
20 };
21
22 int ia32_cmp_irn_reg_assoc(const void *a, const void *b, size_t len) {
23         const struct ia32_irn_reg_assoc *x = a;
24         const struct ia32_irn_reg_assoc *y = b;
25
26         return !(x->irn == y->irn);
27 }
28
29 static struct ia32_irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, set *reg_set) {
30         struct ia32_irn_reg_assoc templ;
31         unsigned int hash;
32
33         templ.irn = irn;
34         templ.reg = NULL;
35         hash = HASH_PTR(irn);
36
37         return set_insert(reg_set, &templ, sizeof(templ), hash);
38 }
39
40 void ia32_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set) {
41         struct ia32_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
42         assoc->reg = reg;
43 }
44
45 const arch_register_t *ia32_get_firm_reg(const ir_node *irn, set *reg_set) {
46         struct ia32_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
47         return assoc->reg;
48 }
49
50
51
52 /* Mapping to store proj numbers for registers */
53
54 struct ia32_reg_projnum_assoc {
55         const arch_register_t *reg;
56         long                   proj_num;
57 };
58
59 int ia32_cmp_reg_projnum_assoc(const void *a, const void *b, size_t len) {
60         const struct ia32_reg_projnum_assoc *x = a;
61         const struct ia32_reg_projnum_assoc *y = b;
62
63         return !(x->reg == y->reg);
64 }
65
66 static struct ia32_reg_projnum_assoc *get_reg_projnum_assoc(const arch_register_t *reg, set *reg_set) {
67         struct ia32_reg_projnum_assoc templ;
68         unsigned int hash;
69
70         templ.reg      = reg;
71         templ.proj_num = -1;
72         hash = HASH_PTR(reg);
73
74         return set_insert(reg_set, &templ, sizeof(templ), hash);
75 }
76
77 void ia32_set_reg_projnum(const arch_register_t *reg, long proj_num, set *reg_set) {
78         struct ia32_reg_projnum_assoc *assoc = get_reg_projnum_assoc(reg, reg_set);
79         assoc->proj_num = proj_num;
80 }
81
82 long ia32_get_reg_projnum(const arch_register_t *reg, set *reg_set) {
83         struct ia32_reg_projnum_assoc *assoc = get_reg_projnum_assoc(reg, reg_set);
84         return assoc->proj_num;
85 }
86
87
88
89 /**
90  * Translates the projnum into a "real" argument position for register
91  * requirements dependend on the predecessor.
92  */
93 long ia32_translate_proj_pos(const ir_node *proj) {
94         ir_node *first;
95         ir_node *pred = get_Proj_pred(proj);
96         long nr       = get_Proj_proj(proj);
97
98         if (is_ia32_Load(pred)) {
99                 if (nr == pn_Load_res)
100                         return 0;
101                 assert(0 && "unsupported Proj(Load) number");
102         }
103         else if (is_ia32_Store(pred)) {
104                 return 0;
105         }
106         else if (is_ia32_CondJmp(pred) || is_ia32_CondJmp_i(pred)) {
107                 return 0;
108         }
109         else if (is_ia32_SwitchJmp(pred)) {
110                 return 0;
111         }
112         else if (is_ia32_Cltd(pred) || is_ia32_Mul(pred)) {
113                 if (nr == pn_EAX)
114                         return 0;
115                 if (nr == pn_EDX)
116                         return 1;
117         }
118         else if (is_ia32_DivMod(pred)) {
119                 if (nr == pn_DivMod_res_div || pn_Div_res)
120                         return 0;
121                 if (nr == pn_DivMod_res_mod || pn_Mod_res)
122                         return 1;
123         }
124         else if (is_ia32_Call(pred)) {
125                 return 0;
126         }
127         else if (get_irn_mode(proj) == mode_X && nr == pn_Start_X_initial_exec) {
128                 return 0;
129         }
130         else if (is_Proj(pred)) {
131 //              return nr + translate_proj_pos(pred);
132                 first = get_Proj_pred(pred);
133
134                 if (is_ia32_Call(first))
135                         return 0;
136
137                 assert(0 && "unsupported proj-pos translation Proj(Proj)");
138                 return -1;
139         }
140         else if (get_irn_opcode(pred) == iro_Start) {
141                 return nr;
142         }
143
144 //      assert(0 && "unsupported Proj(X)");
145         return nr;
146 }