2 * Register mapping for firm nodes. Stolen from bearch_firm :)
11 #include "ia32_map_regs.h"
12 #include "ia32_new_nodes.h"
13 #include "gen_ia32_regalloc_if.h"
15 static int maxnum_gpreg_args = 3; /* maximum number of int arguments passed in registers; default 3 */
16 static int maxnum_fpreg_args = 5; /* maximum number of float arguments passed in registers; default 5 */
18 /* this is the order of the assigned registers usesd for parameter passing */
20 const ia32_register_req_t *gpreg_param_req_std[] = {
21 &ia32_default_req_ia32_general_purpose_eax,
22 &ia32_default_req_ia32_general_purpose_ecx,
23 &ia32_default_req_ia32_general_purpose_edx,
24 &ia32_default_req_ia32_general_purpose_ebx,
25 &ia32_default_req_ia32_general_purpose_edi,
26 &ia32_default_req_ia32_general_purpose_esi
29 const ia32_register_req_t *gpreg_param_req_this[] = {
30 &ia32_default_req_ia32_general_purpose_ecx,
31 &ia32_default_req_ia32_general_purpose_eax,
32 &ia32_default_req_ia32_general_purpose_edx,
33 &ia32_default_req_ia32_general_purpose_ebx,
34 &ia32_default_req_ia32_general_purpose_edi,
35 &ia32_default_req_ia32_general_purpose_esi
38 const ia32_register_req_t *fpreg_param_req_std[] = {
39 &ia32_default_req_ia32_floating_point_xmm0,
40 &ia32_default_req_ia32_floating_point_xmm1,
41 &ia32_default_req_ia32_floating_point_xmm2,
42 &ia32_default_req_ia32_floating_point_xmm3,
43 &ia32_default_req_ia32_floating_point_xmm4,
44 &ia32_default_req_ia32_floating_point_xmm5,
45 &ia32_default_req_ia32_floating_point_xmm6,
46 &ia32_default_req_ia32_floating_point_xmm7
49 const ia32_register_req_t *fpreg_param_req_this[] = {
50 NULL, /* in case of a "this" pointer, the first parameter must not be a float */
51 &ia32_default_req_ia32_floating_point_xmm0,
52 &ia32_default_req_ia32_floating_point_xmm1,
53 &ia32_default_req_ia32_floating_point_xmm2,
54 &ia32_default_req_ia32_floating_point_xmm3,
55 &ia32_default_req_ia32_floating_point_xmm4,
56 &ia32_default_req_ia32_floating_point_xmm5,
57 &ia32_default_req_ia32_floating_point_xmm6,
58 &ia32_default_req_ia32_floating_point_xmm7
63 /* Mapping to store registers in firm nodes */
65 struct ia32_irn_reg_assoc {
67 const arch_register_t *reg;
70 int ia32_cmp_irn_reg_assoc(const void *a, const void *b, size_t len) {
71 const struct ia32_irn_reg_assoc *x = a;
72 const struct ia32_irn_reg_assoc *y = b;
74 return x->irn != y->irn;
77 static struct ia32_irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, set *reg_set) {
78 struct ia32_irn_reg_assoc templ;
85 return set_insert(reg_set, &templ, sizeof(templ), hash);
88 void ia32_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set) {
89 struct ia32_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
93 const arch_register_t *ia32_get_firm_reg(const ir_node *irn, set *reg_set) {
94 struct ia32_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
100 /* Mapping to store proj numbers for registers */
102 struct ia32_reg_projnum_assoc {
103 const arch_register_t *reg;
107 int ia32_cmp_reg_projnum_assoc(const void *a, const void *b, size_t len) {
108 const struct ia32_reg_projnum_assoc *x = a;
109 const struct ia32_reg_projnum_assoc *y = b;
111 return !(x->reg == y->reg);
114 static struct ia32_reg_projnum_assoc *get_reg_projnum_assoc(const arch_register_t *reg, set *reg_set) {
115 struct ia32_reg_projnum_assoc templ;
120 hash = HASH_PTR(reg);
122 return set_insert(reg_set, &templ, sizeof(templ), hash);
125 void ia32_set_reg_projnum(const arch_register_t *reg, long proj_num, set *reg_set) {
126 struct ia32_reg_projnum_assoc *assoc = get_reg_projnum_assoc(reg, reg_set);
127 assoc->proj_num = proj_num;
130 long ia32_get_reg_projnum(const arch_register_t *reg, set *reg_set) {
131 struct ia32_reg_projnum_assoc *assoc = get_reg_projnum_assoc(reg, reg_set);
132 return assoc->proj_num;
138 * Check all parameters and determine the maximum number of parameters
139 * to pass in gp regs resp. in fp regs.
141 * @param n The number of parameters
142 * @param modes The parameter list
143 * @param n_int Holds the number of int parameters to be passed in regs after the call
144 * @param n_float Holds the number of float parameters to be passed in regs after the call
145 * @return The number of the last parameter to be passed in register
147 int ia32_get_n_regparam_class(int n, ir_node **params, int *n_int, int *n_float) {
150 for (i = 0; i < n && !finished; i++) {
151 if (mode_is_int(get_irn_mode(params[i]))) {
154 else if (mode_is_float(get_irn_mode(params[i]))) {
155 *n_float = *n_float + 1;
161 /* test for maximum */
162 if (*n_int == maxnum_gpreg_args || *n_float == maxnum_fpreg_args) {
172 * Returns the register requirements for parameter nr.
174 * @param n The number of parameters
175 * @param modes The parameter list
176 * @param nr The number of the parameter to return the requirements for
177 * @param cc The calling convention
178 * @return The register requirements
180 const ia32_register_req_t *ia32_get_RegParam_req(int n, ir_node **params, long nr, unsigned cc) {
181 const ia32_register_req_t **current_gpreg_param_req;
182 const ia32_register_req_t **current_fpreg_param_req;
183 const ia32_register_req_t *param_req = NULL;
184 int n_gpregparam = 0;
185 int n_fpregparam = 0;
189 int biggest_n = ia32_get_n_regparam_class(n, params, &n_gpregparam, &n_fpregparam);
191 /* Check if parameter #nr is in range for passing in register */
192 if (nr <= biggest_n) {
193 current_gpreg_param_req = gpreg_param_req_std;
194 current_fpreg_param_req = fpreg_param_req_std;
196 if (cc & cc_this_call) {
197 current_gpreg_param_req = gpreg_param_req_this;
198 current_fpreg_param_req = fpreg_param_req_this;
201 /* loop over all parameters and determine whether its a int or float register parameter */
202 for (i = 0; i < nr && !done && (cc & cc_reg_param); i++) {
203 if (mode_is_int(get_irn_mode(params[i])) && cur_gp_idx < maxnum_gpreg_args) {
204 /* param can be passed in general purpose register and we have some registers left */
207 else if (mode_is_float(get_irn_mode(params[i])) && cur_fp_idx < maxnum_fpreg_args) {
208 /* param can be passed in floating point register and we have some registers left */
209 assert(current_gpreg_param_req[cur_fp_idx] && "'this' pointer cannot be passed as float");
214 /* now: i == nr, that's the parameter requirement we want */
215 if (mode_is_int(get_irn_mode(params[i])) && cur_gp_idx < maxnum_gpreg_args) {
216 /* parameter #nr can be passed in general purpose register */
217 param_req = current_gpreg_param_req[i];
219 else if (mode_is_float(get_irn_mode(params[i])) && cur_fp_idx < maxnum_fpreg_args) {
220 /* parameter #nr can be passed in floating point register */
221 param_req = current_fpreg_param_req[i];
224 assert(0 && "This should not happen!");
234 * Translates the projnum into a "real" argument position for register
235 * requirements dependend on the predecessor.
237 long ia32_translate_proj_pos(const ir_node *proj) {
239 ir_node *pred = get_Proj_pred(proj);
240 long nr = get_Proj_proj(proj);
242 if (is_ia32_Load(pred)) {
243 if (nr == pn_Load_res)
245 assert(0 && "unsupported Proj(Load) number");
247 else if (is_ia32_Store(pred)) {
250 else if (is_ia32_CondJmp(pred) || is_ia32_CondJmp_i(pred)) {
253 else if (is_ia32_SwitchJmp(pred)) {
256 else if (is_ia32_Cltd(pred) || is_ia32_Mul(pred)) {
262 else if (is_ia32_DivMod(pred)) {
263 if (nr == pn_DivMod_res_div || pn_Div_res)
265 if (nr == pn_DivMod_res_mod || pn_Mod_res)
268 else if (is_ia32_Call(pred)) {
271 else if (get_irn_mode(proj) == mode_X && nr == pn_Start_X_initial_exec) {
274 else if (is_Proj(pred)) {
275 first = get_Proj_pred(pred);
277 if (is_ia32_Call(first))
280 assert(0 && "unsupported proj-pos translation Proj(Proj)");
283 else if (get_irn_opcode(pred) == iro_Start) {
287 // assert(0 && "unsupported Proj(X)");